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:
@@ -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() != "")
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user