1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Implemented visit mode "limiter". Fixed h3m variable loading

This commit is contained in:
Ivan Savenko 2023-09-30 21:22:31 +03:00
parent fd01a25352
commit a3b2354481
9 changed files with 37 additions and 13 deletions

View File

@ -396,6 +396,8 @@ bool CTownRewardableBuilding::wasVisitedBefore(const CGHeroInstance * contextHer
return contextHero->hasBonusFrom(BonusSource::TOWN_STRUCTURE, Bonus::getSid32(town->town->faction->getIndex(), bID));
case Rewardable::VISIT_HERO:
return visitors.find(contextHero->id) != visitors.end();
case Rewardable::VISIT_LIMITER:
return configuration.visitLimiter.heroAllowed(contextHero);
default:
return false;
}

View File

@ -188,6 +188,8 @@ bool CRewardableObject::wasVisitedBefore(const CGHeroInstance * contextHero) con
return contextHero->hasBonusFrom(BonusSource::OBJECT, ID);
case Rewardable::VISIT_HERO:
return contextHero->visitedObjects.count(ObjectInstanceID(id));
case Rewardable::VISIT_LIMITER:
return configuration.visitLimiter.heroAllowed(contextHero);
default:
return false;
}
@ -200,6 +202,7 @@ bool CRewardableObject::wasVisited(PlayerColor player) const
case Rewardable::VISIT_UNLIMITED:
case Rewardable::VISIT_BONUS:
case Rewardable::VISIT_HERO:
case Rewardable::VISIT_LIMITER:
return false;
case Rewardable::VISIT_ONCE:
case Rewardable::VISIT_PLAYER:
@ -217,6 +220,8 @@ bool CRewardableObject::wasVisited(const CGHeroInstance * h) const
return h->hasBonusFrom(BonusSource::OBJECT, ID);
case Rewardable::VISIT_HERO:
return h->visitedObjects.count(ObjectInstanceID(id));
case Rewardable::VISIT_LIMITER:
return configuration.visitLimiter.heroAllowed(h);
default:
return wasVisited(h->tempOwner);
}

View File

@ -34,6 +34,7 @@
#include "../mapObjects/CGCreature.h"
#include "../mapObjects/MapObjects.h"
#include "../mapObjects/ObjectTemplate.h"
#include "../modding/ModScope.h"
#include "../spells/CSpellHandler.h"
#include <boost/crc.hpp>
@ -1156,7 +1157,7 @@ CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position, std::share
{
auto defaultAllowed = VLC->skillh->getDefaultAllowed();
for(int skillID = 0; skillID < VLC->skillh->size(); ++skillID)
for(int skillID = features.skillsCount; skillID < defaultAllowed.size(); ++skillID)
if(defaultAllowed[skillID])
allowedAbilities.insert(SecondarySkill(skillID));
}
@ -1170,7 +1171,8 @@ CGObjectInstance * CMapLoaderH3M::readWitchHut(const int3 & position, std::share
anyOfList.push_back(entry);
}
JsonNode variable;
variable.Vector() = anyOfList;
variable["anyOf"].Vector() = anyOfList;
variable.setMeta(ModScope::scopeGame()); // list may include skills from all mods
rewardable->configuration.presetVariable("secondarySkill", "gainedSkill", variable);
}

View File

