mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Multiple minor fixes:
- fixed starting armies of some heroes, including Bron #1602 - (debian) added vcmi-dbg package with debug information - proper randomization of hero secondary skills, fixes #1603 - second capitol will show up as disabled immediately #1604 - proper deserialization of boost::variant - empty file will no longer crash JsonNode parser - fixed some compiler warnings
This commit is contained in:
parent
ee1b0459e6
commit
3d3f93275d
@ -12,6 +12,21 @@
|
|||||||
"specialties":
|
"specialties":
|
||||||
[
|
[
|
||||||
{ "type":10, "val": 1, "subtype": 5, "info": 0 }
|
{ "type":10, "val": 1, "subtype": 5, "info": 0 }
|
||||||
|
],
|
||||||
|
"army" :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"min" : 10, "max" : 20,
|
||||||
|
"creature" : "gnoll"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"min" : 4, "max" : 7,
|
||||||
|
"creature" : "basilisk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"min" : 2, "max" : 4,
|
||||||
|
"creature" : "serpentFly"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"drakon":
|
"drakon":
|
||||||
|
@ -170,12 +170,15 @@
|
|||||||
"army" :
|
"army" :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"min" : 10, "max" : 20,
|
||||||
"creature" : "troglodyte"
|
"creature" : "troglodyte"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"min" : 4, "max" : 7,
|
||||||
"creature" : "harpy"
|
"creature" : "harpy"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"min" : 2, "max" : 3,
|
||||||
"creature" : "evilEye"
|
"creature" : "evilEye"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -198,12 +201,15 @@
|
|||||||
"army" :
|
"army" :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"min" : 10, "max" : 20,
|
||||||
"creature" : "goblin"
|
"creature" : "goblin"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"min" : 4, "max" : 7,
|
||||||
"creature" : "goblinWolfRider"
|
"creature" : "goblinWolfRider"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"min" : 2, "max" : 3,
|
||||||
"creature" : "orc"
|
"creature" : "orc"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -228,12 +234,15 @@
|
|||||||
"army" :
|
"army" :
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"min" : 10, "max" : 20,
|
||||||
"creature" : "imp"
|
"creature" : "imp"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"min" : 4, "max" : 7,
|
||||||
"creature" : "hellHound"
|
"creature" : "hellHound"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"min" : 2, "max" : 3,
|
||||||
"creature" : "hellHound"
|
"creature" : "hellHound"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
6
debian/control
vendored
6
debian/control
vendored
@ -17,3 +17,9 @@ Description: Rewrite of the Heroes of Might and Magic 3 engine
|
|||||||
.
|
.
|
||||||
In its current state it already supports maps of any sizes, higher
|
In its current state it already supports maps of any sizes, higher
|
||||||
resolutions and extended engine limits.
|
resolutions and extended engine limits.
|
||||||
|
|
||||||
|
Package: vcmi-dbg
|
||||||
|
Architecture: any
|
||||||
|
Section: debug
|
||||||
|
Depends: vcmi (= ${binary:Version}), ${misc:Depends}
|
||||||
|
Description: Debug symbols for vcmi package
|
||||||
|
8
debian/rules
vendored
8
debian/rules
vendored
@ -6,3 +6,11 @@
|
|||||||
# override disabled by default rpath - we need to find libvcmi.so with it:
|
# override disabled by default rpath - we need to find libvcmi.so with it:
|
||||||
override_dh_auto_configure:
|
override_dh_auto_configure:
|
||||||
dh_auto_configure -- -DCMAKE_SKIP_RPATH=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBIN_DIR=games
|
dh_auto_configure -- -DCMAKE_SKIP_RPATH=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBIN_DIR=games
|
||||||
|
.PHONY: override_dh_strip
|
||||||
|
override_dh_strip:
|
||||||
|
dh_strip --dbg-package=vcmi-dbg
|
||||||
|
override_dh_auto_install:
|
||||||
|
dh_auto_install --destdir=debian/vcmi
|
||||||
|
override_dh_installdocs:
|
||||||
|
dh_installdocs --link-doc=vcmi
|
||||||
|
|
||||||
|
@ -2957,8 +2957,8 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
|
|||||||
else
|
else
|
||||||
ss.heroId = -1;
|
ss.heroId = -1;
|
||||||
|
|
||||||
for(const JsonNode &n : n["heroPrimSkills"].Vector())
|
for(const JsonNode &entry : n["heroPrimSkills"].Vector())
|
||||||
ss.heroPrimSkills.push_back(n.Float());
|
ss.heroPrimSkills.push_back(entry.Float());
|
||||||
|
|
||||||
for(const JsonNode &skillNode : n["heroSecSkills"].Vector())
|
for(const JsonNode &skillNode : n["heroSecSkills"].Vector())
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SecondarySkill CHeroClass::chooseSecSkill(const std::set<SecondarySkill> & possibles) const //picks secondary skill out from given possibilities
|
SecondarySkill CHeroClass::chooseSecSkill(const std::set<SecondarySkill> & possibles, std::minstd_rand & distr) const //picks secondary skill out from given possibilities
|
||||||
{
|
{
|
||||||
int totalProb = 0;
|
int totalProb = 0;
|
||||||
for(auto & possible : possibles)
|
for(auto & possible : possibles)
|
||||||
@ -31,7 +31,7 @@ SecondarySkill CHeroClass::chooseSecSkill(const std::set<SecondarySkill> & possi
|
|||||||
}
|
}
|
||||||
if (totalProb != 0) // may trigger if set contains only banned skills (0 probability)
|
if (totalProb != 0) // may trigger if set contains only banned skills (0 probability)
|
||||||
{
|
{
|
||||||
int ran = rand()%totalProb;
|
int ran = distr()%totalProb;
|
||||||
for(auto & possible : possibles)
|
for(auto & possible : possibles)
|
||||||
{
|
{
|
||||||
ran -= secSkillProbability[possible];
|
ran -= secSkillProbability[possible];
|
||||||
|
@ -121,7 +121,7 @@ public:
|
|||||||
std::string imageMapFemale;
|
std::string imageMapFemale;
|
||||||
|
|
||||||
bool isMagicHero() const;
|
bool isMagicHero() const;
|
||||||
SecondarySkill chooseSecSkill(const std::set<SecondarySkill> & possibles) const; //picks secondary skill out from given possibilities
|
SecondarySkill chooseSecSkill(const std::set<SecondarySkill> & possibles, std::minstd_rand & distr) const; //picks secondary skill out from given possibilities
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
@ -1016,7 +1016,7 @@ void CGHeroInstance::initObj()
|
|||||||
if(!type)
|
if(!type)
|
||||||
initHero(); //TODO: set up everything for prison before specialties are configured
|
initHero(); //TODO: set up everything for prison before specialties are configured
|
||||||
|
|
||||||
skillsInfo.randomSeed = rand();
|
skillsInfo.distribution.seed(rand());
|
||||||
skillsInfo.resetMagicSchoolCounter();
|
skillsInfo.resetMagicSchoolCounter();
|
||||||
skillsInfo.resetWisdomCounter();
|
skillsInfo.resetWisdomCounter();
|
||||||
|
|
||||||
@ -1661,14 +1661,19 @@ ArtBearer::ArtBearer CGHeroInstance::bearerType() const
|
|||||||
std::vector<SecondarySkill> CGHeroInstance::levelUpProposedSkills() const
|
std::vector<SecondarySkill> CGHeroInstance::levelUpProposedSkills() const
|
||||||
{
|
{
|
||||||
std::vector<SecondarySkill> obligatorySkills; //hero is offered magic school or wisdom if possible
|
std::vector<SecondarySkill> obligatorySkills; //hero is offered magic school or wisdom if possible
|
||||||
|
if (!skillsInfo.wisdomCounter)
|
||||||
|
{
|
||||||
|
if (cb->isAllowed(2, SecondarySkill::WISDOM) && !getSecSkillLevel(SecondarySkill::WISDOM))
|
||||||
|
obligatorySkills.push_back(SecondarySkill::WISDOM);
|
||||||
|
}
|
||||||
if (!skillsInfo.magicSchoolCounter)
|
if (!skillsInfo.magicSchoolCounter)
|
||||||
{
|
{
|
||||||
std::vector<SecondarySkill> ss;
|
std::vector<SecondarySkill> ss;
|
||||||
ss += SecondarySkill::FIRE_MAGIC, SecondarySkill::WATER_MAGIC, SecondarySkill::EARTH_MAGIC, SecondarySkill::EARTH_MAGIC;
|
ss += SecondarySkill::FIRE_MAGIC, SecondarySkill::WATER_MAGIC, SecondarySkill::EARTH_MAGIC, SecondarySkill::EARTH_MAGIC;
|
||||||
|
|
||||||
auto rng = [=](ui32 val)-> ui32
|
auto rng = [=](ui32 val) mutable -> ui32
|
||||||
{
|
{
|
||||||
return skillsInfo.randomSeed % val; //must be determined
|
return skillsInfo.distribution() % val; //must be determined
|
||||||
};
|
};
|
||||||
std::random_shuffle(ss.begin(), ss.end(), rng);
|
std::random_shuffle(ss.begin(), ss.end(), rng);
|
||||||
|
|
||||||
@ -1681,11 +1686,6 @@ std::vector<SecondarySkill> CGHeroInstance::levelUpProposedSkills() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!skillsInfo.wisdomCounter)
|
|
||||||
{
|
|
||||||
if (cb->isAllowed(2, SecondarySkill::WISDOM) && !getSecSkillLevel(SecondarySkill::WISDOM))
|
|
||||||
obligatorySkills.push_back(SecondarySkill::WISDOM);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SecondarySkill> skills;
|
std::vector<SecondarySkill> skills;
|
||||||
//picking sec. skills for choice
|
//picking sec. skills for choice
|
||||||
@ -1696,7 +1696,7 @@ std::vector<SecondarySkill> CGHeroInstance::levelUpProposedSkills() const
|
|||||||
|
|
||||||
for(auto & elem : secSkills)
|
for(auto & elem : secSkills)
|
||||||
{
|
{
|
||||||
if(elem.second < 3)
|
if(elem.second < SecSkillLevel::EXPERT)
|
||||||
basicAndAdv.insert(elem.first);
|
basicAndAdv.insert(elem.first);
|
||||||
else
|
else
|
||||||
expert.insert(elem.first);
|
expert.insert(elem.first);
|
||||||
@ -1709,35 +1709,41 @@ std::vector<SecondarySkill> CGHeroInstance::levelUpProposedSkills() const
|
|||||||
expert.erase (s);
|
expert.erase (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
//first offered skill
|
//first offered skill:
|
||||||
if (canLearnSkill() && obligatorySkills.size()) //offer always if possible
|
// 1) give obligatory skill
|
||||||
|
// 2) give any other new skill
|
||||||
|
// 3) upgrade existing
|
||||||
|
if (canLearnSkill() && obligatorySkills.size() > 0)
|
||||||
{
|
{
|
||||||
skills.push_back (obligatorySkills[0]);
|
skills.push_back (obligatorySkills[0]);
|
||||||
}
|
}
|
||||||
|
else if(none.size() && canLearnSkill()) //hero have free skill slot
|
||||||
|
{
|
||||||
|
skills.push_back(type->heroClass->chooseSecSkill(none, skillsInfo.distribution)); //new skill
|
||||||
|
}
|
||||||
else if(!basicAndAdv.empty())
|
else if(!basicAndAdv.empty())
|
||||||
{
|
{
|
||||||
SecondarySkill s = type->heroClass->chooseSecSkill(basicAndAdv);//upgrade existing
|
skills.push_back(type->heroClass->chooseSecSkill(basicAndAdv, skillsInfo.distribution)); //upgrade existing
|
||||||
|
}
|
||||||
|
|
||||||
|
//second offered skill:
|
||||||
|
//1) upgrade existing
|
||||||
|
//2) give obligatory skill
|
||||||
|
//3) give any other new skill
|
||||||
|
if(!basicAndAdv.empty())
|
||||||
|
{
|
||||||
|
SecondarySkill s = type->heroClass->chooseSecSkill(basicAndAdv, skillsInfo.distribution);//upgrade existing
|
||||||
skills.push_back(s);
|
skills.push_back(s);
|
||||||
basicAndAdv.erase(s);
|
basicAndAdv.erase(s);
|
||||||
}
|
}
|
||||||
else if(none.size() && canLearnSkill())
|
else if (canLearnSkill() && obligatorySkills.size() > 1)
|
||||||
{
|
|
||||||
skills.push_back(type->heroClass->chooseSecSkill(none)); //give new skill
|
|
||||||
none.erase(skills.back());
|
|
||||||
}
|
|
||||||
|
|
||||||
//second offered skill
|
|
||||||
if (canLearnSkill() && obligatorySkills.size() > 1)
|
|
||||||
{
|
{
|
||||||
skills.push_back (obligatorySkills[1]);
|
skills.push_back (obligatorySkills[1]);
|
||||||
}
|
}
|
||||||
else if(none.size() && canLearnSkill()) //hero have free skill slot
|
else if(none.size() && canLearnSkill())
|
||||||
{
|
{
|
||||||
skills.push_back(type->heroClass->chooseSecSkill(none)); //new skill
|
skills.push_back(type->heroClass->chooseSecSkill(none, skillsInfo.distribution)); //give new skill
|
||||||
}
|
none.erase(skills.back());
|
||||||
else if(!basicAndAdv.empty())
|
|
||||||
{
|
|
||||||
skills.push_back(type->heroClass->chooseSecSkill(basicAndAdv)); //upgrade existing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return skills;
|
return skills;
|
||||||
|
@ -350,7 +350,9 @@ public:
|
|||||||
|
|
||||||
struct DLL_LINKAGE SecondarySkillsInfo
|
struct DLL_LINKAGE SecondarySkillsInfo
|
||||||
{
|
{
|
||||||
ui32 randomSeed; //skills are determined, initialized at map start
|
//skills are determined, initialized at map start
|
||||||
|
//FIXME: remove mutable?
|
||||||
|
mutable std::minstd_rand distribution;
|
||||||
ui8 magicSchoolCounter;
|
ui8 magicSchoolCounter;
|
||||||
ui8 wisdomCounter;
|
ui8 wisdomCounter;
|
||||||
|
|
||||||
@ -359,7 +361,21 @@ public:
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & randomSeed & magicSchoolCounter & wisdomCounter;
|
h & magicSchoolCounter & wisdomCounter;
|
||||||
|
if (h.saving)
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << distribution;
|
||||||
|
std::string str = stream.str();
|
||||||
|
h & str;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string str;
|
||||||
|
h & str;
|
||||||
|
std::istringstream stream(str);
|
||||||
|
stream >> distribution;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} skillsInfo;
|
} skillsInfo;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <boost/mpl/equal_to.hpp>
|
#include <boost/mpl/equal_to.hpp>
|
||||||
#include <boost/mpl/int.hpp>
|
#include <boost/mpl/int.hpp>
|
||||||
#include <boost/mpl/identity.hpp>
|
#include <boost/mpl/identity.hpp>
|
||||||
|
#include <boost/mpl/for_each.hpp>
|
||||||
#include <boost/any.hpp>
|
#include <boost/any.hpp>
|
||||||
|
|
||||||
#include "ConstTransitivePtr.h"
|
#include "ConstTransitivePtr.h"
|
||||||
@ -248,6 +249,30 @@ struct LoadWrong
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Variant, typename Source>
|
||||||
|
struct VariantLoaderHelper
|
||||||
|
{
|
||||||
|
Source & source;
|
||||||
|
std::vector<std::function<Variant()>> funcs;
|
||||||
|
|
||||||
|
VariantLoaderHelper(Source & source):
|
||||||
|
source(source)
|
||||||
|
{
|
||||||
|
mpl::for_each<typename Variant::types>(std::ref(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
void operator()(Type)
|
||||||
|
{
|
||||||
|
funcs.push_back([&]() -> Variant
|
||||||
|
{
|
||||||
|
Type obj;
|
||||||
|
source >> obj;
|
||||||
|
return Variant(obj);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct SerializationLevel
|
struct SerializationLevel
|
||||||
{
|
{
|
||||||
@ -1179,27 +1204,20 @@ public:
|
|||||||
data.resize(length);
|
data.resize(length);
|
||||||
this->This()->read((void*)data.c_str(),length);
|
this->This()->read((void*)data.c_str(),length);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||||
void loadSerializable(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &data)
|
void loadSerializable(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> &data)
|
||||||
{
|
{
|
||||||
|
typedef boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> TVariant;
|
||||||
|
|
||||||
|
VariantLoaderHelper<TVariant, CISer> loader(*this);
|
||||||
|
|
||||||
si32 which;
|
si32 which;
|
||||||
*this >> which;
|
*this >> which;
|
||||||
if(which == 0)
|
assert(which < loader.funcs.size());
|
||||||
{
|
data = loader.funcs.at(which)();
|
||||||
T0 obj;
|
|
||||||
*this >> obj;
|
|
||||||
data = obj;
|
|
||||||
}
|
|
||||||
else if(which == 1)
|
|
||||||
{
|
|
||||||
T1 obj;
|
|
||||||
*this >> obj;
|
|
||||||
data = obj;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
//TODO write more if needed, general solution would be much longer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void loadSerializable(boost::optional<T> & data)
|
void loadSerializable(boost::optional<T> & data)
|
||||||
{
|
{
|
||||||
|
@ -580,20 +580,6 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
|
|||||||
if(vstd::contains(t->forbiddenBuildings, ID))
|
if(vstd::contains(t->forbiddenBuildings, ID))
|
||||||
return EBuildingState::FORBIDDEN; //forbidden
|
return EBuildingState::FORBIDDEN; //forbidden
|
||||||
|
|
||||||
auto buildTest = [&](const BuildingID & id)
|
|
||||||
{
|
|
||||||
return t->hasBuilt(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
|
|
||||||
return EBuildingState::CANT_BUILD_TODAY; //building limit
|
|
||||||
|
|
||||||
if (!building->requirements.test(buildTest))
|
|
||||||
return EBuildingState::PREREQUIRES;
|
|
||||||
|
|
||||||
if (building->upgrade != BuildingID::NONE && !t->hasBuilt(building->upgrade))
|
|
||||||
return EBuildingState::MISSING_BASE;
|
|
||||||
|
|
||||||
if(ID == BuildingID::CAPITOL)
|
if(ID == BuildingID::CAPITOL)
|
||||||
{
|
{
|
||||||
const PlayerState *ps = getPlayer(t->tempOwner);
|
const PlayerState *ps = getPlayer(t->tempOwner);
|
||||||
@ -612,10 +598,24 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
|
|||||||
{
|
{
|
||||||
const TerrainTile *tile = getTile(t->bestLocation(), false);
|
const TerrainTile *tile = getTile(t->bestLocation(), false);
|
||||||
|
|
||||||
if(!tile || tile->terType != ETerrainType::WATER)
|
if(!tile || tile->terType != ETerrainType::WATER)
|
||||||
return EBuildingState::NO_WATER; //lack of water
|
return EBuildingState::NO_WATER; //lack of water
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto buildTest = [&](const BuildingID & id)
|
||||||
|
{
|
||||||
|
return t->hasBuilt(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
|
||||||
|
return EBuildingState::CANT_BUILD_TODAY; //building limit
|
||||||
|
|
||||||
|
if (!building->requirements.test(buildTest))
|
||||||
|
return EBuildingState::PREREQUIRES;
|
||||||
|
|
||||||
|
if (building->upgrade != BuildingID::NONE && !t->hasBuilt(building->upgrade))
|
||||||
|
return EBuildingState::MISSING_BASE;
|
||||||
|
|
||||||
//checking resources
|
//checking resources
|
||||||
if(!building->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
|
if(!building->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
|
||||||
return EBuildingState::NO_RESOURCES; //lack of res
|
return EBuildingState::NO_RESOURCES; //lack of res
|
||||||
|
@ -131,15 +131,22 @@ JsonNode JsonParser::parse(std::string fileName)
|
|||||||
{
|
{
|
||||||
JsonNode root;
|
JsonNode root;
|
||||||
|
|
||||||
if (!Unicode::isValidString(&input[0], input.size()))
|
if (input.size() == 0)
|
||||||
error("Not a valid UTF-8 file", false);
|
{
|
||||||
|
error("File is empty", false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!Unicode::isValidString(&input[0], input.size()))
|
||||||
|
error("Not a valid UTF-8 file", false);
|
||||||
|
|
||||||
extractValue(root);
|
extractValue(root);
|
||||||
extractWhitespace(false);
|
extractWhitespace(false);
|
||||||
|
|
||||||
//Warn if there are any non-whitespace symbols left
|
//Warn if there are any non-whitespace symbols left
|
||||||
if (pos < input.size())
|
if (pos < input.size())
|
||||||
error("Not all file was parsed!", true);
|
error("Not all file was parsed!", true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!errors.empty())
|
if (!errors.empty())
|
||||||
{
|
{
|
||||||
|
@ -205,9 +205,9 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero)
|
|||||||
else if(hlu.skills.size() == 1 || hero->tempOwner == PlayerColor::NEUTRAL) //choose skill automatically
|
else if(hlu.skills.size() == 1 || hero->tempOwner == PlayerColor::NEUTRAL) //choose skill automatically
|
||||||
{
|
{
|
||||||
sendAndApply(&hlu);
|
sendAndApply(&hlu);
|
||||||
auto rng = [&]()-> ui32
|
auto rng = [&]() mutable -> ui32
|
||||||
{
|
{
|
||||||
return hero->skillsInfo.randomSeed; //must be determined
|
return hero->skillsInfo.distribution(); //must be determined
|
||||||
};
|
};
|
||||||
levelUpHero(hero, vstd::pickRandomElementOf (hlu.skills, rng));
|
levelUpHero(hero, vstd::pickRandomElementOf (hlu.skills, rng));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user