SummonBoatEffect.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * SummonBoatEffect.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 "SummonBoatEffect.h"
  12. #include "../CSpellHandler.h"
  13. #include "../../mapObjects/CGHeroInstance.h"
  14. #include "../../mapObjects/MiscObjects.h"
  15. #include "../../mapping/CMap.h"
  16. #include "../../networkPacks/PacksForClient.h"
  17. VCMI_LIB_NAMESPACE_BEGIN
  18. SummonBoatEffect::SummonBoatEffect(const CSpell * s, const JsonNode & config)
  19. : owner(s)
  20. , useExistingBoat(config["useExistingBoat"].Bool())
  21. , createNewBoat(config["createNewBoat"].Bool())
  22. {
  23. }
  24. bool SummonBoatEffect::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
  25. {
  26. if(!caster->getHeroCaster())
  27. return false;
  28. if(caster->getHeroCaster()->inBoat())
  29. {
  30. MetaString message = MetaString::createFromTextID("core.genrltxt.333");
  31. caster->getCasterName(message);
  32. problem.add(std::move(message));
  33. return false;
  34. }
  35. int3 summonPos = caster->getHeroCaster()->bestLocation();
  36. if(summonPos.x < 0)
  37. {
  38. MetaString message = MetaString::createFromTextID("core.genrltxt.334");
  39. caster->getCasterName(message);
  40. problem.add(std::move(message));
  41. return false;
  42. }
  43. return true;
  44. }
  45. ESpellCastResult SummonBoatEffect::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
  46. {
  47. const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
  48. //check if spell works at all
  49. if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //power is % chance of success
  50. {
  51. InfoWindow iw;
  52. iw.player = parameters.caster->getCasterOwner();
  53. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
  54. parameters.caster->getCasterName(iw.text);
  55. env->apply(iw);
  56. return ESpellCastResult::OK;
  57. }
  58. //try to find unoccupied boat to summon
  59. const CGBoat * nearest = nullptr;
  60. if (useExistingBoat)
  61. {
  62. double dist = 0;
  63. for(const auto & b : env->getMap()->getObjects<CGBoat>())
  64. {
  65. if(b->getBoardedHero() || b->layer != EPathfindingLayer::SAIL)
  66. continue; //we're looking for unoccupied boat
  67. double nDist = b->visitablePos().dist2d(parameters.caster->getHeroCaster()->visitablePos());
  68. if(!nearest || nDist < dist) //it's first boat or closer than previous
  69. {
  70. nearest = b;
  71. dist = nDist;
  72. }
  73. }
  74. }
  75. int3 summonPos = parameters.caster->getHeroCaster()->bestLocation();
  76. if(nullptr != nearest) //we found boat to summon
  77. {
  78. ChangeObjPos cop;
  79. cop.objid = nearest->id;
  80. cop.nPos = summonPos;
  81. cop.initiator = parameters.caster->getCasterOwner();
  82. env->apply(cop);
  83. }
  84. else if(!createNewBoat) //none or basic level -> cannot create boat :(
  85. {
  86. InfoWindow iw;
  87. iw.player = parameters.caster->getCasterOwner();
  88. iw.text.appendLocalString(EMetaText::GENERAL_TXT, 335); //There are no boats to summon.
  89. env->apply(iw);
  90. return ESpellCastResult::ERROR;
  91. }
  92. else //create boat
  93. {
  94. env->createBoat(summonPos, BoatId::NECROPOLIS, parameters.caster->getCasterOwner());
  95. }
  96. return ESpellCastResult::OK;
  97. }
  98. VCMI_LIB_NAMESPACE_END