@ -38,7 +38,7 @@ JsonNode Rewardable::Configuration::getPresetVariable(const std::string & catego
{
std::string variableID = category + '@' + name;
if (variables.values.count(variableID))
if (variables.preset.count(variableID))
return variables.preset.at(variableID);
else
return JsonNode();

View File

@ -26,6 +26,7 @@ enum EVisitMode
VISIT_ONCE, // only once, first to visit get all the rewards
VISIT_HERO, // every hero can visit object once
VISIT_BONUS, // can be visited by any hero that don't have bonus from this object
VISIT_LIMITER, // can be visited by heroes that don't fulfill provided limiter
VISIT_PLAYER // every player can visit object once
};
@ -46,7 +47,7 @@ enum class EEventType
};
const std::array<std::string, 3> SelectModeString{"selectFirst", "selectPlayer", "selectRandom"};
const std::array<std::string, 5> VisitModeString{"unlimited", "once", "hero", "bonus", "player"};
const std::array<std::string, 6> VisitModeString{"unlimited", "once", "hero", "bonus", "limiter", "player"};
struct DLL_LINKAGE ResetInfo
{
@ -135,6 +136,9 @@ struct DLL_LINKAGE Configuration
/// List of variables shoread between all limiters and rewards
Rewardable::Variables variables;
/// Limiter that will be used to determine that object is visited. Only if visit mode is set to "limiter"
Rewardable::Limiter visitLimiter;
/// if true - player can refuse visiting an object (e.g. Tomb)
bool canRefuse = false;

View File

@ -108,6 +108,7 @@ void Rewardable::Info::configureLimiter(Rewardable::Configuration & object, CRan
limiter.daysPassed = JsonRandom::loadValue(source["daysPassed"], rng, variables);
limiter.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng, variables);
limiter.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng, variables);
limiter.canLearnSkills = source["canLearnSkills"].Bool();
limiter.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, variables);
limiter.manaPoints = JsonRandom::loadValue(source["manaPoints"], rng, variables);
@ -185,31 +186,32 @@ void Rewardable::Info::configureVariables(Rewardable::Configuration & object, CR
for(const auto & entry : category.second.Struct())
{
JsonNode preset = object.getPresetVariable(category.first, entry.first);
const JsonNode & input = preset.isNull() ? entry.second : preset;
int32_t value = -1;
if (category.first == "number")
value = JsonRandom::loadValue(entry.second, rng, object.variables.values);
value = JsonRandom::loadValue(input, rng, object.variables.values);
if (category.first == "artifact")
value = JsonRandom::loadArtifact(entry.second, rng, object.variables.values).getNum();
value = JsonRandom::loadArtifact(input, rng, object.variables.values).getNum();
if (category.first == "spell")
value = JsonRandom::loadSpell(entry.second, rng, object.variables.values).getNum();
value = JsonRandom::loadSpell(input, rng, object.variables.values).getNum();
// TODO
// if (category.first == "creature")
// value = JsonRandom::loadCreature(entry.second, rng, object.variables.values).type->getId();
// value = JsonRandom::loadCreature(input, rng, object.variables.values).type->getId();
// TODO
// if (category.first == "resource")
// value = JsonRandom::loadResource(entry.second, rng, object.variables.values).getNum();
// value = JsonRandom::loadResource(input, rng, object.variables.values).getNum();
// TODO
// if (category.first == "primarySkill")
// value = JsonRandom::loadCreature(entry.second, rng, object.variables.values).getNum();
// value = JsonRandom::loadCreature(input, rng, object.variables.values).getNum();
if (category.first == "secondarySkill")
value = JsonRandom::loadSecondary(entry.second, rng, object.variables.values).getNum();
value = JsonRandom::loadSecondary(input, rng, object.variables.values).getNum();
object.initVariable(category.first, entry.first, value);
}
@ -328,6 +330,9 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, CRand
break;
}
}
configureLimiter(object, rng, object.visitLimiter, parameters["visitLimiter"]);
}
bool Rewardable::Info::givesResources() const

View File

@ -101,6 +101,9 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
if(manaPoints > hero->mana)
return false;
if (canLearnSkills && !hero->canLearnSkill())
return false;
if(manaPercentage > 100 * hero->mana / hero->manaLimit())
return false;

View File

@ -44,6 +44,9 @@ struct DLL_LINKAGE Limiter final
/// percentage of mana points that hero needs to have
si32 manaPercentage;
/// Number of free secondary slots that hero needs to have
bool canLearnSkills;
/// resources player needs to have in order to trigger reward
TResources resources;

View File

@ -102,7 +102,7 @@ int SetResourcesProxy::getAmount(lua_State * L)
if(!S.tryGet(1, object))
return S.retVoid();
auto type = EGameResID::INVALID;
auto type = EGameResID::NONE;
if(!S.tryGet(2, type))
return S.retVoid();
@ -122,7 +122,7 @@ int SetResourcesProxy::setAmount(lua_State * L)
if(!S.tryGet(1, object))
return S.retVoid();
auto type = EGameResID::INVALID;
auto type = EGameResID::NONE;
if(!S.tryGet(2, type))
return S.retVoid();