SummonBoatMechanics.cpp 3.0 KB

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