1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

Spells configuration version 2 (effect-based)

* Indirect spell effects loading
* Json serializer improvements
* spell->canBeCastAt do not allow useless cast for any spell
* Added proxy caster class for spell-created obstacles
* Handle damage from spell-created obstacles inside mechanics
* Experimental GameState integration/regression tests
* Ignore mod settings and load only "vcmi" mod when running tests
* fixed https://bugs.vcmi.eu/view.php?id=2765 (with tests)
* Huge improvements of BattleAI regarding spell casts
* AI can cast almost any combat spell except TELEPORT, SACRIFICE and obstacle placement spells.
* Possible fix for https://bugs.vcmi.eu/view.php?id=1811
* CStack factored out to several classes
* [Battle] Allowed RETURN_AFTER_STRIKE effect on server side to be optional
* [Battle] Allowed BattleAction have multiple destinations
* [Spells] Converted limit|immunity to target condition
* [Spells] Use partial configuration reload for backward compatibility handling
* [Tests] Started tests for CUnitState
* Partial fixes of fire shield effect
* [Battle] Do HP calculations in 64 bits
* [BattleAI] Use threading for spell cast evaluation
* [BattleAI] Made AI be able to evaluate modified turn order (on hypothetical battle state)
* Implemented https://bugs.vcmi.eu/view.php?id=2811
* plug rare freeze when hypnotized unit shots vertically
* Correctly apply ONLY_MELEE_FIGHT / ONLY_DISTANCE_FIGHT for unit damage, attack & defense
* [BattleAI] Try to not waste a cast if battle is actually won already
* Extended JsonSerializeFormat API
* fixed https://bugs.vcmi.eu/view.php?id=2847
* Any unit effect can be now chained (not only damage like Chain Lightning)
** only damage effect for now actually uses "chainFactor"
* Possible quick fix for https://bugs.vcmi.eu/view.php?id=2860
This commit is contained in:
AlexVinS
2017-07-20 07:08:49 +03:00
parent ff2d01a03d
commit 0b70baa95e
256 changed files with 20904 additions and 7964 deletions

View File

@@ -625,7 +625,7 @@ void CGCreature::serializeJsonOptions(JsonSerializeFormat & handler)
resources.serializeJson(handler, "rewardResources");
handler.serializeId("rewardArtifact", gainedArtifact, ArtifactID(ArtifactID::NONE), &CArtHandler::decodeArfifact, &CArtHandler::encodeArtifact);
handler.serializeId("rewardArtifact", gainedArtifact, ArtifactID(ArtifactID::NONE));
handler.serializeBool("noGrowing", notGrowingTeam);
handler.serializeBool("neverFlees", neverFlees);
@@ -780,25 +780,27 @@ void CGMine::serializeJsonOptions(JsonSerializeFormat & handler)
if(isAbandoned())
{
auto possibleResources = handler.enterStruct("possibleResources");
JsonNode & node = handler.getCurrent();
if(handler.saving)
{
JsonNode node(JsonNode::JsonType::DATA_VECTOR);
for(int i = 0; i < PlayerColor::PLAYER_LIMIT_I; i++)
{
if(tempOwner.getNum() & 1<<i)
{
JsonNode one(JsonNode::JsonType::DATA_STRING);
one.String() = GameConstants::RESOURCE_NAMES[i];
node.Vector().push_back(one);
}
}
handler.serializeRaw("possibleResources", node, boost::none);
}
else
{
auto guard = handler.enterArray("possibleResources");
const JsonNode & node = handler.getCurrent();
std::set<int> possibleResources;
if(node.Vector().size() == 0)
if(node.getType() != JsonNode::JsonType::DATA_VECTOR || node.Vector().size() == 0)
{
//assume all allowed
for(int i = (int)Res::WOOD; i < (int) Res::GOLD; i++)
@@ -1429,7 +1431,7 @@ void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
const std::shared_ptr<Bonus> b = storedArtifact->getBonusLocalFirst(Selector::type(Bonus::SPELL));
SpellID spellId(b->subtype);
handler.serializeId("spell", spellId, SpellID::NONE, &CSpellHandler::decodeSpell, &CSpellHandler::encodeSpell);
handler.serializeId("spell", spellId, SpellID::NONE);
}
}
@@ -1653,9 +1655,9 @@ std::string CGShrine::getHoverText(const CGHeroInstance * hero) const
return hoverName;
}
void CGShrine::serializeJsonOptions(JsonSerializeFormat& handler)
void CGShrine::serializeJsonOptions(JsonSerializeFormat & handler)
{
handler.serializeId("spell", spell, SpellID::NONE, &CSpellHandler::decodeSpell, &CSpellHandler::encodeSpell);
handler.serializeId("spell", spell, SpellID::NONE);
}
void CGSignBottle::initObj(CRandomGenerator & rand)
@@ -1758,19 +1760,22 @@ void CGScholar::initObj(CRandomGenerator & rand)
void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler)
{
JsonNode& json = handler.getCurrent();
if(handler.saving)
{
std::string value;
switch(bonusType)
{
case PRIM_SKILL:
json["rewardPrimSkill"].String() = PrimarySkill::names[bonusID];
value = PrimarySkill::names[bonusID];
handler.serializeString("rewardPrimSkill", value);
break;
case SECONDARY_SKILL:
json["rewardSkill"].String() = NSecondarySkill::names[bonusID];
value = NSecondarySkill::names[bonusID];
handler.serializeString("rewardSkill", value);
break;
case SPELL:
json["rewardSpell"].String() = VLC->spellh->objects.at(bonusID)->identifier;
value = VLC->spellh->objects.at(bonusID)->identifier;
handler.serializeString("rewardSpell", value);
break;
case RANDOM:
break;
@@ -1778,6 +1783,8 @@ void CGScholar::serializeJsonOptions(JsonSerializeFormat & handler)
}
else
{
//TODO: unify
const JsonNode & json = handler.getCurrent();
bonusType = RANDOM;
if(json["rewardPrimSkill"].String() != "")
{