mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-17 20:58:07 +02:00
vcmi: remove obstacle caster logic
It is possible now to cast something via obstacle Immune creatures should not trigger an obstacle trigger now and should not reveal it.
This commit is contained in:
parent
db428faeeb
commit
cd1730b1fb
@ -133,6 +133,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/spells/BonusCaster.cpp
|
||||
${MAIN_LIB_DIR}/spells/CSpellHandler.cpp
|
||||
${MAIN_LIB_DIR}/spells/ISpellMechanics.cpp
|
||||
${MAIN_LIB_DIR}/spells/ObstacleCasterProxy.cpp
|
||||
${MAIN_LIB_DIR}/spells/Problem.cpp
|
||||
${MAIN_LIB_DIR}/spells/ProxyCaster.cpp
|
||||
${MAIN_LIB_DIR}/spells/TargetCondition.cpp
|
||||
|
98
lib/spells/ObstacleCasterProxy.cpp
Normal file
98
lib/spells/ObstacleCasterProxy.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* ObstacleCasterProxy.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 "ObstacleCasterProxy.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
namespace spells
|
||||
{
|
||||
|
||||
ObstacleCasterProxy::ObstacleCasterProxy(PlayerColor owner_, const Caster * hero_, const SpellCreatedObstacle * obs_):
|
||||
ProxyCaster(hero_),
|
||||
owner(std::move(owner_)),
|
||||
obs(*obs_)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t ObstacleCasterProxy::getCasterUnitId() const
|
||||
{
|
||||
if(actualCaster)
|
||||
return actualCaster->getCasterUnitId();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t ObstacleCasterProxy::getSpellSchoolLevel(const Spell * spell, int32_t * outSelectedSchool) const
|
||||
{
|
||||
return obs.spellLevel;
|
||||
}
|
||||
|
||||
int32_t ObstacleCasterProxy::getEffectLevel(const Spell * spell) const
|
||||
{
|
||||
return obs.spellLevel;
|
||||
}
|
||||
|
||||
int64_t ObstacleCasterProxy::getSpellBonus(const Spell * spell, int64_t base, const battle::Unit * affectedStack) const
|
||||
{
|
||||
if(actualCaster)
|
||||
return std::max<int64_t>(actualCaster->getSpellBonus(spell, base, affectedStack), obs.minimalDamage);
|
||||
else
|
||||
return std::max<int64_t>(base, obs.minimalDamage);
|
||||
}
|
||||
|
||||
int64_t ObstacleCasterProxy::getSpecificSpellBonus(const Spell * spell, int64_t base) const
|
||||
{
|
||||
if(actualCaster)
|
||||
return actualCaster->getSpecificSpellBonus(spell, base);
|
||||
else
|
||||
return base;
|
||||
}
|
||||
|
||||
int32_t ObstacleCasterProxy::getEffectPower(const Spell * spell) const
|
||||
{
|
||||
return obs.casterSpellPower;
|
||||
}
|
||||
|
||||
int32_t ObstacleCasterProxy::getEnchantPower(const Spell * spell) const
|
||||
{
|
||||
return obs.casterSpellPower;
|
||||
}
|
||||
|
||||
int64_t ObstacleCasterProxy::getEffectValue(const Spell * spell) const
|
||||
{
|
||||
if(actualCaster)
|
||||
return std::max(static_cast<int64_t>(obs.minimalDamage), actualCaster->getEffectValue(spell));
|
||||
else
|
||||
return obs.minimalDamage;
|
||||
}
|
||||
|
||||
PlayerColor ObstacleCasterProxy::getCasterOwner() const
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
|
||||
void ObstacleCasterProxy::getCasterName(MetaString & text) const
|
||||
{
|
||||
logGlobal->error("Unexpected call to ObstacleCasterProxy::getCasterName");
|
||||
}
|
||||
|
||||
void ObstacleCasterProxy::getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
void ObstacleCasterProxy::spendMana(ServerCallback * server, const int spellCost) const
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
}
|
||||
VCMI_LIB_NAMESPACE_END
|
44
lib/spells/ObstacleCasterProxy.h
Normal file
44
lib/spells/ObstacleCasterProxy.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* ObstacleCasterProxy.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
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ProxyCaster.h"
|
||||
#include "../lib/NetPacksBase.h"
|
||||
#include "../battle/BattleHex.h"
|
||||
#include "../battle/CObstacleInstance.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
namespace spells
|
||||
{
|
||||
|
||||
class DLL_LINKAGE ObstacleCasterProxy : public ProxyCaster
|
||||
{
|
||||
public:
|
||||
ObstacleCasterProxy(PlayerColor owner_, const Caster * hero_, const SpellCreatedObstacle * obs_);
|
||||
|
||||
int32_t getCasterUnitId() const override;
|
||||
int32_t getSpellSchoolLevel(const Spell * spell, int32_t * outSelectedSchool = nullptr) const override;
|
||||
int32_t getEffectLevel(const Spell * spell) const override;
|
||||
int64_t getSpellBonus(const Spell * spell, int64_t base, const battle::Unit * affectedStack) const override;
|
||||
int64_t getSpecificSpellBonus(const Spell * spell, int64_t base) const override;
|
||||
int32_t getEffectPower(const Spell * spell) const override;
|
||||
int32_t getEnchantPower(const Spell * spell) const override;
|
||||
int64_t getEffectValue(const Spell * spell) const override;
|
||||
PlayerColor getCasterOwner() 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 spendMana(ServerCallback * server, const int spellCost) const override;
|
||||
|
||||
private:
|
||||
const PlayerColor owner;
|
||||
const SpellCreatedObstacle & obs;
|
||||
};
|
||||
|
||||
}//
|
||||
VCMI_LIB_NAMESPACE_END
|
@ -121,7 +121,7 @@ void Obstacle::adjustAffectedHexes(std::set<BattleHex> & hexes, const Mechanics
|
||||
|
||||
bool Obstacle::applicable(Problem & problem, const Mechanics * m) const
|
||||
{
|
||||
if(hidden && m->battle()->battleHasNativeStack(m->battle()->otherSide(m->casterSide)))
|
||||
if(hidden && !hideNative && m->battle()->battleHasNativeStack(m->battle()->otherSide(m->casterSide)))
|
||||
return m->adaptProblem(ESpellCastProblem::NO_APPROPRIATE_TARGET, problem);
|
||||
|
||||
return LocationEffect::applicable(problem, m);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "../lib/spells/BonusCaster.h"
|
||||
#include "../lib/spells/CSpellHandler.h"
|
||||
#include "../lib/spells/ISpellMechanics.h"
|
||||
#include "../lib/spells/ObstacleCasterProxy.h"
|
||||
#include "../lib/spells/Problem.h"
|
||||
#include "../lib/CGeneralTextHandler.h"
|
||||
#include "../lib/CTownHandler.h"
|
||||
@ -93,102 +94,6 @@ private:
|
||||
CGameHandler * gh;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
namespace spells
|
||||
{
|
||||
|
||||
class ObstacleCasterProxy : public Caster
|
||||
{
|
||||
public:
|
||||
ObstacleCasterProxy(const PlayerColor owner_, const CGHeroInstance * hero_, const SpellCreatedObstacle * obs_)
|
||||
: owner(owner_),
|
||||
hero(hero_),
|
||||
obs(obs_)
|
||||
{
|
||||
};
|
||||
|
||||
~ObstacleCasterProxy() = default;
|
||||
|
||||
int32_t getCasterUnitId() const override
|
||||
{
|
||||
if(hero)
|
||||
return hero->getCasterUnitId();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t getSpellSchoolLevel(const Spell * spell, int32_t * outSelectedSchool = nullptr) const override
|
||||
{
|
||||
return obs->spellLevel;
|
||||
}
|
||||
|
||||
int32_t getEffectLevel(const Spell * spell) const override
|
||||
{
|
||||
return obs->spellLevel;
|
||||
}
|
||||
|
||||
int64_t getSpellBonus(const Spell * spell, int64_t base, const battle::Unit * affectedStack) const override
|
||||
{
|
||||
if(hero)
|
||||
return hero->getSpellBonus(spell, base, affectedStack);
|
||||
else
|
||||
return base;
|
||||
}
|
||||
|
||||
int64_t getSpecificSpellBonus(const Spell * spell, int64_t base) const override
|
||||
{
|
||||
if(hero)
|
||||
return hero->getSpecificSpellBonus(spell, base);
|
||||
else
|
||||
return base;
|
||||
}
|
||||
|
||||
int32_t getEffectPower(const Spell * spell) const override
|
||||
{
|
||||
return obs->casterSpellPower;
|
||||
}
|
||||
|
||||
int32_t getEnchantPower(const Spell * spell) const override
|
||||
{
|
||||
return obs->casterSpellPower;
|
||||
}
|
||||
|
||||
int64_t getEffectValue(const Spell * spell) const override
|
||||
{
|
||||
if(hero)
|
||||
return hero->getEffectValue(spell);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
PlayerColor getCasterOwner() const override
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
|
||||
void getCasterName(MetaString & text) const override
|
||||
{
|
||||
logGlobal->error("Unexpected call to ObstacleCasterProxy::getCasterName");
|
||||
}
|
||||
|
||||
void getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const override
|
||||
{
|
||||
logGlobal->error("Unexpected call to ObstacleCasterProxy::getCastDescription");
|
||||
}
|
||||
|
||||
void spendMana(ServerCallback * server, const int spellCost) const override
|
||||
{
|
||||
logGlobal->error("Unexpected call to ObstacleCasterProxy::spendMana");
|
||||
}
|
||||
|
||||
private:
|
||||
const CGHeroInstance * hero;
|
||||
const PlayerColor owner;
|
||||
const SpellCreatedObstacle * obs;
|
||||
};
|
||||
|
||||
}//
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
CondSh<bool> battleMadeAction(false);
|
||||
CondSh<BattleResult *> battleResult(nullptr);
|
||||
@ -5333,27 +5238,18 @@ bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackI
|
||||
if(spellObstacle->triggersEffects())
|
||||
{
|
||||
const bool oneTimeObstacle = spellObstacle->removeOnTrigger;
|
||||
|
||||
//hidden obstacle triggers effects until revealed
|
||||
if(!(spellObstacle->hidden && gs->curB->battleIsObstacleVisibleForSide(*obstacle, (BattlePerspective::BattlePerspective)side)))
|
||||
auto revealObstacles = [&](const SpellCreatedObstacle & spellObstacle) -> void
|
||||
{
|
||||
const CGHeroInstance * hero = gs->curB->battleGetFightingHero(spellObstacle->casterSide);
|
||||
spells::ObstacleCasterProxy caster(gs->curB->sides.at(spellObstacle->casterSide).color, hero, spellObstacle);
|
||||
|
||||
const CSpell * sp = SpellID(spellObstacle->ID).toSpell();
|
||||
if(!sp)
|
||||
COMPLAIN_RET("Invalid obstacle instance");
|
||||
|
||||
// For the hidden spell created obstacles, e.g. QuickSand, it should be revealed after taking damage
|
||||
ObstacleChanges changeInfo;
|
||||
changeInfo.id = spellObstacle->uniqueID;
|
||||
changeInfo.id = spellObstacle.uniqueID;
|
||||
if (oneTimeObstacle)
|
||||
changeInfo.operation = ObstacleChanges::EOperation::REMOVE;
|
||||
else
|
||||
changeInfo.operation = ObstacleChanges::EOperation::UPDATE;
|
||||
|
||||
SpellCreatedObstacle changedObstacle;
|
||||
changedObstacle.uniqueID = spellObstacle->uniqueID;
|
||||
changedObstacle.uniqueID = changeInfo.id;
|
||||
changedObstacle.revealed = true;
|
||||
|
||||
changeInfo.data.clear();
|
||||
@ -5363,10 +5259,26 @@ bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackI
|
||||
BattleObstaclesChanged bocp;
|
||||
bocp.changes.emplace_back(changeInfo);
|
||||
sendAndApply(&bocp);
|
||||
|
||||
spells::BattleCast battleCast(gs->curB, &caster, spells::Mode::HERO, sp);
|
||||
battleCast.applyEffects(spellEnv, spells::Target(1, spells::Destination(curStack)), true);
|
||||
};
|
||||
auto shouldReveal = !spellObstacle->hidden || !gs->curB->battleIsObstacleVisibleForSide(*obstacle, (BattlePerspective::BattlePerspective)side);
|
||||
const auto * hero = gs->curB->battleGetFightingHero(spellObstacle->casterSide);
|
||||
auto caster = spells::ObstacleCasterProxy(gs->curB->sides.at(spellObstacle->casterSide).color, hero, spellObstacle);
|
||||
const auto * sp = SpellID(spellObstacle->ID).toSpell();
|
||||
if(sp)
|
||||
{
|
||||
auto cast = spells::BattleCast(gs->curB, &caster, spells::Mode::PASSIVE, sp);
|
||||
spells::detail::ProblemImpl ignored;
|
||||
auto target = spells::Target(1, spells::Destination(curStack));
|
||||
if(sp->battleMechanics(&cast)->canBeCastAt(target, ignored)) // Obstacles should not be revealed by immune creatures
|
||||
{
|
||||
if(shouldReveal) { //hidden obstacle triggers effects after revealed
|
||||
revealObstacles(*spellObstacle);
|
||||
cast.cast(spellEnv, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(shouldReveal)
|
||||
revealObstacles(*spellObstacle);
|
||||
}
|
||||
}
|
||||
else if(obstacle->obstacleType == CObstacleInstance::MOAT)
|
||||
|
Loading…
x
Reference in New Issue
Block a user