1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-15 01:24:45 +02:00

Implement async requests for bonus types

This commit is contained in:
Ivan Savenko
2025-06-13 13:29:31 +03:00
parent 54de24c687
commit bc48337445
8 changed files with 58 additions and 58 deletions

View File

@ -30,10 +30,6 @@ VCMI_LIB_NAMESPACE_BEGIN
///CBonusType
CBonusType::CBonusType():
hidden(true)
{}
std::string CBonusType::getDescriptionTextID() const
{
return TextIdentifier( "core", "bonus", identifier, "description").get();
@ -51,6 +47,11 @@ CBonusTypeHandler::CBonusTypeHandler()
};
#undef BONUS_NAME
for (int i = 0; i < bonusNames.size(); ++i)
{
registerObject(ModScope::scopeBuiltin(), "bonus", bonusNames[i], i);
}
#define BONUS_NAME(x) \
do { \
bonusTypes.push_back(CBonusType()); \
@ -125,7 +126,7 @@ void CBonusTypeHandler::loadObject(std::string scope, std::string name, const Js
if (vstd::contains(bonusNames, name))
{
//h3 bonus
BonusType bonus = stringToBonus(name);
BonusType bonus = static_cast<BonusType>(vstd::find_pos(bonusNames, name));
CBonusType & bt = bonusTypes[vstd::to_underlying(bonus)];
loadItem(data, bt, name);
logBonus->trace("Loaded bonus type %s", name);
@ -133,6 +134,7 @@ void CBonusTypeHandler::loadObject(std::string scope, std::string name, const Js
else
{
// new bonus
registerObject(scope, "bonus", name, bonusNames.size());
bonusNames.push_back(name);
bonusTypes.emplace_back();
loadItem(data, bonusTypes.back(), name);
@ -194,15 +196,6 @@ void CBonusTypeHandler::loadItem(const JsonNode & source, CBonusType & dest, con
}
}
BonusType CBonusTypeHandler::stringToBonus(const std::string & name) const
{
auto it = boost::range::find(bonusNames, name);
if (it != bonusNames.end())
return static_cast<BonusType>(it - bonusNames.begin());
return BonusType::NONE;
}
const std::string & CBonusTypeHandler::bonusToString(BonusType bonus) const
{
return bonusNames.at(static_cast<int>(bonus));

View File

@ -22,7 +22,7 @@ class JsonNode;
class DLL_LINKAGE CBonusType
{
public:
CBonusType();
CBonusType() = default;
std::string getDescriptionTextID() const;
@ -36,8 +36,8 @@ private:
std::map<int, std::string> valueDescriptions;
std::string identifier;
bool creatureNature;
bool hidden;
bool creatureNature = false;
bool hidden = true;
};
class DLL_LINKAGE CBonusTypeHandler : public IBonusTypeHandler
@ -54,7 +54,6 @@ public:
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
BonusType stringToBonus(const std::string & name) const;
const std::string & bonusToString(BonusType bonus) const;
bool isCreatureNatureBonus(BonusType bonus) const;

View File

@ -901,7 +901,6 @@ void CCreatureHandler::loadJsonAnimation(CCreature * cre, const JsonNode & graph
void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & config) const
{
bool hasCreatureNatureBonus = false;
creature->animDefName = AnimationPath::fromJson(config["graphics"]["animation"]);
//FIXME: MOD COMPATIBILITY
@ -915,15 +914,11 @@ void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & c
b->source = BonusSource::CREATURE_ABILITY;
b->sid = BonusSourceID(creature->getId());
b->duration = BonusDuration::PERMANENT;
hasCreatureNatureBonus |= LIBRARY->bth->isCreatureNatureBonus(b->type);
creature->addNewBonus(b);
}
}
}
if (!hasCreatureNatureBonus)
creature->addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::LIVING, BonusSource::CREATURE_ABILITY, 0, BonusSourceID(creature->getId())));
LIBRARY->identifiers()->requestIdentifier("faction", config["faction"], [=](si32 faction)
{
creature->faction = FactionID(faction);
@ -1352,7 +1347,18 @@ CCreatureHandler::~CCreatureHandler()
void CCreatureHandler::afterLoadFinalization()
{
for(auto & creature : objects)
{
if (!creature)
continue;
auto natureBonuses = creature->getBonuses([](const Bonus * b){
return LIBRARY->bth->isCreatureNatureBonus(b->type);
});
if (natureBonuses->empty())
creature->addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::LIVING, BonusSource::CREATURE_ABILITY, 0, BonusSourceID(creature->getId())));
}
}
std::set<CreatureID> CCreatureHandler::getDefaultAllowed() const

View File

@ -193,7 +193,7 @@ static void loadBonusSubtype(BonusSubtypeID & subtype, BonusType type, const Jso
}
}
static void loadBonusAddInfo(CAddInfo & var, BonusType type, const JsonNode & node)
static void loadBonusAddInfo(CAddInfo & var, BonusType type, const JsonNode & value)
{
const auto & getFirstValue = [](const JsonNode & jsonNode) -> const JsonNode &
{
@ -203,7 +203,6 @@ static void loadBonusAddInfo(CAddInfo & var, BonusType type, const JsonNode & no
return jsonNode;
};
const JsonNode & value = node["addInfo"];
if (value.isNull())
return;
@ -432,11 +431,16 @@ VCMI_LIB_NAMESPACE_BEGIN
std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonVector & ability_vec)
{
auto b = std::make_shared<Bonus>();
std::string type = ability_vec[0].String();
b->type = LIBRARY->bth->stringToBonus(type);
const JsonNode & typeNode = ability_vec[0];
const JsonNode & subtypeNode = ability_vec[2];
LIBRARY->identifiers()->requestIdentifier("bonus", typeNode, [b, subtypeNode](si32 bonusID)
{
b->type = BonusType(bonusID);
loadBonusSubtype(b->subtype, b->type, subtypeNode);
});
b->val = static_cast<si32>(ability_vec[1].Float());
loadBonusSubtype(b->subtype, b->type, ability_vec[2]);
b->additionalInfo = static_cast<si32>(ability_vec[3].Float());
b->duration = BonusDuration::PERMANENT; //TODO: handle flags (as integer)
b->turnsRemain = 0;
@ -517,8 +521,10 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
if (!parameters[0].isNull())
{
std::string anotherBonusType = parameters[0].String();
bonusLimiter->type = LIBRARY->bth->stringToBonus(anotherBonusType);
LIBRARY->identifiers()->requestIdentifier("bonus", parameters[0], [bonusLimiter](si32 bonusID)
{
bonusLimiter->type = BonusType(bonusID);
});
}
auto findSource = [&](const JsonNode & parameter)
@ -631,10 +637,15 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonNode &ability, const Text
bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b, const TextIdentifier & descriptionID)
{
const JsonNode * value = nullptr;
const JsonNode & subtypeNode = ability["subtype"];
const JsonNode & addinfoNode = ability["addInfo"];
b->type = LIBRARY->bth->stringToBonus(ability["type"].String());
loadBonusSubtype(b->subtype, b->type, ability["subtype"]);
LIBRARY->identifiers()->requestIdentifier("bonus", ability["type"], [b, subtypeNode, addinfoNode](si32 bonusID)
{
b->type = BonusType(bonusID);
loadBonusSubtype(b->subtype, b->type, subtypeNode);
loadBonusAddInfo(b->additionalInfo, b->type, addinfoNode);
});
b->val = static_cast<si32>(ability["val"].Float());
@ -643,9 +654,6 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b, const TextIdentifi
b->valType = static_cast<BonusValueType>(parseByMapN(bonusValueMap, value, "value type "));
b->stacking = ability["stacking"].String();
loadBonusAddInfo(b->additionalInfo, b->type, ability);
b->turnsRemain = static_cast<si32>(ability["turns"].Float());
if(!ability["description"].isNull())
@ -768,7 +776,7 @@ CSelector JsonUtils::parseSelector(const JsonNode & ability)
value = &ability["type"];
if(value->isString())
{
ret = ret.And(Selector::type()(LIBRARY->bth->stringToBonus(value->String())));
ret = ret.And(Selector::type()(static_cast<BonusType>(*LIBRARY->identifiers()->getIdentifier("bonus", value->String()))));
}
value = &ability["subtype"];
if(!value->isNull() && type != BonusType::NONE)

View File

@ -86,21 +86,7 @@ CIdentifierStorage::CIdentifierStorage()
void CIdentifierStorage::checkIdentifier(std::string & ID)
{
if (boost::algorithm::ends_with(ID, "."))
logMod->warn("BIG WARNING: identifier %s seems to be broken!", ID);
else
{
size_t pos = 0;
do
{
if (std::tolower(ID[pos]) != ID[pos] ) //Not in camelCase
{
logMod->warn("Warning: identifier %s is not in camelCase!", ID);
ID[pos] = std::tolower(ID[pos]);// Try to fix the ID
}
pos = ID.find('.', pos);
}
while(pos++ != std::string::npos);
}
logMod->error("BIG WARNING: identifier %s seems to be broken!", ID);
}
void CIdentifierStorage::requestIdentifier(ObjectCallback callback) const

View File

@ -844,11 +844,13 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
{
for(auto bonusData: json[name].Struct())
{
const std::string bonusId = bonusData.first;
const bool flag = bonusData.second.Bool();
if(!bonusData.second.Bool())
continue;
if(flag)
vec.push_back(LIBRARY->bth->stringToBonus(bonusId));
LIBRARY->identifiers()->requestIdentifier(bonusData.second.getModScope(), "bonus", bonusData.first, [&vec](si32 bonusID)
{
vec.push_back(BonusType(bonusID));
});
}
};

View File

@ -355,7 +355,11 @@ public:
{
if(type == "bonus")
{
return std::make_shared<SelectorCondition>(Selector::type()(LIBRARY->bth->stringToBonus(identifier)));
std::optional bonusID(LIBRARY->identifiers()->getIdentifier(scope, "bonus", identifier, true));
if (bonusID)
return std::make_shared<SelectorCondition>(Selector::type()(BonusType(*bonusID)));
else
logMod->error("Invalid bonus %s type in spell target condition.", identifier);
}
else if(type == "creature")
{

View File

@ -18,6 +18,8 @@
#include "../lib/constants/StringConstants.h"
#include "../lib/entities/artifact/CArtifact.h"
#include "../lib/mapping/CMap.h"
#include "../lib/modding/IdentifierStorage.h"
#include "../lib/modding/ModScope.h"
#include "../lib/rewardable/Configuration.h"
#include "../lib/rewardable/Limiter.h"
#include "../lib/rewardable/Reward.h"
@ -341,7 +343,7 @@ void RewardsWidget::saveCurrentVisitInfo(int index)
for(int i = 0; i < ui->bonuses->rowCount(); ++i)
{
auto dur = bonusDurationMap.at(ui->bonuses->item(i, 0)->text().toStdString());
auto typ = LIBRARY->bth->stringToBonus(ui->bonuses->item(i, 1)->text().toStdString());
auto typ = static_cast<BonusType>(*LIBRARY->identifiers()->getIdentifier(ModScope::scopeBuiltin(), "bonus", ui->bonuses->item(i, 1)->text().toStdString()));
auto val = ui->bonuses->item(i, 2)->data(Qt::UserRole).toInt();
vinfo.reward.heroBonuses.emplace_back(dur, typ, BonusSource::OBJECT_INSTANCE, val, BonusSourceID(object.id));
}