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

Fixes issues related to spell mechanics

This commit is contained in:
nordsoft
2023-04-10 17:08:24 +04:00
parent f550457d23
commit b9cabef179
7 changed files with 44 additions and 22 deletions

View File

@@ -132,7 +132,11 @@ void CRandomRewardObjectInfo::configureReward(CRewardableObject * object, CRando
reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng); reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng);
reward.spells = JsonRandom::loadSpells(source["spells"], rng, spells); reward.spells = JsonRandom::loadSpells(source["spells"], rng, spells);
reward.creatures = JsonRandom::loadCreatures(source["creatures"], rng); reward.creatures = JsonRandom::loadCreatures(source["creatures"], rng);
reward.casts = JsonRandom::loadSpells(source["casts"], rng, spells); if(!source["spellCast"].isNull() && source["spellCast"].isStruct())
{
reward.spellCast.first = JsonRandom::loadSpell(source["spellCast"]["spell"], rng);
reward.spellCast.second = source["spellCast"]["schoolLevel"].Integer();
}
for ( auto node : source["changeCreatures"].Struct() ) for ( auto node : source["changeCreatures"].Struct() )
{ {

View File

@@ -363,13 +363,14 @@ void CRewardableObject::grantRewardAfterLevelup(const CRewardVisitInfo & info, c
cb->giveCreatures(this, hero, creatures, false); cb->giveCreatures(this, hero, creatures, false);
} }
if(!info.reward.casts.empty()) if(info.reward.spellCast.first != SpellID::NONE)
{ {
caster = std::make_unique<spells::OuterCaster>(hero, SecSkillLevel::EXPERT); caster.setActualCaster(hero);
for(const auto & c : info.reward.casts) caster.setSpellSchoolLevel(info.reward.spellCast.second);
{ cb->castSpell(&caster, info.reward.spellCast.first, int3{-1, -1, -1});
cb->castSpell(caster.get(), c, int3{-1, -1, -1});
} if(info.reward.removeObject)
logMod->warn("Removal of object with spell casts is not supported!");
} }
else if(info.reward.removeObject) //FIXME: object can't track spell cancel or finish, so removeObject leads to crash else if(info.reward.removeObject) //FIXME: object can't track spell cancel or finish, so removeObject leads to crash
cb->removeObject(this); cb->removeObject(this);

View File

@@ -171,8 +171,8 @@ public:
std::vector<SpellID> spells; std::vector<SpellID> spells;
std::vector<CStackBasicDescriptor> creatures; std::vector<CStackBasicDescriptor> creatures;
/// actions that hero may execute and object caster /// actions that hero may execute and object caster. Pair of spellID and school level
std::vector<SpellID> casts; std::pair<SpellID, int> spellCast;
/// list of components that will be added to reward description. First entry in list will override displayed component /// list of components that will be added to reward description. First entry in list will override displayed component
std::vector<Component> extraComponents; std::vector<Component> extraComponents;
@@ -195,7 +195,8 @@ public:
movePoints(0), movePoints(0),
movePercentage(-1), movePercentage(-1),
primary(4, 0), primary(4, 0),
removeObject(false) removeObject(false),
spellCast(SpellID::NONE, SecSkillLevel::NONE)
{} {}
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
@@ -217,7 +218,8 @@ public:
h & spells; h & spells;
h & creatures; h & creatures;
h & creaturesChange; h & creaturesChange;
h & casts; if(version >= 821)
h & spellCast;
} }
}; };
@@ -324,7 +326,7 @@ protected:
bool onceVisitableObjectCleared; bool onceVisitableObjectCleared;
/// caster to cast adveture spells /// caster to cast adveture spells
mutable std::unique_ptr<spells::OuterCaster> caster; mutable spells::OuterCaster caster;
public: public:
EVisitMode getVisitMode() const; EVisitMode getVisitMode() const;

View File

