DimensionDoorEffect.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * DimensionDoorEffect.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "DimensionDoorEffect.h"
  12. #include "../CSpellHandler.h"
  13. #include "../../IGameSettings.h"
  14. #include "../../callback/IGameInfoCallback.h"
  15. #include "../../mapObjects/CGHeroInstance.h"
  16. #include "../../mapping/TerrainTile.h"
  17. #include "../../networkPacks/PacksForClient.h"
  18. VCMI_LIB_NAMESPACE_BEGIN
  19. DimensionDoorEffect::DimensionDoorEffect(const CSpell * s, const JsonNode & config)
  20. : AdventureSpellRangedEffect(config)
  21. , cursor(config["cursor"].String())
  22. , cursorGuarded(config["cursorGuarded"].String())
  23. , movementPointsRequired(config["movementPointsRequired"].Integer())
  24. , movementPointsTaken(config["movementPointsTaken"].Integer())
  25. , waterLandFailureTakesPoints(config["waterLandFailureTakesPoints"].Bool())
  26. , exposeFow(config["exposeFow"].Bool())
  27. {
  28. }
  29. std::string DimensionDoorEffect::getCursorForTarget(const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
  30. {
  31. if(!cb->getSettings().getBoolean(EGameSettings::SPELLS_DIMENSION_DOOR_TRIGGERS_GUARDS))
  32. return cursor;
  33. if (!exposeFow && !cb->isVisibleFor(pos, caster->getCasterOwner()))
  34. return cursor;
  35. if (!cb->isTileGuardedUnchecked(pos))
  36. return cursor;
  37. return cursorGuarded;
  38. }
  39. bool DimensionDoorEffect::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
  40. {
  41. if(!caster->getHeroCaster())
  42. return false;
  43. if(caster->getHeroCaster()->movementPointsRemaining() <= movementPointsRequired)
  44. {
  45. problem.add(MetaString::createFromTextID("core.genrltxt.125"));
  46. return false;
  47. }
  48. return true;
  49. }
  50. bool DimensionDoorEffect::canBeCastAtImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const
  51. {
  52. if (!isTargetInRange(cb, caster, pos))
  53. return false;
  54. int3 casterPosition = caster->getHeroCaster()->getSightCenter();
  55. const TerrainTile * dest = cb->getTileUnchecked(pos);
  56. const TerrainTile * curr = cb->getTileUnchecked(casterPosition);
  57. if(!dest)
  58. return false;
  59. if(!curr)
  60. return false;
  61. if(exposeFow)
  62. {
  63. if(!dest->isClear(curr))
  64. return false;
  65. }
  66. else
  67. {
  68. if(dest->blocked())
  69. return false;
  70. }
  71. return true;
  72. }
  73. ESpellCastResult DimensionDoorEffect::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
  74. {
  75. int3 casterPosition = parameters.caster->getHeroCaster()->getSightCenter();
  76. const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
  77. const TerrainTile * curr = env->getCb()->getTile(casterPosition);
  78. if(!dest->isClear(curr))
  79. {
  80. InfoWindow iw;
  81. iw.player = parameters.caster->getCasterOwner();
  82. // tile is either blocked or not possible to move (e.g. water <-> land)
  83. if(waterLandFailureTakesPoints)
  84. {
  85. // SOD: DD to such "wrong" terrain results in mana and move points spending, but fails to move hero
  86. iw.text = MetaString::createFromTextID("core.genrltxt.70"); // Dimension Door failed!
  87. env->apply(iw);
  88. // no return - resources will be spent
  89. }
  90. else
  91. {
  92. // HotA: game will show error message without taking mana or move points, even when DD into terra incognita
  93. iw.text = MetaString::createFromTextID("vcmi.dimensionDoor.seaToLandError");
  94. env->apply(iw);
  95. return ESpellCastResult::CANCEL;
  96. }
  97. }
  98. SetMovePoints smp;
  99. smp.hid = ObjectInstanceID(parameters.caster->getCasterUnitId());
  100. if(movementPointsTaken < static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()))
  101. smp.val = parameters.caster->getHeroCaster()->movementPointsRemaining() - movementPointsTaken;
  102. else
  103. smp.val = 0;
  104. env->apply(smp);
  105. return ESpellCastResult::OK;
  106. }
  107. void DimensionDoorEffect::endCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
  108. {
  109. int3 casterPosition = parameters.caster->getHeroCaster()->getSightCenter();
  110. const TerrainTile * dest = env->getCb()->getTile(parameters.pos);
  111. const TerrainTile * curr = env->getCb()->getTile(casterPosition);
  112. if(dest->isClear(curr))
  113. env->moveHero(ObjectInstanceID(parameters.caster->getCasterUnitId()), parameters.caster->getHeroCaster()->convertFromVisitablePos(parameters.pos), EMovementMode::DIMENSION_DOOR);
  114. }
  115. VCMI_LIB_NAMESPACE_END