1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00
Files
vcmi/lib/spells/adventure/SummonBoatEffect.cpp
Ivan Savenko cf378c3672 Migrate codebase to C++20
- VCMI can now be compiled in C++20 mode
- Replaced all references to C++17 with C++20
- Boost 1.74 is now set as minimal version (older version might work but
untested)
- Updated documentation to reflect required versions of compilers /
libraries
- Removed excessive fail-fast / continue-on-error from CI
2025-11-06 14:40:21 +02:00

135 lines
3.5 KiB
C++

/*
* SummonBoatEffect.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 "StdInc.h"
#include "SummonBoatEffect.h"
#include "../CSpellHandler.h"
#include "../../mapObjects/CGHeroInstance.h"
#include "../../mapObjects/MiscObjects.h"
#include "../../mapping/CMap.h"
#include "../../modding/IdentifierStorage.h"
#include "../../networkPacks/PacksForClient.h"
VCMI_LIB_NAMESPACE_BEGIN
SummonBoatEffect::SummonBoatEffect(const CSpell * s, const JsonNode & config)
: owner(s)
, useExistingBoat(config["useExistingBoat"].Bool())
{
if (!config["createdBoat"].isNull())
{
LIBRARY->identifiers()->requestIdentifier("core:boat", config["createdBoat"], [this](int32_t boatTypeID)
{
createdBoat = BoatId(boatTypeID);
});
}
}
bool SummonBoatEffect::canCreateNewBoat() const
{
return createdBoat != BoatId::NONE;
}
int SummonBoatEffect::getSuccessChance(const spells::Caster * caster) const
{
const auto schoolLevel = caster->getSpellSchoolLevel(owner);
return owner->getLevelPower(schoolLevel);
}
bool SummonBoatEffect::canBeCastImpl(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
{
if(!caster->getHeroCaster())
return false;
if(caster->getHeroCaster()->inBoat())
{
MetaString message = MetaString::createFromTextID("core.genrltxt.333");
caster->getCasterName(message);
problem.add(std::move(message));
return false;
}
int3 summonPos = caster->getHeroCaster()->bestLocation();
if(summonPos.x < 0)
{
MetaString message = MetaString::createFromTextID("core.genrltxt.334");
caster->getCasterName(message);
problem.add(std::move(message));
return false;
}
return true;
}
ESpellCastResult SummonBoatEffect::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
{
//check if spell works at all
if(env->getRNG()->nextInt(0, 99) >= getSuccessChance(parameters.caster)) //power is % chance of success
{
InfoWindow iw;
iw.player = parameters.caster->getCasterOwner();
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 336); //%s tried to summon a boat, but failed.
parameters.caster->getCasterName(iw.text);
env->apply(iw);
return ESpellCastResult::OK;
}
//try to find unoccupied boat to summon
const CGBoat * nearest = nullptr;
if (useExistingBoat)
{
double dist = 0;
for(const auto & b : env->getMap()->getObjects<CGBoat>())
{
if(b->getBoardedHero() || b->layer != EPathfindingLayer::SAIL)
continue; //we're looking for unoccupied boat
double nDist = b->visitablePos().dist2d(parameters.caster->getHeroCaster()->visitablePos());
if(!nearest || nDist < dist) //it's first boat or closer than previous
{
nearest = b;
dist = nDist;
}
}
}
int3 summonPos = parameters.caster->getHeroCaster()->bestLocation();
if(nullptr != nearest) //we found boat to summon
{
ChangeObjPos cop;
cop.objid = nearest->id;
cop.nPos = summonPos;
cop.initiator = parameters.caster->getCasterOwner();
env->apply(cop);
}
else if(!canCreateNewBoat()) //none or basic level -> cannot create boat :(
{
InfoWindow iw;
iw.player = parameters.caster->getCasterOwner();
iw.text.appendLocalString(EMetaText::GENERAL_TXT, 335); //There are no boats to summon.
env->apply(iw);
return ESpellCastResult::ERROR;
}
else //create boat
{
env->createBoat(summonPos, createdBoat, parameters.caster->getCasterOwner());
}
return ESpellCastResult::OK;
}
VCMI_LIB_NAMESPACE_END