@@ -32,7 +32,7 @@ namespace JsonRandom
}; };
DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0); DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0);
DLL_LINKAGE std::string loadKey(const JsonNode & value, CRandomGenerator & rng, const std::set<std::string> & valuesSet); DLL_LINKAGE std::string loadKey(const JsonNode & value, CRandomGenerator & rng, const std::set<std::string> & valuesSet = {});
DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng); DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng);
DLL_LINKAGE TResources loadResource(const JsonNode & value, CRandomGenerator & rng); DLL_LINKAGE TResources loadResource(const JsonNode & value, CRandomGenerator & rng);
DLL_LINKAGE std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng); DLL_LINKAGE std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng);
@@ -41,8 +41,8 @@ namespace JsonRandom
DLL_LINKAGE ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng); DLL_LINKAGE ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng);
DLL_LINKAGE std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng); DLL_LINKAGE std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng);
DLL_LINKAGE SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells); DLL_LINKAGE SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells = {});
DLL_LINKAGE std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const std::vector<SpellID> & spells); DLL_LINKAGE std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, const std::vector<SpellID> & spells = {});
DLL_LINKAGE CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng); DLL_LINKAGE CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng);
DLL_LINKAGE std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng); DLL_LINKAGE std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng);

View File

@@ -122,13 +122,7 @@ void AdventureSpellMechanics::endCast(SpellCastEnvironment * env, const Adventur
switch(result) switch(result)
{ {
case ESpellCastResult::OK: case ESpellCastResult::OK:
{ parameters.caster->spendMana(env, cost);
SetMana sm;
sm.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
sm.absolute = false;
sm.val = -cost;
env->apply(&sm);
}
break; break;
default: default:
break; break;
@@ -584,6 +578,9 @@ std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(SpellC
int32_t TownPortalMechanics::movementCost(const AdventureSpellCastParameters & parameters) const int32_t TownPortalMechanics::movementCost(const AdventureSpellCastParameters & parameters) const
{ {
if(parameters.caster != parameters.caster->getHeroCaster()) //if caster is not hero
return 0;
return GameConstants::BASE_MOVEMENT_COST * ((parameters.caster->getSpellSchoolLevel(owner) >= 3) ? 2 : 3); return GameConstants::BASE_MOVEMENT_COST * ((parameters.caster->getSpellSchoolLevel(owner) >= 3) ? 2 : 3);
} }

View File

@@ -17,10 +17,24 @@ VCMI_LIB_NAMESPACE_BEGIN
namespace spells namespace spells
{ {
OuterCaster::OuterCaster()
: ProxyCaster(nullptr), schoolLevel(0)
{
}
OuterCaster::OuterCaster(const Caster * actualCaster_, int schoolLevel_) OuterCaster::OuterCaster(const Caster * actualCaster_, int schoolLevel_)
: ProxyCaster(actualCaster_), schoolLevel(schoolLevel_) : ProxyCaster(actualCaster_), schoolLevel(schoolLevel_)
{ {
}
void OuterCaster::setActualCaster(const Caster * actualCaster_)
{
actualCaster = actualCaster_;
}
void OuterCaster::setSpellSchoolLevel(int level)
{
schoolLevel = level;
} }
void OuterCaster::spendMana(ServerCallback * server, const int32_t spellCost) const void OuterCaster::spendMana(ServerCallback * server, const int32_t spellCost) const

View File

@@ -21,7 +21,11 @@ class DLL_LINKAGE OuterCaster : public ProxyCaster
{ {
int schoolLevel; int schoolLevel;
public: public:
OuterCaster();
OuterCaster(const Caster * actualCaster_, int schoolLevel_); OuterCaster(const Caster * actualCaster_, int schoolLevel_);
void setActualCaster(const Caster * actualCaster);
void setSpellSchoolLevel(int level);
int32_t getSpellSchoolLevel(const Spell * spell, int32_t * outSelectedSchool = nullptr) const override; int32_t getSpellSchoolLevel(const Spell * spell, int32_t * outSelectedSchool = nullptr) const override;
void spendMana(ServerCallback * server, const int32_t spellCost) const override; void spendMana(ServerCallback * server, const int32_t spellCost) const override;