mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
112 lines
3.0 KiB
C++
112 lines
3.0 KiB
C++
|
|
/*
|
||
|
|
* SummonBoatMechanics.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 "SummonBoatMechanics.h"
|
||
|
|
|
||
|
|
#include "../CSpellHandler.h"
|
||
|
|
|
||
|
|
#include "../../mapObjects/CGHeroInstance.h"
|
||
|
|
#include "../../mapObjects/MiscObjects.h"
|
||
|
|
#include "../../mapping/CMap.h"
|
||
|
|
#include "../../networkPacks/PacksForClient.h"
|
||
|
|
|
||
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
||
|
|
|
||
|
|
SummonBoatMechanics::SummonBoatMechanics(const CSpell * s)
|
||
|
|
: AdventureSpellMechanics(s)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
bool SummonBoatMechanics::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 SummonBoatMechanics::applyAdventureEffects(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const
|
||
|
|
{
|
||
|
|
const auto schoolLevel = parameters.caster->getSpellSchoolLevel(owner);
|
||
|
|
|
||
|
|
//check if spell works at all
|
||
|
|
if(env->getRNG()->nextInt(0, 99) >= owner->getLevelPower(schoolLevel)) //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;
|
||
|
|
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(schoolLevel < 2) //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, BoatId::NECROPOLIS, parameters.caster->getCasterOwner());
|
||
|
|
}
|
||
|
|
return ESpellCastResult::OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
VCMI_LIB_NAMESPACE_END
|