mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-25 21:38:59 +02:00
vcmi: allow to configure army movement counter
It is not hardcoded now. MOVEMENT.TXT is still not read, but ARMY_MOVEMENT updater parameters can be specified in json. There is a 4 parameters: 1. Base - base value (firstly lowest speed is multiplied by it) 2. Divider - base value is integrally divided by it 3. Multiplier - result value will be multiplied by it 4. Max - maximum allowed movement from army. Vanilla values is in defaultMods.json Fixes: https://bugs.vcmi.eu/view.php?id=3209
This commit is contained in:
parent
b91d7418dd
commit
0adffc824f
@ -88,9 +88,11 @@
|
||||
{
|
||||
"type" : "MOVEMENT", //Enable army movement bonus
|
||||
"subtype" : 1,
|
||||
"val" : 0,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"updater" : "ARMY_MOVEMENT"
|
||||
"updater" : {
|
||||
"type" : "ARMY_MOVEMENT",
|
||||
"parameters" : [ 20, 3, 10, 700]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type" : "MOVEMENT", //Basic sea movement
|
||||
|
@ -2763,13 +2763,32 @@ JsonNode TimesHeroLevelUpdater::toJsonNode() const
|
||||
return JsonUtils::stringNode("TIMES_HERO_LEVEL");
|
||||
}
|
||||
|
||||
ArmyMovementUpdater::ArmyMovementUpdater():
|
||||
base(20),
|
||||
divider(3),
|
||||
multiplier(10),
|
||||
max(700)
|
||||
{
|
||||
}
|
||||
|
||||
ArmyMovementUpdater::ArmyMovementUpdater(int base, int divider, int multiplier, int max):
|
||||
base(base),
|
||||
divider(divider),
|
||||
multiplier(multiplier),
|
||||
max(max)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<Bonus> ArmyMovementUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
||||
{
|
||||
if(b->type == Bonus::MOVEMENT && context.getNodeType() == CBonusSystemNode::HERO)
|
||||
{
|
||||
auto speed = static_cast<const CGHeroInstance &>(context).getLowestCreatureSpeed();
|
||||
si32 armySpeed = speed * base / divider;
|
||||
auto counted = armySpeed * multiplier;
|
||||
auto newBonus = std::make_shared<Bonus>(*b);
|
||||
newBonus->source = Bonus::ARMY;
|
||||
newBonus->val = static_cast<const CGHeroInstance &>(context).getArmyMovementBonus();
|
||||
newBonus->val = vstd::amin(counted, max);
|
||||
return newBonus;
|
||||
}
|
||||
if(b->type != Bonus::MOVEMENT)
|
||||
@ -2784,7 +2803,15 @@ std::string ArmyMovementUpdater::toString() const
|
||||
|
||||
JsonNode ArmyMovementUpdater::toJsonNode() const
|
||||
{
|
||||
return JsonUtils::stringNode("ARMY_MOVEMENT");
|
||||
JsonNode root(JsonNode::JsonType::DATA_STRUCT);
|
||||
|
||||
root["type"].String() = "ARMY_MOVEMENT";
|
||||
root["parameters"].Vector().push_back(JsonUtils::intNode(base));
|
||||
root["parameters"].Vector().push_back(JsonUtils::intNode(divider));
|
||||
root["parameters"].Vector().push_back(JsonUtils::intNode(multiplier));
|
||||
root["parameters"].Vector().push_back(JsonUtils::intNode(max));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
TimesStackLevelUpdater::TimesStackLevelUpdater()
|
||||
|
@ -1320,9 +1320,19 @@ public:
|
||||
class DLL_LINKAGE ArmyMovementUpdater : public IUpdater
|
||||
{
|
||||
public:
|
||||
si32 base;
|
||||
si32 divider;
|
||||
si32 multiplier;
|
||||
si32 max;
|
||||
ArmyMovementUpdater();
|
||||
ArmyMovementUpdater(int base, int divider, int multiplier, int max);
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & static_cast<IUpdater &>(*this);
|
||||
h & base;
|
||||
h & divider;
|
||||
h & multiplier;
|
||||
h & max;
|
||||
}
|
||||
|
||||
std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
|
||||
|
@ -864,6 +864,24 @@ static TUpdaterPtr parseUpdater(const JsonNode & updaterJson)
|
||||
updater->stepSize = static_cast<int>(param[1].Integer());
|
||||
return updater;
|
||||
}
|
||||
else if (updaterJson["type"].String() == "ARMY_MOVEMENT")
|
||||
{
|
||||
std::shared_ptr<ArmyMovementUpdater> updater = std::make_shared<ArmyMovementUpdater>();
|
||||
if(updaterJson["parameters"].isVector())
|
||||
{
|
||||
const auto & param = updaterJson["parameters"].Vector();
|
||||
if(param.size() < 4)
|
||||
logMod->warn("Invalid ARMY_MOVEMENT parameters, using default!");
|
||||
else
|
||||
{
|
||||
updater->base = static_cast<si32>(param.at(0).Integer());
|
||||
updater->divider = static_cast<si32>(param.at(1).Integer());
|
||||
updater->multiplier = static_cast<si32>(param.at(2).Integer());
|
||||
updater->max = static_cast<si32>(param.at(3).Integer());
|
||||
}
|
||||
return updater;
|
||||
}
|
||||
}
|
||||
else
|
||||
logMod->warn("Unknown updater type \"%s\"", updaterJson["type"].String());
|
||||
break;
|
||||
|
@ -188,19 +188,17 @@ int CGHeroInstance::maxMovePoints(bool onLand) const
|
||||
return maxMovePointsCached(onLand, &ti);
|
||||
}
|
||||
|
||||
int CGHeroInstance::getArmyMovementBonus() const
|
||||
int CGHeroInstance::getLowestCreatureSpeed() const
|
||||
{
|
||||
return armyMovementVal;
|
||||
return lowestCreatureSpeed;
|
||||
}
|
||||
|
||||
void CGHeroInstance::updateArmyMovementBonus(bool onLand, const TurnInfo * ti) const
|
||||
{
|
||||
int armySpeed = lowestSpeed(this) * 20 / 3;
|
||||
|
||||
auto base = armySpeed * 10; // separate *10 is intentional to receive same rounding as in h3
|
||||
if(armyMovementVal != vstd::abetween(base, 200, 700)) // army modifier speed is limited by these values
|
||||
auto realLowestSpeed = lowestSpeed(this);
|
||||
if(lowestCreatureSpeed != realLowestSpeed)
|
||||
{
|
||||
armyMovementVal = base;
|
||||
lowestCreatureSpeed = realLowestSpeed;
|
||||
ti->updateHeroBonuses(Bonus::MOVEMENT, Selector::subtype()(!!onLand).And(Selector::sourceTypeSel(Bonus::ARMY)));
|
||||
}
|
||||
}
|
||||
@ -208,7 +206,7 @@ void CGHeroInstance::updateArmyMovementBonus(bool onLand, const TurnInfo * ti) c
|
||||
int CGHeroInstance::maxMovePointsCached(bool onLand, const TurnInfo * ti) const
|
||||
{
|
||||
updateArmyMovementBonus(onLand, ti);
|
||||
return ti->valOfBonuses(Bonus::MOVEMENT, !!onLand);;
|
||||
return ti->valOfBonuses(Bonus::MOVEMENT, !!onLand);
|
||||
}
|
||||
|
||||
CGHeroInstance::CGHeroInstance():
|
||||
@ -222,7 +220,7 @@ CGHeroInstance::CGHeroInstance():
|
||||
level(1),
|
||||
exp(UNINITIALIZED_EXPERIENCE),
|
||||
sex(std::numeric_limits<ui8>::max()),
|
||||
armyMovementVal(0)
|
||||
lowestCreatureSpeed(0)
|
||||
{
|
||||
setNodeType(HERO);
|
||||
ID = Obj::HERO;
|
||||
|
@ -49,7 +49,7 @@ class DLL_LINKAGE CGHeroInstance : public CArmedInstance, public IBoatGenerator,
|
||||
|
||||
private:
|
||||
std::set<SpellID> spells; //known spells (spell IDs)
|
||||
mutable int armyMovementVal;
|
||||
mutable int lowestCreatureSpeed;
|
||||
|
||||
public:
|
||||
|
||||
@ -171,7 +171,7 @@ public:
|
||||
|
||||
ui32 getTileCost(const TerrainTile & dest, const TerrainTile & from, const TurnInfo * ti) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||
TerrainId getNativeTerrain() const;
|
||||
ui32 getLowestCreatureSpeed() const;
|
||||
int getLowestCreatureSpeed() const;
|
||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||
si32 getManaNewTurn() const; //calculate how much mana this hero is going to have the next day
|
||||
int getCurrentLuck(int stack=-1, bool town=false) const;
|
||||
@ -213,7 +213,6 @@ public:
|
||||
int maxMovePointsCached(bool onLand, const TurnInfo * ti) const;
|
||||
//update army movement bonus
|
||||
void updateArmyMovementBonus(bool onLand, const TurnInfo * ti) const;
|
||||
int getArmyMovementBonus() const;
|
||||
|
||||
int movementPointsAfterEmbark(int MPsBefore, int basicCost, bool disembark = false, const TurnInfo * ti = nullptr) const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user