mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
commit
ebd17c9e4a
@ -231,6 +231,7 @@ public:
|
|||||||
void changeObjPos(ObjectInstanceID objid, int3 newPos) override {};
|
void changeObjPos(ObjectInstanceID objid, int3 newPos) override {};
|
||||||
void sendAndApply(CPackForClient * pack) override {};
|
void sendAndApply(CPackForClient * pack) override {};
|
||||||
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {};
|
void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2) override {};
|
||||||
|
void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override {};
|
||||||
|
|
||||||
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {}
|
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {}
|
||||||
void changeFogOfWar(std::unordered_set<int3, ShashInt3> & tiles, PlayerColor player, bool hide) override {}
|
void changeFogOfWar(std::unordered_set<int3, ShashInt3> & tiles, PlayerColor player, bool hide) override {}
|
||||||
|
@ -134,6 +134,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.cpp
|
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.cpp
|
||||||
${MAIN_LIB_DIR}/spells/BonusCaster.cpp
|
${MAIN_LIB_DIR}/spells/BonusCaster.cpp
|
||||||
${MAIN_LIB_DIR}/spells/CSpellHandler.cpp
|
${MAIN_LIB_DIR}/spells/CSpellHandler.cpp
|
||||||
|
${MAIN_LIB_DIR}/spells/ExternalCaster.cpp
|
||||||
${MAIN_LIB_DIR}/spells/ISpellMechanics.cpp
|
${MAIN_LIB_DIR}/spells/ISpellMechanics.cpp
|
||||||
${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.cpp
|
${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.cpp
|
||||||
${MAIN_LIB_DIR}/spells/Problem.cpp
|
${MAIN_LIB_DIR}/spells/Problem.cpp
|
||||||
@ -397,7 +398,9 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.h
|
${MAIN_LIB_DIR}/spells/BattleSpellMechanics.h
|
||||||
${MAIN_LIB_DIR}/spells/BonusCaster.h
|
${MAIN_LIB_DIR}/spells/BonusCaster.h
|
||||||
${MAIN_LIB_DIR}/spells/CSpellHandler.h
|
${MAIN_LIB_DIR}/spells/CSpellHandler.h
|
||||||
|
${MAIN_LIB_DIR}/spells/ExternalCaster.h
|
||||||
${MAIN_LIB_DIR}/spells/ISpellMechanics.h
|
${MAIN_LIB_DIR}/spells/ISpellMechanics.h
|
||||||
|
${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.h
|
||||||
${MAIN_LIB_DIR}/spells/Problem.h
|
${MAIN_LIB_DIR}/spells/Problem.h
|
||||||
${MAIN_LIB_DIR}/spells/ProxyCaster.h
|
${MAIN_LIB_DIR}/spells/ProxyCaster.h
|
||||||
${MAIN_LIB_DIR}/spells/TargetCondition.h
|
${MAIN_LIB_DIR}/spells/TargetCondition.h
|
||||||
|
@ -15,6 +15,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
|||||||
class PlayerColor;
|
class PlayerColor;
|
||||||
struct MetaString;
|
struct MetaString;
|
||||||
class ServerCallback;
|
class ServerCallback;
|
||||||
|
class CGHeroInstance;
|
||||||
|
|
||||||
namespace battle
|
namespace battle
|
||||||
{
|
{
|
||||||
@ -65,6 +66,9 @@ public:
|
|||||||
virtual void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const = 0;
|
virtual void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const = 0;
|
||||||
|
|
||||||
virtual void spendMana(ServerCallback * server, const int32_t spellCost) const = 0;
|
virtual void spendMana(ServerCallback * server, const int32_t spellCost) const = 0;
|
||||||
|
|
||||||
|
///used to identify actual hero caster
|
||||||
|
virtual const CGHeroInstance * getHeroCaster() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,11 @@ class CStackBasicDescriptor;
|
|||||||
class CGCreature;
|
class CGCreature;
|
||||||
struct ShashInt3;
|
struct ShashInt3;
|
||||||
|
|
||||||
|
namespace spells
|
||||||
|
{
|
||||||
|
class Caster;
|
||||||
|
}
|
||||||
|
|
||||||
#if SCRIPTING_ENABLED
|
#if SCRIPTING_ENABLED
|
||||||
namespace scripting
|
namespace scripting
|
||||||
{
|
{
|
||||||
@ -132,6 +137,8 @@ public:
|
|||||||
virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map
|
virtual void heroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2)=0; //when two heroes meet on adventure map
|
||||||
virtual void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) = 0;
|
virtual void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) = 0;
|
||||||
virtual void changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide) = 0;
|
virtual void changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide) = 0;
|
||||||
|
|
||||||
|
virtual void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_LINKAGE CNonConstInfoCallback : public CPrivilegedInfoCallback
|
class DLL_LINKAGE CNonConstInfoCallback : public CPrivilegedInfoCallback
|
||||||
|
@ -418,6 +418,11 @@ int32_t CUnitState::getCasterUnitId() const
|
|||||||
return static_cast<int32_t>(unitId());
|
return static_cast<int32_t>(unitId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CGHeroInstance * CUnitState::getHeroCaster() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t CUnitState::getSpellSchoolLevel(const spells::Spell * spell, int32_t * outSelectedSchool) const
|
int32_t CUnitState::getSpellSchoolLevel(const spells::Spell * spell, int32_t * outSelectedSchool) const
|
||||||
{
|
{
|
||||||
int32_t skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->getIndex()));
|
int32_t skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->getIndex()));
|
||||||
|
@ -192,6 +192,7 @@ public:
|
|||||||
int64_t getEffectValue(const spells::Spell * spell) const override;
|
int64_t getEffectValue(const spells::Spell * spell) const override;
|
||||||
|
|
||||||
PlayerColor getCasterOwner() const override;
|
PlayerColor getCasterOwner() const override;
|
||||||
|
const CGHeroInstance * getHeroCaster() const override;
|
||||||
void getCasterName(MetaString & text) const override;
|
void getCasterName(MetaString & text) const override;
|
||||||
void getCastDescription(const spells::Spell * spell, const std::vector<const Unit *> & attacked, MetaString & text) const override;
|
void getCastDescription(const spells::Spell * spell, const std::vector<const Unit *> & attacked, MetaString & text) const override;
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ TExpType CGHeroInstance::calculateXp(TExpType exp) const
|
|||||||
|
|
||||||
int32_t CGHeroInstance::getCasterUnitId() const
|
int32_t CGHeroInstance::getCasterUnitId() const
|
||||||
{
|
{
|
||||||
return -1; //TODO: special value for attacker/defender hero
|
return id.getNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CGHeroInstance::getSpellSchoolLevel(const spells::Spell * spell, int32_t * outSelectedSchool) const
|
int32_t CGHeroInstance::getSpellSchoolLevel(const spells::Spell * spell, int32_t * outSelectedSchool) const
|
||||||
@ -669,6 +669,11 @@ void CGHeroInstance::getCastDescription(const spells::Spell * spell, const std::
|
|||||||
attacked.at(0)->addNameReplacement(text, true);
|
attacked.at(0)->addNameReplacement(text, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CGHeroInstance * CGHeroInstance::getHeroCaster() const
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
void CGHeroInstance::spendMana(ServerCallback * server, const int spellCost) const
|
void CGHeroInstance::spendMana(ServerCallback * server, const int spellCost) const
|
||||||
{
|
{
|
||||||
if(spellCost != 0)
|
if(spellCost != 0)
|
||||||
|
@ -275,6 +275,7 @@ public:
|
|||||||
int64_t getEffectValue(const spells::Spell * spell) const override;
|
int64_t getEffectValue(const spells::Spell * spell) const override;
|
||||||
|
|
||||||
PlayerColor getCasterOwner() const override;
|
PlayerColor getCasterOwner() const override;
|
||||||
|
const CGHeroInstance * getHeroCaster() const override;
|
||||||
|
|
||||||
void getCasterName(MetaString & text) const override;
|
void getCasterName(MetaString & text) const override;
|
||||||
void getCastDescription(const spells::Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override;
|
void getCastDescription(const spells::Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override;
|
||||||
|
@ -132,6 +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);
|
||||||
|
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() )
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include "../IGameCallback.h"
|
#include "../IGameCallback.h"
|
||||||
#include "../CGameState.h"
|
#include "../CGameState.h"
|
||||||
#include "../CPlayerState.h"
|
#include "../CPlayerState.h"
|
||||||
|
#include "../spells/CSpellHandler.h"
|
||||||
|
#include "../spells/ISpellMechanics.h"
|
||||||
|
|
||||||
#include "CObjectClassesHandler.h"
|
#include "CObjectClassesHandler.h"
|
||||||
|
|
||||||
@ -142,7 +144,8 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
|
|||||||
iw.text = vi.message;
|
iw.text = vi.message;
|
||||||
vi.reward.loadComponents(iw.components, h);
|
vi.reward.loadComponents(iw.components, h);
|
||||||
iw.type = infoWindowType;
|
iw.type = infoWindowType;
|
||||||
cb->showInfoDialog(&iw);
|
if(!iw.components.empty() || !iw.text.toString().empty())
|
||||||
|
cb->showInfoDialog(&iw);
|
||||||
}
|
}
|
||||||
// grant reward afterwards. Note that it may remove object
|
// grant reward afterwards. Note that it may remove object
|
||||||
grantReward(index, h, markAsVisit);
|
grantReward(index, h, markAsVisit);
|
||||||
@ -359,8 +362,17 @@ void CRewardableObject::grantRewardAfterLevelup(const CRewardVisitInfo & info, c
|
|||||||
|
|
||||||
cb->giveCreatures(this, hero, creatures, false);
|
cb->giveCreatures(this, hero, creatures, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info.reward.removeObject)
|
if(info.reward.spellCast.first != SpellID::NONE)
|
||||||
|
{
|
||||||
|
caster.setActualCaster(hero);
|
||||||
|
caster.setSpellSchoolLevel(info.reward.spellCast.second);
|
||||||
|
cb->castSpell(&caster, info.reward.spellCast.first, 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
|
||||||
cb->removeObject(this);
|
cb->removeObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "../NetPacksBase.h"
|
#include "../NetPacksBase.h"
|
||||||
#include "../ResourceSet.h"
|
#include "../ResourceSet.h"
|
||||||
|
#include "../spells/ExternalCaster.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -169,6 +170,9 @@ public:
|
|||||||
std::vector<ArtifactID> artifacts;
|
std::vector<ArtifactID> artifacts;
|
||||||
std::vector<SpellID> spells;
|
std::vector<SpellID> spells;
|
||||||
std::vector<CStackBasicDescriptor> creatures;
|
std::vector<CStackBasicDescriptor> creatures;
|
||||||
|
|
||||||
|
/// actions that hero may execute and object caster. Pair of spellID and school level
|
||||||
|
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;
|
||||||
@ -191,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)
|
||||||
@ -213,6 +218,8 @@ public:
|
|||||||
h & spells;
|
h & spells;
|
||||||
h & creatures;
|
h & creatures;
|
||||||
h & creaturesChange;
|
h & creaturesChange;
|
||||||
|
if(version >= 821)
|
||||||
|
h & spellCast;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -317,6 +324,9 @@ protected:
|
|||||||
bool wasVisitedBefore(const CGHeroInstance * contextHero) const;
|
bool wasVisitedBefore(const CGHeroInstance * contextHero) const;
|
||||||
|
|
||||||
bool onceVisitableObjectCleared;
|
bool onceVisitableObjectCleared;
|
||||||
|
|
||||||
|
/// caster to cast adveture spells
|
||||||
|
mutable spells::ExternalCaster caster;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EVisitMode getVisitMode() const;
|
EVisitMode getVisitMode() const;
|
||||||
|
@ -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);
|
||||||
|
@ -37,27 +37,28 @@ bool AdventureSpellMechanics::adventureCast(SpellCastEnvironment * env, const Ad
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGHeroInstance * caster = parameters.caster;
|
if(const CGHeroInstance * heroCaster = dynamic_cast<const CGHeroInstance *>(parameters.caster))
|
||||||
|
|
||||||
if(caster->inTownGarrison)
|
|
||||||
{
|
{
|
||||||
env->complain("Attempt to cast an adventure spell in town garrison");
|
if(heroCaster->inTownGarrison)
|
||||||
return false;
|
{
|
||||||
}
|
env->complain("Attempt to cast an adventure spell in town garrison");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto level = caster->getSpellSchoolLevel(owner);
|
const auto level = heroCaster->getSpellSchoolLevel(owner);
|
||||||
const auto cost = owner->getCost(level);
|
const auto cost = owner->getCost(level);
|
||||||
|
|
||||||
if(!caster->canCastThisSpell(owner))
|
if(!heroCaster->canCastThisSpell(owner))
|
||||||
{
|
{
|
||||||
env->complain("Hero cannot cast this spell!");
|
env->complain("Hero cannot cast this spell!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(caster->mana < cost)
|
if(heroCaster->mana < cost)
|
||||||
{
|
{
|
||||||
env->complain("Hero doesn't have enough spell points to cast this spell!");
|
env->complain("Hero doesn't have enough spell points to cast this spell!");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ESpellCastResult result = beginCast(env, parameters);
|
ESpellCastResult result = beginCast(env, parameters);
|
||||||
@ -82,7 +83,7 @@ ESpellCastResult AdventureSpellMechanics::applyAdventureEffects(SpellCastEnviron
|
|||||||
for(const Bonus & b : bonuses)
|
for(const Bonus & b : bonuses)
|
||||||
{
|
{
|
||||||
GiveBonus gb;
|
GiveBonus gb;
|
||||||
gb.id = parameters.caster->id.getNum();
|
gb.id = parameters.caster->getCasterUnitId();
|
||||||
gb.bonus = b;
|
gb.bonus = b;
|
||||||
env->apply(&gb);
|
env->apply(&gb);
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ ESpellCastResult AdventureSpellMechanics::beginCast(SpellCastEnvironment * env,
|
|||||||
void AdventureSpellMechanics::performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
void AdventureSpellMechanics::performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
{
|
{
|
||||||
AdvmapSpellCast asc;
|
AdvmapSpellCast asc;
|
||||||
asc.casterID = parameters.caster->id;
|
asc.casterID = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
asc.spellID = owner->id;
|
asc.spellID = owner->id;
|
||||||
env->apply(&asc);
|
env->apply(&asc);
|
||||||
|
|
||||||
@ -121,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 = parameters.caster->id;
|
|
||||||
sm.absolute = false;
|
|
||||||
sm.val = -cost;
|
|
||||||
env->apply(&sm);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -142,21 +137,28 @@ SummonBoatMechanics::SummonBoatMechanics(const CSpell * s):
|
|||||||
|
|
||||||
ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
{
|
{
|
||||||
if(parameters.caster->boat)
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
{
|
||||||
|
env->complain("Not a hero caster!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(parameters.caster->getHeroCaster()->boat)
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 333);//%s is already in boat
|
iw.text.addTxt(MetaString::GENERAL_TXT, 333);//%s is already in boat
|
||||||
iw.text.addReplacement(parameters.caster->getNameTranslated());
|
parameters.caster->getCasterName(iw.text);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::CANCEL;
|
return ESpellCastResult::CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int3 summonPos = parameters.caster->bestLocation();
|
int3 summonPos = parameters.caster->getHeroCaster()->bestLocation();
|
||||||
|
|
||||||
if(summonPos.x < 0)
|
if(summonPos.x < 0)
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 334);//There is no place to put the boat.
|
iw.text.addTxt(MetaString::GENERAL_TXT, 334);//There is no place to put the boat.
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::CANCEL;
|
return ESpellCastResult::CANCEL;
|
||||||
@ -168,9 +170,9 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
|
iw.text.addTxt(MetaString::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
|
||||||
iw.text.addReplacement(parameters.caster->getNameTranslated());
|
parameters.caster->getCasterName(iw.text);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::OK;
|
return ESpellCastResult::OK;
|
||||||
}
|
}
|
||||||
@ -186,7 +188,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
if(b->hero)
|
if(b->hero)
|
||||||
continue; //we're looking for unoccupied boat
|
continue; //we're looking for unoccupied boat
|
||||||
|
|
||||||
double nDist = b->pos.dist2d(parameters.caster->visitablePos());
|
double nDist = b->pos.dist2d(parameters.caster->getHeroCaster()->visitablePos());
|
||||||
if(!nearest || nDist < dist) //it's first boat or closer than previous
|
if(!nearest || nDist < dist) //it's first boat or closer than previous
|
||||||
{
|
{
|
||||||
nearest = b;
|
nearest = b;
|
||||||
@ -205,7 +207,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
else if(schoolLevel < 2) //none or basic level -> cannot create boat :(
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 335); //There are no boats to summon.
|
iw.text.addTxt(MetaString::GENERAL_TXT, 335); //There are no boats to summon.
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
}
|
}
|
||||||
@ -213,7 +215,7 @@ ESpellCastResult SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
{
|
{
|
||||||
NewObject no;
|
NewObject no;
|
||||||
no.ID = Obj::BOAT;
|
no.ID = Obj::BOAT;
|
||||||
no.subID = parameters.caster->getBoatType();
|
no.subID = parameters.caster->getHeroCaster()->getBoatType();
|
||||||
no.pos = summonPos + int3(1,0,0);
|
no.pos = summonPos + int3(1,0,0);
|
||||||
env->apply(&no);
|
env->apply(&no);
|
||||||
}
|
}
|
||||||
@ -233,9 +235,9 @@ ESpellCastResult ScuttleBoatMechanics::applyAdventureEffects(SpellCastEnvironmen
|
|||||||
if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
if(env->getRNG()->getInt64Range(0, 99)() >= owner->getLevelPower(schoolLevel)) //power is % chance of success
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
|
iw.text.addTxt(MetaString::GENERAL_TXT, 337); //%s tried to scuttle the boat, but failed
|
||||||
iw.text.addReplacement(parameters.caster->getNameTranslated());
|
parameters.caster->getCasterName(iw.text);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::OK;
|
return ESpellCastResult::OK;
|
||||||
}
|
}
|
||||||
@ -273,9 +275,15 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
|
|||||||
env->complain("Destination is out of map!");
|
env->complain("Destination is out of map!");
|
||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
{
|
||||||
|
env->complain("Not a hero caster!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
|
const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
|
||||||
const TerrainTile * curr = env->getCb()->getTile(parameters.caster->getSightCenter());
|
const TerrainTile * curr = env->getCb()->getTile(parameters.caster->getHeroCaster()->getSightCenter());
|
||||||
|
|
||||||
if(nullptr == dest)
|
if(nullptr == dest)
|
||||||
{
|
{
|
||||||
@ -289,7 +297,7 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
|
|||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parameters.caster->movement <= 0) //unlike town portal non-zero MP is enough
|
if(parameters.caster->getHeroCaster()->movement <= 0) //unlike town portal non-zero MP is enough
|
||||||
{
|
{
|
||||||
env->complain("Hero needs movement points to cast Dimension Door!");
|
env->complain("Hero needs movement points to cast Dimension Door!");
|
||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
@ -301,34 +309,34 @@ ESpellCastResult DimensionDoorMechanics::applyAdventureEffects(SpellCastEnvironm
|
|||||||
std::stringstream cachingStr;
|
std::stringstream cachingStr;
|
||||||
cachingStr << "source_" << Bonus::SPELL_EFFECT << "id_" << owner->id.num;
|
cachingStr << "source_" << Bonus::SPELL_EFFECT << "id_" << owner->id.num;
|
||||||
|
|
||||||
if(parameters.caster->getBonuses(Selector::source(Bonus::SPELL_EFFECT, owner->id), Selector::all, cachingStr.str())->size() >= owner->getLevelPower(schoolLevel)) //limit casts per turn
|
if(parameters.caster->getHeroCaster()->getBonuses(Selector::source(Bonus::SPELL_EFFECT, owner->id), Selector::all, cachingStr.str())->size() >= owner->getLevelPower(schoolLevel)) //limit casts per turn
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today.
|
iw.text.addTxt(MetaString::GENERAL_TXT, 338); //%s is not skilled enough to cast this spell again today.
|
||||||
iw.text.addReplacement(parameters.caster->getNameTranslated());
|
parameters.caster->getCasterName(iw.text);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::CANCEL;
|
return ESpellCastResult::CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GiveBonus gb;
|
GiveBonus gb;
|
||||||
gb.id = parameters.caster->id.getNum();
|
gb.id = parameters.caster->getCasterUnitId();
|
||||||
gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::SPELL_EFFECT, 0, owner->id);
|
gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::SPELL_EFFECT, 0, owner->id);
|
||||||
env->apply(&gb);
|
env->apply(&gb);
|
||||||
|
|
||||||
if(!dest->isClear(curr)) //wrong dest tile
|
if(!dest->isClear(curr)) //wrong dest tile
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 70); //Dimension Door failed!
|
iw.text.addTxt(MetaString::GENERAL_TXT, 70); //Dimension Door failed!
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
}
|
}
|
||||||
else if(env->moveHero(parameters.caster->id, parameters.caster->convertFromVisitablePos(parameters.pos), true))
|
else if(env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(parameters.pos), true))
|
||||||
{
|
{
|
||||||
SetMovePoints smp;
|
SetMovePoints smp;
|
||||||
smp.hid = parameters.caster->id;
|
smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
if(movementCost < static_cast<int>(parameters.caster->movement))
|
if(movementCost < static_cast<int>(parameters.caster->getHeroCaster()->movement))
|
||||||
smp.val = parameters.caster->movement - movementCost;
|
smp.val = parameters.caster->getHeroCaster()->movement - movementCost;
|
||||||
else
|
else
|
||||||
smp.val = 0;
|
smp.val = 0;
|
||||||
env->apply(&smp);
|
env->apply(&smp);
|
||||||
@ -346,6 +354,12 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
{
|
{
|
||||||
const CGTownInstance * destination = nullptr;
|
const CGTownInstance * destination = nullptr;
|
||||||
const int moveCost = movementCost(parameters);
|
const int moveCost = movementCost(parameters);
|
||||||
|
|
||||||
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
{
|
||||||
|
env->complain("Not a hero caster!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
|
if(parameters.caster->getSpellSchoolLevel(owner) < 2)
|
||||||
{
|
{
|
||||||
@ -355,13 +369,13 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
if(nullptr == destination)
|
if(nullptr == destination)
|
||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
|
|
||||||
if(static_cast<int>(parameters.caster->movement) < moveCost)
|
if(static_cast<int>(parameters.caster->getHeroCaster()->movement) < moveCost)
|
||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
|
|
||||||
if(destination->visitingHero)
|
if(destination->visitingHero)
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 123);
|
iw.text.addTxt(MetaString::GENERAL_TXT, 123);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::CANCEL;
|
return ESpellCastResult::CANCEL;
|
||||||
@ -397,7 +411,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto relations = env->getCb()->getPlayerRelations(destination->tempOwner, parameters.caster->tempOwner);
|
const auto relations = env->getCb()->getPlayerRelations(destination->tempOwner, parameters.caster->getCasterOwner());
|
||||||
|
|
||||||
if(relations == PlayerRelations::ENEMIES)
|
if(relations == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
@ -405,7 +419,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(static_cast<int>(parameters.caster->movement) < moveCost)
|
if(static_cast<int>(parameters.caster->getHeroCaster()->movement) < moveCost)
|
||||||
{
|
{
|
||||||
env->complain("This hero has not enough movement points!");
|
env->complain("This hero has not enough movement points!");
|
||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
@ -423,11 +437,11 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(env->moveHero(parameters.caster->id, parameters.caster->convertFromVisitablePos(destination->visitablePos()), true))
|
if(env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(destination->visitablePos()), true))
|
||||||
{
|
{
|
||||||
SetMovePoints smp;
|
SetMovePoints smp;
|
||||||
smp.hid = parameters.caster->id;
|
smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
|
||||||
smp.val = std::max<ui32>(0, parameters.caster->movement - moveCost);
|
smp.val = std::max<ui32>(0, parameters.caster->getHeroCaster()->movement - moveCost);
|
||||||
env->apply(&smp);
|
env->apply(&smp);
|
||||||
}
|
}
|
||||||
return ESpellCastResult::OK;
|
return ESpellCastResult::OK;
|
||||||
@ -436,11 +450,17 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||||||
{
|
{
|
||||||
std::vector<const CGTownInstance *> towns = getPossibleTowns(env, parameters);
|
std::vector<const CGTownInstance *> towns = getPossibleTowns(env, parameters);
|
||||||
|
|
||||||
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
{
|
||||||
|
env->complain("Not a hero caster!");
|
||||||
|
return ESpellCastResult::ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if(towns.empty())
|
if(towns.empty())
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 124);
|
iw.text.addTxt(MetaString::GENERAL_TXT, 124);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::CANCEL;
|
return ESpellCastResult::CANCEL;
|
||||||
@ -448,10 +468,10 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
|
|||||||
|
|
||||||
const int moveCost = movementCost(parameters);
|
const int moveCost = movementCost(parameters);
|
||||||
|
|
||||||
if(static_cast<int>(parameters.caster->movement) < moveCost)
|
if(static_cast<int>(parameters.caster->getHeroCaster()->movement) < moveCost)
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 125);
|
iw.text.addTxt(MetaString::GENERAL_TXT, 125);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::CANCEL;
|
return ESpellCastResult::CANCEL;
|
||||||
@ -496,13 +516,13 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
|
|||||||
if(request.objects.empty())
|
if(request.objects.empty())
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->tempOwner;
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
iw.text.addTxt(MetaString::GENERAL_TXT, 124);
|
iw.text.addTxt(MetaString::GENERAL_TXT, 124);
|
||||||
env->apply(&iw);
|
env->apply(&iw);
|
||||||
return ESpellCastResult::CANCEL;
|
return ESpellCastResult::CANCEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
request.player = parameters.caster->getOwner();
|
request.player = parameters.caster->getCasterOwner();
|
||||||
request.title.addTxt(MetaString::JK_TXT, 40);
|
request.title.addTxt(MetaString::JK_TXT, 40);
|
||||||
request.description.addTxt(MetaString::JK_TXT, 41);
|
request.description.addTxt(MetaString::JK_TXT, 41);
|
||||||
request.icon.id = Component::EComponentType::SPELL;
|
request.icon.id = Component::EComponentType::SPELL;
|
||||||
@ -520,13 +540,16 @@ const CGTownInstance * TownPortalMechanics::findNearestTown(SpellCastEnvironment
|
|||||||
{
|
{
|
||||||
if(pool.empty())
|
if(pool.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
if(!parameters.caster->getHeroCaster())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
auto nearest = pool.cbegin(); //nearest town's iterator
|
auto nearest = pool.cbegin(); //nearest town's iterator
|
||||||
si32 dist = (*nearest)->pos.dist2dSQ(parameters.caster->pos);
|
si32 dist = (*nearest)->pos.dist2dSQ(parameters.caster->getHeroCaster()->pos);
|
||||||
|
|
||||||
for(auto i = nearest + 1; i != pool.cend(); ++i)
|
for(auto i = nearest + 1; i != pool.cend(); ++i)
|
||||||
{
|
{
|
||||||
si32 curDist = (*i)->pos.dist2dSQ(parameters.caster->pos);
|
si32 curDist = (*i)->pos.dist2dSQ(parameters.caster->getHeroCaster()->pos);
|
||||||
|
|
||||||
if(curDist < dist)
|
if(curDist < dist)
|
||||||
{
|
{
|
||||||
@ -541,7 +564,7 @@ std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(SpellC
|
|||||||
{
|
{
|
||||||
std::vector <const CGTownInstance*> ret;
|
std::vector <const CGTownInstance*> ret;
|
||||||
|
|
||||||
const TeamState * team = env->getCb()->getPlayerTeam(parameters.caster->getOwner());
|
const TeamState * team = env->getCb()->getPlayerTeam(parameters.caster->getCasterOwner());
|
||||||
|
|
||||||
for(const auto & color : team->players)
|
for(const auto & color : team->players)
|
||||||
{
|
{
|
||||||
@ -555,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,11 +594,11 @@ ESpellCastResult ViewMechanics::applyAdventureEffects(SpellCastEnvironment * env
|
|||||||
{
|
{
|
||||||
ShowWorldViewEx pack;
|
ShowWorldViewEx pack;
|
||||||
|
|
||||||
pack.player = parameters.caster->getOwner();
|
pack.player = parameters.caster->getCasterOwner();
|
||||||
|
|
||||||
const auto spellLevel = parameters.caster->getSpellSchoolLevel(owner);
|
const auto spellLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||||||
|
|
||||||
const auto fowMap = env->getCb()->getPlayerTeam(parameters.caster->getOwner())->fogOfWarMap;
|
const auto fowMap = env->getCb()->getPlayerTeam(parameters.caster->getCasterOwner())->fogOfWarMap;
|
||||||
|
|
||||||
for(const CGObjectInstance * obj : env->getMap()->objects)
|
for(const CGObjectInstance * obj : env->getMap()->objects)
|
||||||
{
|
{
|
||||||
|
52
lib/spells/ExternalCaster.cpp
Normal file
52
lib/spells/ExternalCaster.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* ExternalCaster.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
|
||||||
|
#include "ExternalCaster.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
namespace spells
|
||||||
|
{
|
||||||
|
|
||||||
|
ExternalCaster::ExternalCaster()
|
||||||
|
: ProxyCaster(nullptr), schoolLevel(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalCaster::ExternalCaster(const Caster * actualCaster_, int schoolLevel_)
|
||||||
|
: ProxyCaster(actualCaster_), schoolLevel(schoolLevel_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalCaster::setActualCaster(const Caster * actualCaster_)
|
||||||
|
{
|
||||||
|
actualCaster = actualCaster_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalCaster::setSpellSchoolLevel(int level)
|
||||||
|
{
|
||||||
|
schoolLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalCaster::spendMana(ServerCallback * server, const int32_t spellCost) const
|
||||||
|
{
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ExternalCaster::getSpellSchoolLevel(const Spell * spell, int32_t * outSelectedSchool) const
|
||||||
|
{
|
||||||
|
return schoolLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
36
lib/spells/ExternalCaster.h
Normal file
36
lib/spells/ExternalCaster.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* ExternalCaster.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ProxyCaster.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
namespace spells
|
||||||
|
{
|
||||||
|
|
||||||
|
class DLL_LINKAGE ExternalCaster : public ProxyCaster
|
||||||
|
{
|
||||||
|
int schoolLevel;
|
||||||
|
public:
|
||||||
|
ExternalCaster();
|
||||||
|
ExternalCaster(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;
|
||||||
|
void spendMana(ServerCallback * server, const int32_t spellCost) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace spells
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -350,7 +350,7 @@ public:
|
|||||||
class DLL_LINKAGE AdventureSpellCastParameters
|
class DLL_LINKAGE AdventureSpellCastParameters
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const CGHeroInstance * caster;
|
const spells::Caster * caster;
|
||||||
int3 pos;
|
int3 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,6 +118,14 @@ void ProxyCaster::spendMana(ServerCallback * server, const int32_t spellCost) co
|
|||||||
actualCaster->spendMana(server, spellCost);
|
actualCaster->spendMana(server, spellCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CGHeroInstance * ProxyCaster::getHeroCaster() const
|
||||||
|
{
|
||||||
|
if(actualCaster)
|
||||||
|
return actualCaster->getHeroCaster();
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
void getCasterName(MetaString & text) const override;
|
void getCasterName(MetaString & text) const override;
|
||||||
void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override;
|
void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override;
|
||||||
void spendMana(ServerCallback * server, const int32_t spellCost) const override;
|
void spendMana(ServerCallback * server, const int32_t spellCost) const override;
|
||||||
|
const CGHeroInstance * getHeroCaster() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const Caster * actualCaster;
|
const Caster * actualCaster;
|
||||||
|
@ -6299,6 +6299,19 @@ bool CGameHandler::moveStack(const StackLocation &src, const StackLocation &dst,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGameHandler::castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos)
|
||||||
|
{
|
||||||
|
const CSpell * s = spellID.toSpell();
|
||||||
|
if(!s)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AdventureSpellCastParameters p;
|
||||||
|
p.caster = caster;
|
||||||
|
p.pos = pos;
|
||||||
|
|
||||||
|
s->adventureCast(spellEnv, p);
|
||||||
|
}
|
||||||
|
|
||||||
bool CGameHandler::swapStacks(const StackLocation & sl1, const StackLocation & sl2)
|
bool CGameHandler::swapStacks(const StackLocation & sl1, const StackLocation & sl2)
|
||||||
{
|
{
|
||||||
if(!sl1.army->hasStackAtSlot(sl1.slot))
|
if(!sl1.army->hasStackAtSlot(sl1.slot))
|
||||||
@ -7360,4 +7373,4 @@ const ObjectInstanceID CGameHandler::putNewObject(Obj ID, int subID, int3 pos)
|
|||||||
no.pos = pos;
|
no.pos = pos;
|
||||||
sendAndApply(&no);
|
sendAndApply(&no);
|
||||||
return no.id; //id field will be filled during applying on gs
|
return no.id; //id field will be filled during applying on gs
|
||||||
}
|
}
|
||||||
|
@ -200,6 +200,8 @@ public:
|
|||||||
|
|
||||||
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override;
|
void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override;
|
||||||
void changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide) override;
|
void changeFogOfWar(std::unordered_set<int3, ShashInt3> &tiles, PlayerColor player, bool hide) override;
|
||||||
|
|
||||||
|
void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override;
|
||||||
|
|
||||||
bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) override;
|
bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) override;
|
||||||
void setObjProperty(ObjectInstanceID objid, int prop, si64 val) override;
|
void setObjProperty(ObjectInstanceID objid, int prop, si64 val) override;
|
||||||
@ -276,7 +278,6 @@ public:
|
|||||||
void moveArmy(const CArmedInstance *src, const CArmedInstance *dst, bool allowMerging);
|
void moveArmy(const CArmedInstance *src, const CArmedInstance *dst, bool allowMerging);
|
||||||
const ObjectInstanceID putNewObject(Obj ID, int subID, int3 pos);
|
const ObjectInstanceID putNewObject(Obj ID, int subID, int3 pos);
|
||||||
|
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & QID;
|
h & QID;
|
||||||
|
Loading…
Reference in New Issue
Block a user