2022-07-26 15:07:42 +02:00
|
|
|
/*
|
2014-06-05 20:26:50 +03:00
|
|
|
* CBank.cpp, part of VCMI engine
|
2014-06-05 19:52:14 +03:00
|
|
|
*
|
|
|
|
* 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"
|
2014-06-05 20:26:50 +03:00
|
|
|
#include "CBank.h"
|
2014-06-05 19:52:14 +03:00
|
|
|
|
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
|
|
|
#include <vcmi/spells/Spell.h>
|
|
|
|
#include <vcmi/spells/Service.h>
|
|
|
|
|
2014-06-05 20:26:50 +03:00
|
|
|
#include "../CGeneralTextHandler.h"
|
2014-06-05 23:51:24 +03:00
|
|
|
#include "../CSoundBase.h"
|
2023-07-19 12:17:50 +02:00
|
|
|
#include "../GameSettings.h"
|
2023-10-19 14:41:59 +02:00
|
|
|
#include "../CPlayerState.h"
|
2023-06-02 20:47:37 +02:00
|
|
|
#include "../mapObjectConstructors/CObjectClassesHandler.h"
|
2023-06-06 17:32:53 +02:00
|
|
|
#include "../mapObjectConstructors/CBankInstanceConstructor.h"
|
2023-10-23 12:59:15 +02:00
|
|
|
#include "../mapObjects/CGHeroInstance.h"
|
|
|
|
#include "../networkPacks/Component.h"
|
|
|
|
#include "../networkPacks/PacksForClient.h"
|
|
|
|
#include "../networkPacks/PacksForClientBattle.h"
|
|
|
|
#include "../MetaString.h"
|
2014-06-25 17:11:07 +03:00
|
|
|
#include "../IGameCallback.h"
|
2023-06-23 17:02:48 +02:00
|
|
|
#include "../gameState/CGameState.h"
|
2014-06-05 19:52:14 +03:00
|
|
|
|
2022-07-26 15:07:42 +02:00
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
2014-06-05 19:52:14 +03:00
|
|
|
///helpers
|
2023-01-01 20:54:05 +02:00
|
|
|
static std::string visitedTxt(const bool visited)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
|
|
|
int id = visited ? 352 : 353;
|
|
|
|
return VLC->generaltexth->allTexts[id];
|
|
|
|
}
|
|
|
|
|
2024-01-01 16:37:48 +02:00
|
|
|
CBank::CBank(IGameCallback *cb)
|
|
|
|
: CArmedInstance(cb)
|
|
|
|
{}
|
|
|
|
|
2023-02-12 22:39:17 +02:00
|
|
|
//must be instantiated in .cpp file for access to complete types of all member fields
|
|
|
|
CBank::~CBank() = default;
|
2014-06-22 13:39:40 +03:00
|
|
|
|
2016-09-09 19:30:36 +02:00
|
|
|
void CBank::initObj(CRandomGenerator & rand)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
|
|
|
daycounter = 0;
|
2014-06-22 13:39:40 +03:00
|
|
|
resetDuration = 0;
|
2023-10-24 16:11:25 +02:00
|
|
|
getObjectHandler()->configureObject(this, rand);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
2014-06-22 13:39:40 +03:00
|
|
|
|
2023-06-21 15:49:44 +02:00
|
|
|
bool CBank::isCoastVisitable() const
|
|
|
|
{
|
|
|
|
return coastVisitable;
|
|
|
|
}
|
|
|
|
|
2014-06-24 20:39:36 +03:00
|
|
|
std::string CBank::getHoverText(PlayerColor player) const
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-10-19 14:41:59 +02:00
|
|
|
if (!wasVisited(player))
|
|
|
|
return getObjectName();
|
|
|
|
|
|
|
|
return getObjectName() + "\n" + visitedTxt(bc == nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<Component> CBank::getPopupComponents(PlayerColor player) const
|
|
|
|
{
|
|
|
|
if (!wasVisited(player))
|
|
|
|
return {};
|
|
|
|
|
|
|
|
if (!VLC->settings()->getBoolean(EGameSettings::BANKS_SHOW_GUARDS_COMPOSITION))
|
|
|
|
return {};
|
|
|
|
|
2023-11-12 17:50:52 +02:00
|
|
|
if (bc == nullptr)
|
|
|
|
return {};
|
|
|
|
|
2023-10-19 14:41:59 +02:00
|
|
|
std::map<CreatureID, int> guardsAmounts;
|
|
|
|
std::vector<Component> result;
|
|
|
|
|
|
|
|
for (auto const & slot : Slots())
|
|
|
|
if (slot.second)
|
|
|
|
guardsAmounts[slot.second->getCreatureID()] += slot.second->getCount();
|
|
|
|
|
|
|
|
for (auto const & guard : guardsAmounts)
|
|
|
|
{
|
2023-10-31 11:09:56 +02:00
|
|
|
Component comp(ComponentType::CREATURE, guard.first, guard.second);
|
2023-10-19 14:41:59 +02:00
|
|
|
result.push_back(comp);
|
|
|
|
}
|
|
|
|
return result;
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
|
2014-06-22 13:39:40 +03:00
|
|
|
void CBank::setConfig(const BankConfig & config)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-02-12 22:39:17 +02:00
|
|
|
bc = std::make_unique<BankConfig>(config);
|
2023-08-07 18:13:02 +02:00
|
|
|
clearSlots(); // remove all stacks, if any
|
2014-06-05 19:52:14 +03:00
|
|
|
|
2023-02-12 22:39:17 +02:00
|
|
|
for(const auto & stack : config.guards)
|
2023-01-02 18:00:51 +02:00
|
|
|
setCreature (SlotID(stacksCount()), stack.type->getId(), stack.count);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
2014-06-22 13:39:40 +03:00
|
|
|
|
2023-11-06 18:27:16 +02:00
|
|
|
void CBank::setPropertyDer (ObjProperty what, ObjPropertyID identifier)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
|
|
|
switch (what)
|
|
|
|
{
|
|
|
|
case ObjProperty::BANK_DAYCOUNTER: //daycounter
|
2023-11-06 18:27:16 +02:00
|
|
|
daycounter+= identifier.getNum();
|
2014-06-05 19:52:14 +03:00
|
|
|
break;
|
|
|
|
case ObjProperty::BANK_RESET:
|
2016-09-09 19:30:36 +02:00
|
|
|
// FIXME: Object reset must be done by separate netpack from server
|
|
|
|
initObj(cb->gameState()->getRandomGenerator());
|
2014-06-22 13:39:40 +03:00
|
|
|
daycounter = 1; //yes, 1 since "today" daycounter won't be incremented
|
2014-06-05 19:52:14 +03:00
|
|
|
break;
|
2014-06-22 13:39:40 +03:00
|
|
|
case ObjProperty::BANK_CLEAR:
|
|
|
|
bc.reset();
|
2014-06-05 19:52:14 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-09 19:30:36 +02:00
|
|
|
void CBank::newTurn(CRandomGenerator & rand) const
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
|
|
|
if (bc == nullptr)
|
|
|
|
{
|
2014-06-22 13:39:40 +03:00
|
|
|
if (resetDuration != 0)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2014-06-22 13:39:40 +03:00
|
|
|
if (daycounter >= resetDuration)
|
2023-11-06 18:27:16 +02:00
|
|
|
cb->setObjPropertyValue(id, ObjProperty::BANK_RESET); //daycounter 0
|
2014-06-22 13:39:40 +03:00
|
|
|
else
|
2023-11-06 18:27:16 +02:00
|
|
|
cb->setObjPropertyValue(id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-22 13:39:40 +03:00
|
|
|
|
2014-06-05 19:52:14 +03:00
|
|
|
bool CBank::wasVisited (PlayerColor player) const
|
|
|
|
{
|
2023-10-19 14:41:59 +02:00
|
|
|
return vstd::contains(cb->getPlayerState(player)->visitedObjects, ObjectInstanceID(id));
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
|
2017-11-15 22:16:44 +02:00
|
|
|
void CBank::onHeroVisit(const CGHeroInstance * h) const
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-10-19 14:41:59 +02:00
|
|
|
ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD_TEAM, id, h->id);
|
|
|
|
cb->sendAndApply(&cov);
|
|
|
|
|
2017-11-15 22:16:44 +02:00
|
|
|
int banktext = 0;
|
2023-11-02 16:29:59 +02:00
|
|
|
switch (ID.toEnum())
|
2017-11-15 22:16:44 +02:00
|
|
|
{
|
|
|
|
case Obj::DERELICT_SHIP:
|
|
|
|
banktext = 41;
|
|
|
|
break;
|
|
|
|
case Obj::DRAGON_UTOPIA:
|
|
|
|
banktext = 47;
|
|
|
|
break;
|
|
|
|
case Obj::CRYPT:
|
|
|
|
banktext = 119;
|
|
|
|
break;
|
|
|
|
case Obj::SHIPWRECK:
|
|
|
|
banktext = 122;
|
|
|
|
break;
|
|
|
|
case Obj::PYRAMID:
|
|
|
|
banktext = 105;
|
|
|
|
break;
|
|
|
|
case Obj::CREATURE_BANK:
|
|
|
|
default:
|
|
|
|
banktext = 32;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
BlockingDialog bd(true, false);
|
|
|
|
bd.player = h->getOwner();
|
2019-05-03 00:46:18 +02:00
|
|
|
bd.soundID = soundBase::invalid; // Sound is handled in json files, else two sounds are played
|
2023-06-18 11:18:25 +02:00
|
|
|
bd.text.appendLocalString(EMetaText::ADVOB_TXT, banktext);
|
2023-10-19 14:41:59 +02:00
|
|
|
bd.components = getPopupComponents(h->getOwner());
|
2017-11-15 22:16:44 +02:00
|
|
|
if (banktext == 32)
|
2023-06-18 11:18:25 +02:00
|
|
|
bd.text.replaceRawString(getObjectName());
|
2023-07-19 12:17:50 +02:00
|
|
|
|
2017-11-15 22:16:44 +02:00
|
|
|
cb->showBlockingDialog(&bd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBank::doVisit(const CGHeroInstance * hero) const
|
|
|
|
{
|
|
|
|
int textID = -1;
|
|
|
|
InfoWindow iw;
|
2023-03-07 03:09:19 +02:00
|
|
|
iw.type = EInfoWindowMode::AUTO;
|
2017-11-15 22:16:44 +02:00
|
|
|
iw.player = hero->getOwner();
|
|
|
|
MetaString loot;
|
|
|
|
|
2014-06-05 19:52:14 +03:00
|
|
|
if (bc)
|
|
|
|
{
|
2023-11-02 16:29:59 +02:00
|
|
|
switch (ID.toEnum())
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
|
|
|
case Obj::DERELICT_SHIP:
|
2017-11-15 22:16:44 +02:00
|
|
|
textID = 43;
|
2014-06-05 19:52:14 +03:00
|
|
|
break;
|
|
|
|
case Obj::CRYPT:
|
2017-11-15 22:16:44 +02:00
|
|
|
textID = 121;
|
2014-06-05 19:52:14 +03:00
|
|
|
break;
|
|
|
|
case Obj::SHIPWRECK:
|
2017-11-15 22:16:44 +02:00
|
|
|
textID = 124;
|
2014-06-05 19:52:14 +03:00
|
|
|
break;
|
2014-06-22 13:39:40 +03:00
|
|
|
case Obj::PYRAMID:
|
2017-11-15 22:16:44 +02:00
|
|
|
textID = 106;
|
|
|
|
break;
|
|
|
|
case Obj::CREATURE_BANK:
|
|
|
|
case Obj::DRAGON_UTOPIA:
|
|
|
|
default:
|
|
|
|
textID = 34;
|
2014-06-22 13:39:40 +03:00
|
|
|
break;
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-11-02 16:29:59 +02:00
|
|
|
switch (ID.toEnum())
|
2014-06-22 13:39:40 +03:00
|
|
|
{
|
2017-11-15 22:16:44 +02:00
|
|
|
case Obj::SHIPWRECK:
|
|
|
|
case Obj::DERELICT_SHIP:
|
|
|
|
case Obj::CRYPT:
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
|
|
|
GiveBonus gbonus;
|
2023-11-06 18:27:16 +02:00
|
|
|
gbonus.id = hero->id;
|
2023-05-01 00:20:01 +02:00
|
|
|
gbonus.bonus.duration = BonusDuration::ONE_BATTLE;
|
2023-10-21 14:06:18 +02:00
|
|
|
gbonus.bonus.source = BonusSource::OBJECT_TYPE;
|
2023-10-21 13:50:42 +02:00
|
|
|
gbonus.bonus.sid = BonusSourceID(ID);
|
2023-05-01 00:20:01 +02:00
|
|
|
gbonus.bonus.type = BonusType::MORALE;
|
2014-06-05 19:52:14 +03:00
|
|
|
gbonus.bonus.val = -1;
|
2023-11-02 16:29:59 +02:00
|
|
|
switch (ID.toEnum())
|
2017-11-15 22:16:44 +02:00
|
|
|
{
|
|
|
|
case Obj::SHIPWRECK:
|
|
|
|
textID = 123;
|
2023-06-18 11:18:25 +02:00
|
|
|
gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[99]);
|
2017-11-15 22:16:44 +02:00
|
|
|
break;
|
|
|
|
case Obj::DERELICT_SHIP:
|
|
|
|
textID = 42;
|
2023-06-18 11:18:25 +02:00
|
|
|
gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[101]);
|
2017-11-15 22:16:44 +02:00
|
|
|
break;
|
|
|
|
case Obj::CRYPT:
|
|
|
|
textID = 120;
|
2023-06-18 11:18:25 +02:00
|
|
|
gbonus.bdescr.appendRawString(VLC->generaltexth->arraytxt[98]);
|
2017-11-15 22:16:44 +02:00
|
|
|
break;
|
|
|
|
}
|
2014-06-05 19:52:14 +03:00
|
|
|
cb->giveHeroBonus(&gbonus);
|
2023-10-31 11:09:56 +02:00
|
|
|
iw.components.emplace_back(ComponentType::MORALE, -1);
|
2017-11-15 22:16:44 +02:00
|
|
|
iw.soundID = soundBase::GRAVEYARD;
|
|
|
|
break;
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
2017-11-15 22:16:44 +02:00
|
|
|
case Obj::PYRAMID:
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2017-11-15 22:16:44 +02:00
|
|
|
GiveBonus gb;
|
2023-10-21 14:06:18 +02:00
|
|
|
gb.bonus = Bonus(BonusDuration::ONE_BATTLE, BonusType::LUCK, BonusSource::OBJECT_INSTANCE, -2, BonusSourceID(id), VLC->generaltexth->arraytxt[70]);
|
2023-11-06 18:27:16 +02:00
|
|
|
gb.id = hero->id;
|
2017-11-15 22:16:44 +02:00
|
|
|
cb->giveHeroBonus(&gb);
|
|
|
|
textID = 107;
|
2023-10-31 11:09:56 +02:00
|
|
|
iw.components.emplace_back(ComponentType::LUCK, -2);
|
2017-11-15 22:16:44 +02:00
|
|
|
break;
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
2017-11-15 22:16:44 +02:00
|
|
|
case Obj::CREATURE_BANK:
|
|
|
|
case Obj::DRAGON_UTOPIA:
|
|
|
|
default:
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendRawString(VLC->generaltexth->advobtxt[33]);// This was X, now is completely empty
|
|
|
|
iw.text.replaceRawString(getObjectName());
|
2017-11-15 22:16:44 +02:00
|
|
|
}
|
|
|
|
if(textID != -1)
|
|
|
|
{
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendLocalString(EMetaText::ADVOB_TXT, textID);
|
2017-11-15 22:16:44 +02:00
|
|
|
}
|
|
|
|
cb->showInfoDialog(&iw);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
|
|
|
|
2014-06-05 19:52:14 +03:00
|
|
|
|
2014-06-22 13:39:40 +03:00
|
|
|
//grant resources
|
|
|
|
if (bc)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-10-31 11:09:56 +02:00
|
|
|
for (GameResID it : GameResID::ALL_RESOURCES())
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2014-06-22 13:39:40 +03:00
|
|
|
if (bc->resources[it] != 0)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-10-31 11:09:56 +02:00
|
|
|
iw.components.emplace_back(ComponentType::RESOURCE, it, bc->resources[it]);
|
2023-06-18 11:18:25 +02:00
|
|
|
loot.appendRawString("%d %s");
|
2023-10-31 11:09:56 +02:00
|
|
|
loot.replaceNumber(bc->resources[it]);
|
2023-11-08 16:13:08 +02:00
|
|
|
loot.replaceName(it);
|
2023-11-02 17:48:48 +02:00
|
|
|
cb->giveResource(hero->getOwner(), it, bc->resources[it]);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//grant artifacts
|
2014-06-22 13:39:40 +03:00
|
|
|
for (auto & elem : bc->artifacts)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-10-31 11:09:56 +02:00
|
|
|
iw.components.emplace_back(ComponentType::ARTIFACT, elem);
|
2023-06-18 11:18:25 +02:00
|
|
|
loot.appendRawString("%s");
|
2023-11-02 22:01:49 +02:00
|
|
|
loot.replaceName(elem);
|
2023-11-02 18:45:46 +02:00
|
|
|
cb->giveHeroNewArtifact(hero, elem.toArtifact(), ArtifactPosition::FIRST_AVAILABLE);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
//display loot
|
|
|
|
if (!iw.components.empty())
|
|
|
|
{
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendLocalString(EMetaText::ADVOB_TXT, textID);
|
2014-06-05 19:52:14 +03:00
|
|
|
if (textID == 34)
|
|
|
|
{
|
2023-04-05 02:26:29 +02:00
|
|
|
const auto * strongest = boost::range::max_element(bc->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b)
|
2014-06-22 13:39:40 +03:00
|
|
|
{
|
2023-04-05 02:26:29 +02:00
|
|
|
return a.type->getFightValue() < b.type->getFightValue();
|
2014-06-22 13:39:40 +03:00
|
|
|
})->type;
|
|
|
|
|
2023-11-02 22:01:49 +02:00
|
|
|
iw.text.replaceNamePlural(strongest->getId());
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.replaceRawString(loot.buildList());
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
cb->showInfoDialog(&iw);
|
|
|
|
}
|
2014-06-22 13:39:40 +03:00
|
|
|
|
2016-10-09 12:41:35 +02:00
|
|
|
loot.clear();
|
|
|
|
iw.components.clear();
|
|
|
|
iw.text.clear();
|
|
|
|
|
2014-06-22 13:39:40 +03:00
|
|
|
if (!bc->spells.empty())
|
|
|
|
{
|
|
|
|
std::set<SpellID> spells;
|
|
|
|
|
|
|
|
bool noWisdom = false;
|
2017-11-15 22:16:44 +02:00
|
|
|
if(textID == 106)
|
|
|
|
{
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendLocalString(EMetaText::ADVOB_TXT, textID); //pyramid
|
2017-11-15 22:16:44 +02:00
|
|
|
}
|
2016-10-09 12:41:35 +02:00
|
|
|
for(const SpellID & spellId : bc->spells)
|
2014-06-22 13:39:40 +03:00
|
|
|
{
|
2023-11-04 17:04:53 +02:00
|
|
|
const auto * spell = spellId.toEntity(VLC);
|
2023-11-02 22:01:49 +02:00
|
|
|
iw.text.appendName(spellId);
|
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
|
|
|
if(spell->getLevel() <= hero->maxSpellLevel())
|
2014-06-22 13:39:40 +03:00
|
|
|
{
|
2016-10-09 12:41:35 +02:00
|
|
|
if(hero->canLearnSpell(spell))
|
|
|
|
{
|
|
|
|
spells.insert(spellId);
|
2023-10-31 11:09:56 +02:00
|
|
|
iw.components.emplace_back(ComponentType::SPELL, spellId);
|
2016-10-09 12:41:35 +02:00
|
|
|
}
|
2014-06-22 13:39:40 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
noWisdom = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hero->getArt(ArtifactPosition::SPELLBOOK))
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendLocalString(EMetaText::ADVOB_TXT, 109); //no spellbook
|
2017-11-15 22:16:44 +02:00
|
|
|
else if(noWisdom)
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendLocalString(EMetaText::ADVOB_TXT, 108); //no expert Wisdom
|
2016-10-09 12:41:35 +02:00
|
|
|
|
|
|
|
if(!iw.components.empty() || !iw.text.toString().empty())
|
|
|
|
cb->showInfoDialog(&iw);
|
|
|
|
|
|
|
|
if(!spells.empty())
|
2017-11-15 22:16:44 +02:00
|
|
|
cb->changeSpells(hero, true, spells);
|
2014-06-22 13:39:40 +03:00
|
|
|
}
|
2016-10-09 12:41:35 +02:00
|
|
|
|
2014-06-05 19:52:14 +03:00
|
|
|
iw.components.clear();
|
|
|
|
iw.text.clear();
|
|
|
|
|
|
|
|
//grant creatures
|
|
|
|
CCreatureSet ourArmy;
|
2023-02-12 22:39:17 +02:00
|
|
|
for(const auto & slot : bc->creatures)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-04-05 02:26:29 +02:00
|
|
|
ourArmy.addToSlot(ourArmy.getSlotFor(slot.type->getId()), slot.type->getId(), slot.count);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
2014-06-22 13:39:40 +03:00
|
|
|
|
2023-02-12 22:39:17 +02:00
|
|
|
for(const auto & elem : ourArmy.Slots())
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2023-10-31 11:09:56 +02:00
|
|
|
iw.components.emplace_back(ComponentType::CREATURE, elem.second->getId(), elem.second->getCount());
|
2023-06-18 11:18:25 +02:00
|
|
|
loot.appendRawString("%s");
|
2023-11-02 22:01:49 +02:00
|
|
|
loot.replaceName(*elem.second);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
|
2015-12-24 20:30:57 +02:00
|
|
|
if(ourArmy.stacksCount())
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2015-12-24 20:30:57 +02:00
|
|
|
if(ourArmy.stacksCount() == 1 && ourArmy.Slots().begin()->second->count == 1)
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendLocalString(EMetaText::ADVOB_TXT, 185);
|
2014-06-05 19:52:14 +03:00
|
|
|
else
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.appendLocalString(EMetaText::ADVOB_TXT, 186);
|
2014-06-05 19:52:14 +03:00
|
|
|
|
2023-06-18 11:18:25 +02:00
|
|
|
iw.text.replaceRawString(loot.buildList());
|
|
|
|
iw.text.replaceRawString(hero->getNameTranslated());
|
2014-06-05 19:52:14 +03:00
|
|
|
cb->showInfoDialog(&iw);
|
|
|
|
cb->giveCreatures(this, hero, ourArmy, false);
|
|
|
|
}
|
2023-11-06 18:27:16 +02:00
|
|
|
cb->setObjPropertyValue(id, ObjProperty::BANK_CLEAR); //bc = nullptr
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-22 13:39:40 +03:00
|
|
|
void CBank::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2014-06-22 13:39:40 +03:00
|
|
|
if (result.winner == 0)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2014-06-22 13:39:40 +03:00
|
|
|
doVisit(hero);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-22 13:39:40 +03:00
|
|
|
void CBank::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2014-06-22 13:39:40 +03:00
|
|
|
if (answer)
|
2014-06-05 19:52:14 +03:00
|
|
|
{
|
2014-06-22 13:39:40 +03:00
|
|
|
if (bc) // not looted bank
|
|
|
|
cb->startBattleI(hero, this, true);
|
2014-06-05 19:52:14 +03:00
|
|
|
else
|
2014-06-22 13:39:40 +03:00
|
|
|
doVisit(hero);
|
2014-06-05 19:52:14 +03:00
|
|
|
}
|
|
|
|
}
|
2022-07-26 15:07:42 +02:00
|
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_END
|