1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

vcmi: add getTrigger method to obstacles

Fixes advanced remove obstacle spell
This commit is contained in:
Konstantin 2023-03-31 00:49:51 +03:00
parent 82a6d94fd0
commit d8a237ba46
8 changed files with 25 additions and 33 deletions

View File

@ -312,23 +312,22 @@ BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector<Battl
{ {
std::set<BattleHex> obstacleHexes; std::set<BattleHex> obstacleHexes;
auto insertAffected = [](const CObstacleInstance* spellObst, std::set<BattleHex> obstacleHexes) { auto insertAffected = [](const CObstacleInstance & spellObst, std::set<BattleHex> obstacleHexes) {
auto affectedHexes = spellObst->getAffectedTiles(); auto affectedHexes = spellObst.getAffectedTiles();
obstacleHexes.insert(affectedHexes.cbegin(), affectedHexes.cend()); obstacleHexes.insert(affectedHexes.cbegin(), affectedHexes.cend());
}; };
const auto & obstacles = hb.battleGetAllObstacles(); const auto & obstacles = hb.battleGetAllObstacles();
for (const auto & obst: obstacles) { for (const auto & obst: obstacles) {
const auto * spellObst = dynamic_cast<const SpellCreatedObstacle*>(obst.get());
if(spellObst && spellObst->trigger) if(obst->triggersEffects())
{ {
auto triggerAbility = VLC->spells()->getById(SpellID(spellObst->ID)); auto triggerAbility = VLC->spells()->getById(obst->getTrigger());
auto triggerIsNegative = triggerAbility->isNegative() || triggerAbility->isDamage(); auto triggerIsNegative = triggerAbility->isNegative() || triggerAbility->isDamage();
if(triggerIsNegative) if(triggerIsNegative)
insertAffected(spellObst, obstacleHexes); insertAffected(*obst, obstacleHexes);
} }
} }
// Flying stack doesn't go hex by hex, so we can't backtrack using predecessors. // Flying stack doesn't go hex by hex, so we can't backtrack using predecessors.

View File

@ -61,7 +61,6 @@
"type":"core:moat", "type":"core:moat",
"hidden" : false, "hidden" : false,
"trap" : true, "trap" : true,
"trigger" : true,
"triggerAbility" : "core:castleMoatTrigger", "triggerAbility" : "core:castleMoatTrigger",
"dispellable" : false, "dispellable" : false,
"removeOnTrigger" : false, "removeOnTrigger" : false,
@ -159,7 +158,6 @@
"type":"core:moat", "type":"core:moat",
"hidden" : false, "hidden" : false,
"trap" : true, "trap" : true,
"trigger" : true,
"triggerAbility" : "core:rampartMoatTrigger", "triggerAbility" : "core:rampartMoatTrigger",
"dispellable" : false, "dispellable" : false,
"removeOnTrigger" : false, "removeOnTrigger" : false,
@ -216,7 +214,6 @@
"type":"core:moat", "type":"core:moat",
"hidden" : true, "hidden" : true,
"trap" : false, "trap" : false,
"trigger" : true,
"triggerAbility" : "core:landMineTrigger", "triggerAbility" : "core:landMineTrigger",
"dispellable" : true, "dispellable" : true,
"removeOnTrigger" : true, "removeOnTrigger" : true,
@ -309,7 +306,6 @@
"type":"core:moat", "type":"core:moat",
"hidden" : false, "hidden" : false,
"trap" : true, "trap" : true,
"trigger" : true,
"triggerAbility" : "core:infernoMoatTrigger", "triggerAbility" : "core:infernoMoatTrigger",
"dispellable" : false, "dispellable" : false,
"removeOnTrigger" : false, "removeOnTrigger" : false,
@ -405,9 +401,8 @@
"battleEffects":{ "battleEffects":{
"moat":{ "moat":{
"type":"core:moat", "type":"core:moat",
"hidden" : true, "hidden" : false,
"trap" : false, "trap" : true,
"trigger" : true,
"triggerAbility" : "core:necropolisMoatTrigger", "triggerAbility" : "core:necropolisMoatTrigger",
"dispellable" : false, "dispellable" : false,
"removeOnTrigger" : false, "removeOnTrigger" : false,
@ -505,7 +500,6 @@
"type":"core:moat", "type":"core:moat",
"hidden" : false, "hidden" : false,
"trap" : true, "trap" : true,
"trigger" : true,
"triggerAbility" : "core:dungeonMoatTrigger", "triggerAbility" : "core:dungeonMoatTrigger",
"dispellable" : false, "dispellable" : false,
"removeOnTrigger" : false, "removeOnTrigger" : false,
@ -603,7 +597,6 @@
"type":"core:moat", "type":"core:moat",
"hidden" : false, "hidden" : false,
"trap" : true, "trap" : true,
"trigger" : true,
"triggerAbility" : "core:strongholdMoatTrigger", "triggerAbility" : "core:strongholdMoatTrigger",
"dispellable" : false, "dispellable" : false,
"removeOnTrigger" : false, "removeOnTrigger" : false,
@ -701,7 +694,6 @@
"type":"core:moat", "type":"core:moat",
"hidden" : false, "hidden" : false,
"trap" : true, "trap" : true,
"trigger" : true,
"triggerAbility" : "core:fortressMoatTrigger", "triggerAbility" : "core:fortressMoatTrigger",
"dispellable" : false, "dispellable" : false,
"removeOnTrigger" : false, "removeOnTrigger" : false,

View File

@ -15,7 +15,6 @@
"hidden" : true, "hidden" : true,
"passable" : true, "passable" : true,
"trap" : true, "trap" : true,
"trigger" : false,
"patchCount" : 4, "patchCount" : 4,
"turnsRemaining" : -1, "turnsRemaining" : -1,
"attacker" :{ "attacker" :{
@ -127,7 +126,6 @@
"hidden" : true, "hidden" : true,
"passable" : true, "passable" : true,
"trap" : false, "trap" : false,
"trigger" : true,
"triggerAbility" : "core:landMineTrigger", "triggerAbility" : "core:landMineTrigger",
"removeOnTrigger" : true, "removeOnTrigger" : true,
"patchCount" : 4, "patchCount" : 4,
@ -194,7 +192,6 @@
"hidden" : false, "hidden" : false,
"passable" : false, "passable" : false,
"trap" : false, "trap" : false,
"trigger" : false,
"turnsRemaining" : 2, "turnsRemaining" : 2,
"attacker" :{ "attacker" :{
"range" : [[""]], "range" : [[""]],
@ -319,7 +316,6 @@
"hidden" : false, "hidden" : false,
"passable" : true, "passable" : true,
"trap" : false, "trap" : false,
"trigger" : true,
"triggerAbility" : "core:fireWallTrigger", "triggerAbility" : "core:fireWallTrigger",
"turnsRemaining" : 2, "turnsRemaining" : 2,
"attacker" :{ "attacker" :{

View File

@ -98,7 +98,12 @@ bool CObstacleInstance::blocksTiles() const
bool CObstacleInstance::triggersEffects() const bool CObstacleInstance::triggersEffects() const
{ {
return false; return getTrigger() != SpellID::NONE;
}
SpellID CObstacleInstance::getTrigger() const
{
return SpellID::NONE;
} }
void CObstacleInstance::serializeJson(JsonSerializeFormat & handler) void CObstacleInstance::serializeJson(JsonSerializeFormat & handler)
@ -172,7 +177,7 @@ bool SpellCreatedObstacle::stopsMovement() const
return trap; return trap;
} }
bool SpellCreatedObstacle::triggersEffects() const SpellID SpellCreatedObstacle::getTrigger() const
{ {
return trigger; return trigger;
} }
@ -203,7 +208,7 @@ void SpellCreatedObstacle::serializeJson(JsonSerializeFormat & handler)
handler.serializeBool("hidden", hidden); handler.serializeBool("hidden", hidden);
handler.serializeBool("revealed", revealed); handler.serializeBool("revealed", revealed);
handler.serializeBool("passable", passable); handler.serializeBool("passable", passable);
handler.serializeBool("trigger", trigger); handler.serializeId("trigger", trigger, SpellID::NONE);
handler.serializeBool("trap", trap); handler.serializeBool("trap", trap);
handler.serializeBool("removeOnTrigger", removeOnTrigger); handler.serializeBool("removeOnTrigger", removeOnTrigger);
handler.serializeBool("nativeVisible", nativeVisible); handler.serializeBool("nativeVisible", nativeVisible);

View File

@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class ObstacleInfo; class ObstacleInfo;
class ObstacleChanges; class ObstacleChanges;
class JsonSerializeFormat; class JsonSerializeFormat;
class SpellID;
struct DLL_LINKAGE CObstacleInstance struct DLL_LINKAGE CObstacleInstance
{ {
@ -42,6 +43,7 @@ struct DLL_LINKAGE CObstacleInstance
virtual bool blocksTiles() const; virtual bool blocksTiles() const;
virtual bool stopsMovement() const; //if unit stepping onto obstacle, can't continue movement (in general, doesn't checks for the side) virtual bool stopsMovement() const; //if unit stepping onto obstacle, can't continue movement (in general, doesn't checks for the side)
virtual bool triggersEffects() const; virtual bool triggersEffects() const;
virtual SpellID getTrigger() const;
virtual std::vector<BattleHex> getAffectedTiles() const; virtual std::vector<BattleHex> getAffectedTiles() const;
virtual bool visibleForSide(ui8 side, bool hasNativeStack) const; //0 attacker virtual bool visibleForSide(ui8 side, bool hasNativeStack) const; //0 attacker
@ -76,12 +78,12 @@ struct DLL_LINKAGE SpellCreatedObstacle : CObstacleInstance
int32_t minimalDamage; //How many damage should it do regardless of power and level of caster int32_t minimalDamage; //How many damage should it do regardless of power and level of caster
si8 casterSide; //0 - obstacle created by attacker; 1 - by defender si8 casterSide; //0 - obstacle created by attacker; 1 - by defender
SpellID trigger;
bool hidden; bool hidden;
bool passable; bool passable;
bool trigger;
bool trap; bool trap;
bool removeOnTrigger; bool removeOnTrigger;
bool revealed; bool revealed;
bool nativeVisible; //Should native terrain creatures reveal obstacle bool nativeVisible; //Should native terrain creatures reveal obstacle
@ -100,7 +102,7 @@ struct DLL_LINKAGE SpellCreatedObstacle : CObstacleInstance
bool blocksTiles() const override; bool blocksTiles() const override;
bool stopsMovement() const override; bool stopsMovement() const override;
bool triggersEffects() const override; SpellID getTrigger() const override;
void battleTurnPassed() override; void battleTurnPassed() override;

View File

@ -51,7 +51,6 @@ static void serializeMoatHexes(JsonSerializeFormat & handler, const std::string
void Moat::serializeJsonEffect(JsonSerializeFormat & handler) void Moat::serializeJsonEffect(JsonSerializeFormat & handler)
{ {
handler.serializeBool("hidden", hidden); handler.serializeBool("hidden", hidden);
handler.serializeBool("trigger", trigger);
handler.serializeBool("trap", trap); handler.serializeBool("trap", trap);
handler.serializeBool("removeOnTrigger", removeOnTrigger); handler.serializeBool("removeOnTrigger", removeOnTrigger);
handler.serializeBool("dispellable", dispellable); handler.serializeBool("dispellable", dispellable);
@ -147,7 +146,7 @@ void Moat::placeObstacles(ServerCallback * server, const Mechanics * m, const Ef
obstacle.uniqueID = obstacleIdToGive++; obstacle.uniqueID = obstacleIdToGive++;
obstacle.pos = destination.at(0); obstacle.pos = destination.at(0);
obstacle.obstacleType = dispellable ? CObstacleInstance::SPELL_CREATED : CObstacleInstance::MOAT; obstacle.obstacleType = dispellable ? CObstacleInstance::SPELL_CREATED : CObstacleInstance::MOAT;
obstacle.ID = triggerAbility; obstacle.ID = m->getSpellIndex();
obstacle.turnsRemaining = -1; //Moat cannot be expired obstacle.turnsRemaining = -1; //Moat cannot be expired
obstacle.casterSpellPower = m->getEffectPower(); obstacle.casterSpellPower = m->getEffectPower();
@ -156,7 +155,7 @@ void Moat::placeObstacles(ServerCallback * server, const Mechanics * m, const Ef
obstacle.minimalDamage = moatDamage; // Minimal moat damage obstacle.minimalDamage = moatDamage; // Minimal moat damage
obstacle.hidden = hidden; obstacle.hidden = hidden;
obstacle.passable = true; //Moats always passable obstacle.passable = true; //Moats always passable
obstacle.trigger = trigger; obstacle.trigger = triggerAbility;
obstacle.trap = trap; obstacle.trap = trap;
obstacle.removeOnTrigger = removeOnTrigger; obstacle.removeOnTrigger = removeOnTrigger;
obstacle.nativeVisible = false; //Moats is invisible for native terrain obstacle.nativeVisible = false; //Moats is invisible for native terrain

View File

@ -212,7 +212,6 @@ void Obstacle::serializeJsonEffect(JsonSerializeFormat & handler)
{ {
handler.serializeBool("hidden", hidden); handler.serializeBool("hidden", hidden);
handler.serializeBool("passable", passable); handler.serializeBool("passable", passable);
handler.serializeBool("trigger", trigger);
handler.serializeBool("trap", trap); handler.serializeBool("trap", trap);
handler.serializeBool("removeOnTrigger", removeOnTrigger); handler.serializeBool("removeOnTrigger", removeOnTrigger);
handler.serializeBool("hideNative", hideNative); handler.serializeBool("hideNative", hideNative);
@ -289,7 +288,7 @@ void Obstacle::placeObstacles(ServerCallback * server, const Mechanics * m, cons
obstacle.uniqueID = obstacleIdToGive++; obstacle.uniqueID = obstacleIdToGive++;
obstacle.pos = destination.hexValue; obstacle.pos = destination.hexValue;
obstacle.obstacleType = CObstacleInstance::SPELL_CREATED; obstacle.obstacleType = CObstacleInstance::SPELL_CREATED;
obstacle.ID = triggerAbility; obstacle.ID = m->getSpellIndex();
obstacle.turnsRemaining = turnsRemaining; obstacle.turnsRemaining = turnsRemaining;
obstacle.casterSpellPower = m->getEffectPower(); obstacle.casterSpellPower = m->getEffectPower();
@ -299,7 +298,7 @@ void Obstacle::placeObstacles(ServerCallback * server, const Mechanics * m, cons
obstacle.nativeVisible = !hideNative; obstacle.nativeVisible = !hideNative;
obstacle.hidden = hidden; obstacle.hidden = hidden;
obstacle.passable = passable; obstacle.passable = passable;
obstacle.trigger = trigger; obstacle.trigger = triggerAbility;
obstacle.trap = trap; obstacle.trap = trap;
obstacle.removeOnTrigger = removeOnTrigger; obstacle.removeOnTrigger = removeOnTrigger;

View File

@ -5263,7 +5263,7 @@ bool CGameHandler::handleDamageFromObstacle(const CStack * curStack, bool stackI
auto shouldReveal = !spellObstacle->hidden || !gs->curB->battleIsObstacleVisibleForSide(*obstacle, (BattlePerspective::BattlePerspective)side); auto shouldReveal = !spellObstacle->hidden || !gs->curB->battleIsObstacleVisibleForSide(*obstacle, (BattlePerspective::BattlePerspective)side);
const auto * hero = gs->curB->battleGetFightingHero(spellObstacle->casterSide); const auto * hero = gs->curB->battleGetFightingHero(spellObstacle->casterSide);
auto caster = spells::ObstacleCasterProxy(gs->curB->getSidePlayer(spellObstacle->casterSide), hero, *spellObstacle); auto caster = spells::ObstacleCasterProxy(gs->curB->getSidePlayer(spellObstacle->casterSide), hero, *spellObstacle);
const auto * sp = SpellID(spellObstacle->ID).toSpell(); const auto * sp = obstacle->getTrigger().toSpell();
if(obstacle->triggersEffects() && sp) if(obstacle->triggersEffects() && sp)
{ {
auto cast = spells::BattleCast(gs->curB, &caster, spells::Mode::PASSIVE, sp); auto cast = spells::BattleCast(gs->curB, &caster, spells::Mode::PASSIVE, sp);