mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-09 07:13:54 +02:00
Merge branch 'develop' into mutexRelax
This commit is contained in:
commit
a6ea0981b6
@ -531,7 +531,7 @@ std::vector<BattleHex> CBattleAI::getTargetsToConsider( const CSpell *spell ) co
|
||||
{
|
||||
if(spell->getTargetType() == CSpell::NO_TARGET)
|
||||
{
|
||||
//Spell can be casted anywhere, all hexes are potentially considerable.
|
||||
//Spell can be cast anywhere, all hexes are potentially considerable.
|
||||
std::vector<BattleHex> ret;
|
||||
|
||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; i++)
|
||||
|
@ -432,7 +432,7 @@ bool boundaryBetweenTwoPoints (int3 pos1, int3 pos2, CCallback * cbp) //determin
|
||||
for (int y = yMin; y <= yMax; ++y)
|
||||
{
|
||||
int3 tile = int3(x, y, pos1.z); //use only on same level, ofc
|
||||
if (abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5)
|
||||
if (std::abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5)
|
||||
{
|
||||
if (!(cbp->isVisible(tile) && cbp->getTile(tile)->blocked)) //if there's invisible or unblocked tile between, it's good
|
||||
return false;
|
||||
@ -509,4 +509,4 @@ bool compareArtifacts(const CArtifactInstance *a1, const CArtifactInstance *a2)
|
||||
return true;
|
||||
else
|
||||
return art1->price > art2->price;
|
||||
}
|
||||
}
|
||||
|
42
CCallback.h
42
CCallback.h
@ -119,34 +119,34 @@ public:
|
||||
void unregisterAllInterfaces(); //stops delivering information about game events to player interfaces -> can be called ONLY after victory/loss
|
||||
|
||||
//commands
|
||||
bool moveHero(const CGHeroInstance *h, int3 dst, bool transit = false); //dst must be free, neighbouring tile (this function can move hero only by one tile)
|
||||
bool moveHero(const CGHeroInstance *h, int3 dst, bool transit = false) override; //dst must be free, neighbouring tile (this function can move hero only by one tile)
|
||||
bool teleportHero(const CGHeroInstance *who, const CGTownInstance *where);
|
||||
int selectionMade(int selection, QueryID queryID);
|
||||
int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2);
|
||||
int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2); //first goes to the second
|
||||
int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2); //first goes to the second
|
||||
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2, int val);
|
||||
bool dismissHero(const CGHeroInstance * hero);
|
||||
int selectionMade(int selection, QueryID queryID) override;
|
||||
int swapCreatures(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2) override;
|
||||
int mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2) override; //first goes to the second
|
||||
int mergeStacks(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2) override; //first goes to the second
|
||||
int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2, int val) override;
|
||||
bool dismissHero(const CGHeroInstance * hero) override;
|
||||
//bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2);
|
||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2);
|
||||
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
|
||||
//bool moveArtifact(const CGHeroInstance * hero, ui16 src, const CStackInstance * stack, ui16 dest); // TODO: unify classes
|
||||
//bool moveArtifact(const CStackInstance * stack, ui16 src , const CGHeroInstance * hero, ui16 dest); // TODO: unify classes
|
||||
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo);
|
||||
bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override;
|
||||
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
|
||||
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1);
|
||||
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos);
|
||||
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;
|
||||
bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override;
|
||||
bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE) override;
|
||||
void endTurn();
|
||||
void swapGarrisonHero(const CGTownInstance *town);
|
||||
void endTurn() override;
|
||||
void swapGarrisonHero(const CGTownInstance *town) override;
|
||||
void buyArtifact(const CGHeroInstance *hero, ArtifactID aid) override;
|
||||
void trade(const CGObjectInstance *market, EMarketMode::EMarketMode mode, int id1, int id2, int val1, const CGHeroInstance *hero = nullptr);
|
||||
void setFormation(const CGHeroInstance * hero, bool tight);
|
||||
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero);
|
||||
void save(const std::string &fname);
|
||||
void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr);
|
||||
void buildBoat(const IShipyard *obj);
|
||||
void dig(const CGObjectInstance *hero);
|
||||
void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1));
|
||||
void trade(const CGObjectInstance *market, EMarketMode::EMarketMode mode, int id1, int id2, int val1, const CGHeroInstance *hero = nullptr) override;
|
||||
void setFormation(const CGHeroInstance * hero, bool tight) override;
|
||||
void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero) override;
|
||||
void save(const std::string &fname) override;
|
||||
void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) override;
|
||||
void buildBoat(const IShipyard *obj) override;
|
||||
void dig(const CGObjectInstance *hero) override;
|
||||
void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1)) override;
|
||||
|
||||
//friends
|
||||
friend class CClient;
|
||||
|
@ -115,7 +115,7 @@ endif()
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} ${CMAKE_DL_LIBS})
|
||||
|
||||
set(FFmpeg_FIND_COMPONENTS AVFORMAT SWSCALE)
|
||||
find_package(Boost 1.48.0 COMPONENTS filesystem locale program_options system thread REQUIRED)
|
||||
find_package(Boost 1.48.0 COMPONENTS date_time filesystem locale program_options system thread REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(FFmpeg REQUIRED)
|
||||
find_package(Minizip)
|
||||
@ -150,7 +150,7 @@ endif()
|
||||
|
||||
if(ENABLE_TEST)
|
||||
# find_package overwrites BOOST_* variables which are already set, so all components have to be included again
|
||||
find_package(Boost 1.48.0 COMPONENTS program_options filesystem system thread locale unit_test_framework REQUIRED)
|
||||
find_package(Boost 1.48.0 COMPONENTS date_time program_options filesystem system thread locale unit_test_framework REQUIRED)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR NOT WIN32) #so far all *nix compilers support such parameters
|
||||
|
@ -3,7 +3,7 @@
|
||||
ADVETURE AI:
|
||||
* Fixed AI trying to go through underground rock
|
||||
* Fixed several cases causing AI wandering aimlessly
|
||||
* AI can again pick bets artifacts and exchange artifacts between heroes
|
||||
* AI can again pick best artifacts and exchange artifacts between heroes
|
||||
|
||||
RANDOM MAP GENERATOR:
|
||||
* Changed fractalization algorithm so it can create cycles
|
||||
|
3
Global.h
3
Global.h
@ -61,7 +61,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
# define VCMI_UNIX
|
||||
# define VCMI_XDG
|
||||
# define VCMI_FREEBSD
|
||||
#elif defined(__GNU__) || defined(__gnu_hurd__) || (defined(__MACH__) && !defined(__APPLE))
|
||||
#elif defined(__GNU__) || defined(__gnu_hurd__) || (defined(__MACH__) && !defined(__APPLE__))
|
||||
# define VCMI_UNIX
|
||||
# define VCMI_XDG
|
||||
# define VCMI_HURD
|
||||
@ -150,6 +150,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#endif
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/optional/optional_io.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
|
@ -102,7 +102,7 @@ if(APPLE)
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/osx/vcmibuilder.app ${BUNDLE_PATH}/MacOS/vcmibuilder.app &&
|
||||
|
||||
# Copy frameworks
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/${CMAKE_FRAMEWORK_PATH} ${BUNDLE_PATH}/Frameworks/ &&
|
||||
sh -c 'cp -r ${CMAKE_HOME_DIRECTORY}/${CMAKE_FRAMEWORK_PATH} ${BUNDLE_PATH}/Frameworks/ || true' &&
|
||||
|
||||
# Copy vcmi data
|
||||
mkdir -p ${BUNDLE_PATH}/Data &&
|
||||
@ -110,7 +110,8 @@ if(APPLE)
|
||||
mkdir -p ${BUNDLE_PATH}/Data/launcher &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/config/ ${BUNDLE_PATH}/Data/config/ &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/Mods/vcmi/ ${BUNDLE_PATH}/Data/Mods/vcmi/ &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/Mods/WoG/ ${BUNDLE_PATH}/Data/Mods/WoG/ &&
|
||||
sh -c 'cp -r ${CMAKE_HOME_DIRECTORY}/Mods/WoG/ ${BUNDLE_PATH}/Data/Mods/WoG/ || echo "Download WoG mod from http://wiki.vcmi.eu/index.php?title=Mod_list"' &&
|
||||
sh -c 'cp -r ${CMAKE_HOME_DIRECTORY}/Mods/hota/ ${BUNDLE_PATH}/Data/Mods/hota/ || echo "Download HOTA mod from http://wiki.vcmi.eu/index.php?title=Mod_list"' &&
|
||||
cp -r ${CMAKE_HOME_DIRECTORY}/launcher/icons/ ${BUNDLE_PATH}/Data/launcher/icons/)
|
||||
|
||||
add_custom_command(TARGET vcmiclient POST_BUILD COMMAND ${MakeVCMIBundle})
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
CComponent *comp;
|
||||
|
||||
//blit component with image centered at this position
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
//ComponentResolved(); //c-tor
|
||||
ComponentResolved(CComponent *Comp); //c-tor
|
||||
|
@ -52,10 +52,10 @@ private:
|
||||
public:
|
||||
CSoundHandler();
|
||||
|
||||
void init();
|
||||
void release();
|
||||
void init() override;
|
||||
void release() override;
|
||||
|
||||
void setVolume(ui32 percent);
|
||||
void setVolume(ui32 percent) override;
|
||||
|
||||
// Sounds
|
||||
int playSound(soundBase::soundID soundID, int repeats=0);
|
||||
@ -127,9 +127,9 @@ public:
|
||||
/// add entry with URI musicURI in set. Track will have ID musicID
|
||||
void addEntryToSet(std::string set, int musicID, std::string musicURI);
|
||||
|
||||
void init();
|
||||
void release();
|
||||
void setVolume(ui32 percent);
|
||||
void init() override;
|
||||
void release() override;
|
||||
void setVolume(ui32 percent) override;
|
||||
|
||||
/// play track by URI, if loop = true music will be looped
|
||||
void playMusic(std::string musicURI, bool loop);
|
||||
|
@ -772,7 +772,8 @@ BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when i
|
||||
{
|
||||
THREAD_CREATED_BY_CLIENT;
|
||||
logGlobal->traceStream() << "Awaiting command for " << stack->nodeName();
|
||||
|
||||
auto stackId = stack->ID;
|
||||
auto stackName = stack->nodeName();
|
||||
if(autofightingAI)
|
||||
{
|
||||
if(isAutoFightOn)
|
||||
@ -806,17 +807,23 @@ BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when i
|
||||
while(!b->givenCommand->data)
|
||||
{
|
||||
b->givenCommand->cond.wait(lock);
|
||||
if(!battleInt) //batle ended while we were waiting for movement (eg. because of spell)
|
||||
if(!battleInt) //battle ended while we were waiting for movement (eg. because of spell)
|
||||
throw boost::thread_interrupted(); //will shut the thread peacefully
|
||||
}
|
||||
|
||||
//tidy up
|
||||
BattleAction ret = *(b->givenCommand->data);
|
||||
delete b->givenCommand->data;
|
||||
b->givenCommand->data = nullptr;
|
||||
|
||||
//return command
|
||||
logGlobal->traceStream() << "Giving command for " << stack->nodeName();
|
||||
vstd::clear_pointer(b->givenCommand->data);
|
||||
|
||||
if(ret.actionType == Battle::CANCEL)
|
||||
{
|
||||
if(stackId != ret.stackNumber)
|
||||
logGlobal->error("Not current active stack action canceled");
|
||||
logGlobal->traceStream() << "Canceled command for " << stackName;
|
||||
}
|
||||
else
|
||||
logGlobal->traceStream() << "Giving command for " << stackName;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -147,11 +147,11 @@ public:
|
||||
void newStackInserted(const StackLocation &location, const CStackInstance &stack) override; //new stack inserted at given (previously empty position)
|
||||
void stacksRebalanced(const StackLocation &src, const StackLocation &dst, TQuantity count) override; //moves creatures from src stack to dst slot, may be used for merging/splittint/moving stacks
|
||||
|
||||
void artifactPut(const ArtifactLocation &al);
|
||||
void artifactRemoved(const ArtifactLocation &al);
|
||||
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst);
|
||||
void artifactAssembled(const ArtifactLocation &al);
|
||||
void artifactDisassembled(const ArtifactLocation &al);
|
||||
void artifactPut(const ArtifactLocation &al) override;
|
||||
void artifactRemoved(const ArtifactLocation &al) override;
|
||||
void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override;
|
||||
void artifactAssembled(const ArtifactLocation &al) override;
|
||||
void artifactDisassembled(const ArtifactLocation &al) override;
|
||||
|
||||
void heroCreated(const CGHeroInstance* hero) override;
|
||||
void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;
|
||||
@ -236,7 +236,7 @@ public:
|
||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||
void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero
|
||||
void updateInfo(const CGObjectInstance * specific);
|
||||
void init(shared_ptr<CCallback> CB);
|
||||
void init(shared_ptr<CCallback> CB) override;
|
||||
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
|
||||
|
||||
// show dialogs
|
||||
|
@ -207,7 +207,7 @@ public:
|
||||
template <typename T> class CApplyOnPG : public CBaseForPGApply
|
||||
{
|
||||
public:
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const override
|
||||
{
|
||||
T *ptr = static_cast<T*>(pack);
|
||||
ptr->apply(selScr);
|
||||
@ -217,7 +217,7 @@ public:
|
||||
template <> class CApplyOnPG<CPack> : public CBaseForPGApply
|
||||
{
|
||||
public:
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const
|
||||
void applyOnPG(CSelectionScreen *selScr, void *pack) const override
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot apply on PG plain CPack!";
|
||||
assert(0);
|
||||
|
@ -75,10 +75,10 @@ public:
|
||||
};
|
||||
CMenuScreen(const JsonNode& configNode);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to);
|
||||
void activate();
|
||||
void deactivate();
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
void switchToTab(size_t index);
|
||||
};
|
||||
@ -100,10 +100,10 @@ class CreditsScreen : public CIntObject
|
||||
public:
|
||||
CreditsScreen();
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
};
|
||||
|
||||
/// Implementation of the chat box
|
||||
@ -115,7 +115,7 @@ public:
|
||||
|
||||
CChatBox(const Rect &rect);
|
||||
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
|
||||
void addNewMessage(const std::string &text);
|
||||
};
|
||||
@ -136,8 +136,8 @@ public:
|
||||
CDefHandler *sizes, *sFlags;
|
||||
|
||||
void changeSelection(const CMapInfo *to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void showTeamsPopup();
|
||||
void toggleChat();
|
||||
void setChat(bool activateChat);
|
||||
@ -184,10 +184,10 @@ public:
|
||||
void selectFName(std::string fname);
|
||||
const CMapInfo * getSelectedMapInfo() const;
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void onDoubleClick();
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void onDoubleClick() override;
|
||||
SelectionTab(CMenuScreen::EState Type, const std::function<void(CMapInfo *)> &OnSelect, CMenuScreen::EMultiMode MultiPlayer = CMenuScreen::SINGLE_PLAYER);
|
||||
~SelectionTab();
|
||||
};
|
||||
@ -235,7 +235,7 @@ public:
|
||||
CLabel *subtitle;
|
||||
|
||||
SelectedBox(Point position, PlayerSettings & settings, SelType type);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
|
||||
void update();
|
||||
};
|
||||
@ -254,7 +254,7 @@ public:
|
||||
|
||||
PlayerOptionsEntry(OptionsTab *owner, PlayerSettings &S);
|
||||
void selectButtons(); //hides unavailable buttons
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void update();
|
||||
};
|
||||
|
||||
@ -282,7 +282,7 @@ public:
|
||||
void recreate();
|
||||
OptionsTab();
|
||||
~OptionsTab();
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
int nextAllowedHero(PlayerColor player, int min, int max, int incl, int dir );
|
||||
|
||||
@ -295,7 +295,7 @@ class CRandomMapTab : public CIntObject
|
||||
public:
|
||||
CRandomMapTab();
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void updateMapInfo();
|
||||
CFunctionList<void (const CMapInfo *)> & getMapInfoChanged();
|
||||
const CMapInfo * getMapInfo() const;
|
||||
@ -385,7 +385,7 @@ public:
|
||||
void postRequest(ui8 what, ui8 dir) override;
|
||||
void postChatMessage(const std::string &txt) override;
|
||||
void propagateNames();
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
};
|
||||
|
||||
/// Save game screen
|
||||
@ -454,8 +454,8 @@ class CPrologEpilogVideo : public CWindowObject
|
||||
public:
|
||||
CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog _spe, std::function<void()> callback);
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void show(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// Campaign screen where you can choose one out of three starting bonuses
|
||||
@ -498,9 +498,9 @@ private:
|
||||
CRegion(CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber);
|
||||
~CRegion();
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void show(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
void init();
|
||||
@ -560,12 +560,12 @@ private:
|
||||
std::string video; // the resource name of the video
|
||||
std::string hoverText;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
|
||||
public:
|
||||
CCampaignButton(const JsonNode &config );
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
CButton *back;
|
||||
@ -578,7 +578,7 @@ public:
|
||||
enum CampaignSet {ROE, AB, SOD, WOG};
|
||||
|
||||
CCampaignScreen(const JsonNode &config);
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
};
|
||||
|
||||
/// Manages the configuration of pregame GUI elements like campaign screen, main menu, loading screen,...
|
||||
@ -629,7 +629,7 @@ public:
|
||||
CLoadingScreen(std::function<void()> loader);
|
||||
~CLoadingScreen();
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
};
|
||||
|
||||
/// Simple window to enter the server's address.
|
||||
|
@ -72,12 +72,12 @@ public:
|
||||
template <typename T> class CApplyOnCL : public CBaseForCLApply
|
||||
{
|
||||
public:
|
||||
void applyOnClAfter(CClient *cl, void *pack) const
|
||||
void applyOnClAfter(CClient *cl, void *pack) const override
|
||||
{
|
||||
T *ptr = static_cast<T*>(pack);
|
||||
ptr->applyCl(cl);
|
||||
}
|
||||
void applyOnClBefore(CClient *cl, void *pack) const
|
||||
void applyOnClBefore(CClient *cl, void *pack) const override
|
||||
{
|
||||
T *ptr = static_cast<T*>(pack);
|
||||
ptr->applyFirstCl(cl);
|
||||
@ -87,12 +87,12 @@ public:
|
||||
template <> class CApplyOnCL<CPack> : public CBaseForCLApply
|
||||
{
|
||||
public:
|
||||
void applyOnClAfter(CClient *cl, void *pack) const
|
||||
void applyOnClAfter(CClient *cl, void *pack) const override
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot apply on CL plain CPack!";
|
||||
assert(0);
|
||||
}
|
||||
void applyOnClBefore(CClient *cl, void *pack) const
|
||||
void applyOnClBefore(CClient *cl, void *pack) const override
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot apply on CL plain CPack!";
|
||||
assert(0);
|
||||
@ -140,9 +140,12 @@ void CClient::waitForMoveAndSend(PlayerColor color)
|
||||
setThreadName("CClient::waitForMoveAndSend");
|
||||
assert(vstd::contains(battleints, color));
|
||||
BattleAction ba = battleints[color]->activeStack(gs->curB->battleGetStackByID(gs->curB->activeStack, false));
|
||||
logNetwork->traceStream() << "Send battle action to server: " << ba;
|
||||
MakeAction temp_action(ba);
|
||||
sendRequest(&temp_action, color);
|
||||
if(ba.actionType != Battle::CANCEL)
|
||||
{
|
||||
logNetwork->traceStream() << "Send battle action to server: " << ba;
|
||||
MakeAction temp_action(ba);
|
||||
sendRequest(&temp_action, color);
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch(boost::thread_interrupted&)
|
||||
|
@ -189,7 +189,7 @@ public:
|
||||
bool changeStackType(const StackLocation &sl, const CCreature *c) override {return false;};
|
||||
bool changeStackCount(const StackLocation &sl, TQuantity count, bool absoluteValue = false) override {return false;};
|
||||
bool insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count) override {return false;};
|
||||
bool eraseStack(const StackLocation &sl, bool forceRemoval = false){return false;};
|
||||
bool eraseStack(const StackLocation &sl, bool forceRemoval = false) override{return false;};
|
||||
bool swapStacks(const StackLocation &sl1, const StackLocation &sl2) override {return false;}
|
||||
bool addToSlot(const StackLocation &sl, const CCreature *c, TQuantity count) override {return false;}
|
||||
void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) override {}
|
||||
|
@ -750,7 +750,7 @@ void CatapultAttack::applyCl( CClient *cl )
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleCatapultAttacked, *this);
|
||||
}
|
||||
|
||||
void BattleStacksRemoved::applyCl( CClient *cl )
|
||||
void BattleStacksRemoved::applyFirstCl(CClient * cl)
|
||||
{
|
||||
//inform interfaces about removed stacks
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_FOR_BOTH_SIDES(battleStacksRemoved, *this);
|
||||
|
@ -782,7 +782,7 @@ bool CShootingAnimation::init()
|
||||
spi.catapultInfo.reset(new CatapultProjectileInfo(Point(spi.x, spi.y), destPos));
|
||||
|
||||
double animSpeed = AnimationControls::getProjectileSpeed() / 10;
|
||||
spi.lastStep = abs((destPos.x - spi.x) / animSpeed);
|
||||
spi.lastStep = std::abs((destPos.x - spi.x) / animSpeed);
|
||||
spi.dx = animSpeed;
|
||||
spi.dy = 0;
|
||||
|
||||
|
@ -59,8 +59,8 @@ protected:
|
||||
const CStack *attackingStack;
|
||||
int attackingStackPosBeforeReturn; //for stacks with return_after_strike feature
|
||||
public:
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
bool checkInitialConditions();
|
||||
|
||||
CAttackAnimation(CBattleInterface *_owner, const CStack *attacker, BattleHex _dest, const CStack *defender);
|
||||
@ -80,9 +80,9 @@ class CDefenceAnimation : public CBattleStackAnimation
|
||||
|
||||
float timeToWait; // for how long this animation should be paused
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CDefenceAnimation(StackAttackedInfo _attackedInfo, CBattleInterface * _owner);
|
||||
virtual ~CDefenceAnimation(){};
|
||||
@ -94,9 +94,9 @@ private:
|
||||
int counter;
|
||||
int howMany;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CDummyAnimation(CBattleInterface * _owner, int howManyFrames);
|
||||
virtual ~CDummyAnimation(){}
|
||||
@ -106,8 +106,8 @@ public:
|
||||
class CMeleeAttackAnimation : public CAttackAnimation
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMeleeAttackAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest, const CStack * _attacked);
|
||||
virtual ~CMeleeAttackAnimation(){};
|
||||
@ -133,9 +133,9 @@ private:
|
||||
public:
|
||||
BattleHex nextHex; // next hex, to which creature move right now
|
||||
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMovementAnimation(CBattleInterface *_owner, const CStack *_stack, std::vector<BattleHex> _destTiles, int _distance);
|
||||
virtual ~CMovementAnimation(){};
|
||||
@ -147,8 +147,8 @@ class CMovementEndAnimation : public CBattleStackAnimation
|
||||
private:
|
||||
BattleHex destinationTile;
|
||||
public:
|
||||
bool init();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMovementEndAnimation(CBattleInterface * _owner, const CStack * _stack, BattleHex destTile);
|
||||
virtual ~CMovementEndAnimation(){};
|
||||
@ -158,8 +158,8 @@ public:
|
||||
class CMovementStartAnimation : public CBattleStackAnimation
|
||||
{
|
||||
public:
|
||||
bool init();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void endAnim() override;
|
||||
|
||||
CMovementStartAnimation(CBattleInterface * _owner, const CStack * _stack);
|
||||
virtual ~CMovementStartAnimation(){};
|
||||
@ -171,12 +171,12 @@ class CReverseAnimation : public CBattleStackAnimation
|
||||
BattleHex hex;
|
||||
public:
|
||||
bool priority; //true - high, false - low
|
||||
bool init();
|
||||
bool init() override;
|
||||
|
||||
static void rotateStack(CBattleInterface * owner, const CStack * stack, BattleHex hex);
|
||||
|
||||
void setupSecondPart();
|
||||
void endAnim();
|
||||
void endAnim() override;
|
||||
|
||||
CReverseAnimation(CBattleInterface * _owner, const CStack * stack, BattleHex dest, bool _priority);
|
||||
virtual ~CReverseAnimation(){};
|
||||
@ -204,9 +204,9 @@ class CShootingAnimation : public CAttackAnimation
|
||||
private:
|
||||
int catapultDamage;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
//last two params only for catapult attacks
|
||||
CShootingAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest,
|
||||
@ -225,9 +225,9 @@ private:
|
||||
bool Vflip;
|
||||
bool alignToBottom;
|
||||
public:
|
||||
bool init();
|
||||
void nextFrame();
|
||||
void endAnim();
|
||||
bool init() override;
|
||||
void nextFrame() override;
|
||||
void endAnim() override;
|
||||
|
||||
CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||
CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||
|
@ -1005,11 +1005,22 @@ void CBattleInterface::newStack(const CStack * stack)
|
||||
|
||||
void CBattleInterface::stackRemoved(int stackID)
|
||||
{
|
||||
if(activeStack != nullptr)
|
||||
{
|
||||
if(activeStack->ID == stackID)
|
||||
{
|
||||
BattleAction * action = new BattleAction();
|
||||
action->side = defendingHeroInstance ? (curInt->playerID == defendingHeroInstance->tempOwner) : false;
|
||||
action->actionType = Battle::CANCEL;
|
||||
action->stackNumber = activeStack->ID;
|
||||
givenCommand->setn(action);
|
||||
setActiveStack(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
delete creAnims[stackID];
|
||||
creAnims.erase(stackID);
|
||||
creDir.erase(stackID);
|
||||
//FIXME: what if currently removed stack is active one (Sacrifice)?
|
||||
|
||||
redrawBackgroundWithHexes(activeStack);
|
||||
queue->update();
|
||||
}
|
||||
@ -1091,10 +1102,6 @@ void CBattleInterface::newRoundFirst( int round )
|
||||
void CBattleInterface::newRound(int number)
|
||||
{
|
||||
console->addText(CGI->generaltexth->allTexts[412]);
|
||||
|
||||
//unlock spellbook
|
||||
//bSpell->block(!curInt->cb->battleCanCastSpell());
|
||||
//don't unlock spellbook - this should be done when we have axctive creature
|
||||
}
|
||||
|
||||
void CBattleInterface::giveCommand(Battle::ActionType action, BattleHex tile, ui32 stackID, si32 additional, si32 selected)
|
||||
@ -1379,7 +1386,7 @@ void CBattleInterface::castThisSpell(SpellID spellID)
|
||||
sp = spellID.toSpell();
|
||||
spellSelMode = ANY_LOCATION;
|
||||
|
||||
const CSpell::TargetInfo ti = sp->getTargetInfo(castingHero->getSpellSchoolLevel(sp));
|
||||
const CSpell::TargetInfo ti(sp, castingHero->getSpellSchoolLevel(sp));
|
||||
|
||||
if(ti.massive || ti.type == CSpell::NO_TARGET)
|
||||
spellSelMode = NO_LOCATION;
|
||||
@ -2103,9 +2110,9 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
{
|
||||
ui8 skill = 0;
|
||||
if (creatureCasting)
|
||||
skill = sactive->getSpellSchoolLevel(SpellID(SpellID::TELEPORT).toSpell());
|
||||
skill = sactive->getEffectLevel(SpellID(SpellID::TELEPORT).toSpell());
|
||||
else
|
||||
skill = getActiveHero()->getSpellSchoolLevel (CGI->spellh->objects[spellToCast->additionalInfo]);
|
||||
skill = getActiveHero()->getEffectLevel(SpellID(SpellID::TELEPORT).toSpell());
|
||||
//TODO: explicitely save power, skill
|
||||
if (curInt->cb->battleCanTeleportTo(selectedStack, myNumber, skill))
|
||||
legalAction = true;
|
||||
@ -2470,11 +2477,19 @@ bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CSta
|
||||
|
||||
if (sp)
|
||||
{
|
||||
if (creatureCasting)
|
||||
isCastingPossible = (curInt->cb->battleCanCreatureCastThisSpell (sp, myNumber) == ESpellCastProblem::OK);
|
||||
const ISpellCaster * caster = creatureCasting ? dynamic_cast<const ISpellCaster *>(sactive) : dynamic_cast<const ISpellCaster *>(curInt->cb->battleGetMyHero());
|
||||
if(caster == nullptr)
|
||||
{
|
||||
isCastingPossible = false;//just in case
|
||||
}
|
||||
else
|
||||
isCastingPossible = (curInt->cb->battleCanCastThisSpell (sp, myNumber) == ESpellCastProblem::OK);
|
||||
{
|
||||
const ECastingMode::ECastingMode mode = creatureCasting ? ECastingMode::CREATURE_ACTIVE_CASTING : ECastingMode::HERO_CASTING;
|
||||
isCastingPossible = (curInt->cb->battleCanCastThisSpellHere(caster, sp, mode, myNumber) == ESpellCastProblem::OK);
|
||||
}
|
||||
}
|
||||
else
|
||||
isCastingPossible = false;
|
||||
if(!myNumber.isAvailable() && !shere) //empty tile outside battlefield (or in the unavailable border column)
|
||||
isCastingPossible = false;
|
||||
|
||||
|
@ -291,14 +291,14 @@ public:
|
||||
void bEndTacticPhase();
|
||||
//end of button handle funcs
|
||||
//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
|
||||
void activate();
|
||||
void deactivate();
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void mouseMoved(const SDL_MouseMotionEvent &sEvent);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void mouseMoved(const SDL_MouseMotionEvent &sEvent) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
|
||||
void show(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to);
|
||||
void show(SDL_Surface *to) override;
|
||||
void showAll(SDL_Surface *to) override;
|
||||
|
||||
//call-ins
|
||||
void startAction(const BattleAction* action);
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
std::string ingcAlter; //alternative text set by in-game console - very important!
|
||||
int whoSetAlter; //who set alter text; 0 - battle interface or none, 1 - button
|
||||
CBattleConsole();
|
||||
void showAll(SDL_Surface * to = 0);
|
||||
void showAll(SDL_Surface * to = 0) override;
|
||||
bool addText(const std::string &text); //adds text at the last position; returns false if failed (e.g. text longer than 70 characters)
|
||||
void alterText(const std::string &text); //place string at alterTxt
|
||||
void eraseText(ui32 pos); //erases added text at position pos
|
||||
@ -60,9 +60,9 @@ public:
|
||||
int nextPhase; //stage of animation to be set after current phase is fully displayed
|
||||
int currentFrame, firstFrame, lastFrame; //frame of animation
|
||||
ui8 flagAnim, animCount; //for flag animation
|
||||
void show(SDL_Surface * to); //prints next frame of animation to to
|
||||
void show(SDL_Surface * to) override; //prints next frame of animation to to
|
||||
void setPhase(int newPhase); //sets phase of hero animation
|
||||
void clickLeft(tribool down, bool previousState); //call-in
|
||||
void clickLeft(tribool down, bool previousState) override; //call-in
|
||||
CBattleHero(const std::string &defName, bool filpG, PlayerColor player, const CGHeroInstance *hero, const CBattleInterface *owner); //c-tor
|
||||
~CBattleHero(); //d-tor
|
||||
};
|
||||
@ -96,8 +96,8 @@ public:
|
||||
|
||||
void bExitf(); //exit button callback
|
||||
|
||||
void activate();
|
||||
void show(SDL_Surface * to = 0);
|
||||
void activate() override;
|
||||
void show(SDL_Surface * to = 0) override;
|
||||
};
|
||||
|
||||
/// Class which stands for a single hex field on a battlefield
|
||||
@ -114,10 +114,10 @@ public:
|
||||
static Point getXYUnitAnim(BattleHex hexNum, const CStack * creature, CBattleInterface * cbi); //returns (x, y) of left top corner of animation
|
||||
|
||||
//for user interactions
|
||||
void hover (bool on);
|
||||
void mouseMoved (const SDL_MouseMotionEvent &sEvent);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover (bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent &sEvent) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
CClickableHex();
|
||||
};
|
||||
|
||||
@ -132,7 +132,7 @@ class CStackQueue : public CIntObject
|
||||
const CStack *stack;
|
||||
bool small;
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void setStack(const CStack *nStack);
|
||||
StackBox(bool small);
|
||||
};
|
||||
@ -150,6 +150,6 @@ public:
|
||||
CStackQueue(bool Embedded, CBattleInterface * _owner);
|
||||
~CStackQueue();
|
||||
void update();
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
void blitBg(SDL_Surface * to);
|
||||
};
|
||||
|
@ -98,10 +98,10 @@ public:
|
||||
SDLImage(SDL_Surface * from, bool extraRef);
|
||||
~SDLImage();
|
||||
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const;
|
||||
void playerColored(PlayerColor player);
|
||||
int width() const;
|
||||
int height() const;
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
||||
void playerColored(PlayerColor player) override;
|
||||
int width() const override;
|
||||
int height() const override;
|
||||
|
||||
friend class SDLImageLoader;
|
||||
};
|
||||
@ -144,10 +144,10 @@ public:
|
||||
CompImage(SDL_Surface * surf);
|
||||
~CompImage();
|
||||
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const;
|
||||
void playerColored(PlayerColor player);
|
||||
int width() const;
|
||||
int height() const;
|
||||
void draw(SDL_Surface *where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
||||
void playerColored(PlayerColor player) override;
|
||||
int width() const override;
|
||||
int height() const override;
|
||||
|
||||
friend class CompImageLoader;
|
||||
};
|
||||
|
@ -157,15 +157,15 @@ public:
|
||||
|
||||
// activate or deactivate object. Inactive object won't receive any input events (keyboard\mouse)
|
||||
// usually used automatically by parent
|
||||
void activate();
|
||||
void deactivate();
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
//called each frame to update screen
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
//called on complete redraw only
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
//request complete redraw of this object
|
||||
void redraw();
|
||||
void redraw() override;
|
||||
|
||||
enum EAlignment {TOPLEFT, CENTER, BOTTOMRIGHT};
|
||||
|
||||
@ -212,5 +212,5 @@ public:
|
||||
CKeyShortcut();
|
||||
CKeyShortcut(int key);
|
||||
CKeyShortcut(std::set<int> Keys);
|
||||
virtual void keyPressed(const SDL_KeyboardEvent & key); //call-in
|
||||
virtual void keyPressed(const SDL_KeyboardEvent & key) override; //call-in
|
||||
};
|
||||
|
@ -113,7 +113,7 @@ template<typename IntType>
|
||||
std::string makeNumberShort(IntType number, IntType maxLength = 3) //the output is a string containing at most 5 characters [4 if positive] (eg. intead 10000 it gives 10k)
|
||||
{
|
||||
IntType max = pow(10, maxLength);
|
||||
if (abs(number) < max)
|
||||
if (std::abs(number) < max)
|
||||
return boost::lexical_cast<std::string>(number);
|
||||
|
||||
std::string symbols = " kMGTPE";
|
||||
|
@ -312,7 +312,7 @@ class CMapHandler
|
||||
void drawHeroFlag(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, SDL_Rect * destRect, bool moving) const override;
|
||||
void drawObject(SDL_Surface * targetSurf, SDL_Surface * sourceSurf, SDL_Rect * sourceRect, bool moving) const override;
|
||||
void drawFrame(SDL_Surface * targetSurf) const override {}
|
||||
void drawOverlayEx(SDL_Surface * targetSurf);
|
||||
void drawOverlayEx(SDL_Surface * targetSurf) override;
|
||||
void init(const MapDrawingInfo * info) override;
|
||||
SDL_Rect clip(SDL_Surface * targetSurf) const override;
|
||||
|
||||
|
@ -37,9 +37,9 @@ protected:
|
||||
CListItem(CList * parent);
|
||||
~CListItem();
|
||||
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
void onSelect(bool on);
|
||||
|
||||
/// create object with selection rectangle
|
||||
@ -118,12 +118,12 @@ class CHeroList : public CList
|
||||
|
||||
CHeroItem(CHeroList *parent, const CGHeroInstance * hero);
|
||||
|
||||
CIntObject * genSelection();
|
||||
CIntObject * genSelection() override;
|
||||
void update();
|
||||
void select(bool on);
|
||||
void open();
|
||||
void showTooltip();
|
||||
std::string getHoverText();
|
||||
void select(bool on) override;
|
||||
void open() override;
|
||||
void showTooltip() override;
|
||||
std::string getHoverText() override;
|
||||
};
|
||||
|
||||
CIntObject * createHeroItem(size_t index);
|
||||
@ -152,12 +152,12 @@ class CTownList : public CList
|
||||
|
||||
CTownItem(CTownList *parent, const CGTownInstance * town);
|
||||
|
||||
CIntObject * genSelection();
|
||||
CIntObject * genSelection() override;
|
||||
void update();
|
||||
void select(bool on);
|
||||
void open();
|
||||
void showTooltip();
|
||||
std::string getHoverText();
|
||||
void select(bool on) override;
|
||||
void open() override;
|
||||
void showTooltip() override;
|
||||
std::string getHoverText() override;
|
||||
};
|
||||
|
||||
CIntObject * createTownItem(size_t index);
|
||||
@ -195,7 +195,7 @@ public:
|
||||
CMinimapInstance(CMinimap * parent, int level);
|
||||
~CMinimapInstance();
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
void tileToPixels (const int3 &tile, int &x, int &y,int toX = 0, int toY = 0);
|
||||
|
||||
void refreshTile(const int3 &pos);
|
||||
@ -213,10 +213,10 @@ protected:
|
||||
//to initialize colors
|
||||
std::map<int, std::pair<SDL_Color, SDL_Color> > loadColors(std::string from);
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover (bool on);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover (bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
|
||||
void moveAdvMapSelection();
|
||||
|
||||
@ -232,7 +232,7 @@ public:
|
||||
void setLevel(int level);
|
||||
void setAIRadar(bool on);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void hideTile(const int3 &pos); //puts FoW
|
||||
void showTile(const int3 &pos); //removes FoW
|
||||
@ -256,7 +256,7 @@ class CInfoBar : public CIntObject
|
||||
public:
|
||||
CVisibleInfo(Point position);
|
||||
|
||||
void show(SDL_Surface *to);
|
||||
void show(SDL_Surface *to) override;
|
||||
|
||||
//functions that must be called only once
|
||||
void loadHero(const CGHeroInstance * hero);
|
||||
@ -283,11 +283,11 @@ class CInfoBar : public CIntObject
|
||||
//removes all information about current state, deactivates timer (if any)
|
||||
void reset(EState newState);
|
||||
|
||||
void tick();
|
||||
void tick() override;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
|
||||
public:
|
||||
CInfoBar(const Rect & pos);
|
||||
@ -331,7 +331,7 @@ public:
|
||||
/// recolors all buttons to given player color
|
||||
void setPlayerColor(const PlayerColor & clr);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// specialized version of CAdvMapPanel that handles recolorable def-based pictures for world view info panel
|
||||
@ -351,7 +351,7 @@ public:
|
||||
void addChildIcon(std::pair<int, Point> data, const CDefHandler *def, int indexOffset);
|
||||
/// recreates all pictures from given def to recolor them according to current player color
|
||||
void recolorIcons(const PlayerColor &color, const CDefHandler *def, int indexOffset);
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
class CInGameConsole : public CIntObject
|
||||
@ -365,9 +365,9 @@ private:
|
||||
int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
|
||||
public:
|
||||
std::string enteredText;
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void print(const std::string &txt);
|
||||
void keyPressed (const SDL_KeyboardEvent & key); //call-in
|
||||
void keyPressed (const SDL_KeyboardEvent & key) override; //call-in
|
||||
|
||||
void textInputed(const SDL_TextInputEvent & event) override;
|
||||
void textEdited(const SDL_TextEditingEvent & event) override;
|
||||
|
@ -215,7 +215,7 @@ public:
|
||||
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void wheelScrolled(bool down, bool in);
|
||||
void wheelScrolled(bool down, bool in) override;
|
||||
};
|
||||
|
||||
/// A typical slider which can be orientated horizontally/vertically.
|
||||
@ -264,11 +264,11 @@ public:
|
||||
|
||||
void addCallback(std::function<void(int)> callback);
|
||||
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void wheelScrolled(bool down, bool in);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void showAll(SDL_Surface * to);
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void wheelScrolled(bool down, bool in) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
/// @param position coordinates of slider
|
||||
/// @param length length of slider ribbon, including left/right buttons
|
||||
|
@ -35,10 +35,10 @@ class CWindowWithArtifacts : public CArtifactHolder
|
||||
public:
|
||||
std::vector<CArtifactsOfHero *> artSets;
|
||||
|
||||
void artifactRemoved(const ArtifactLocation &artLoc);
|
||||
void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc);
|
||||
void artifactDisassembled(const ArtifactLocation &artLoc);
|
||||
void artifactAssembled(const ArtifactLocation &artLoc);
|
||||
void artifactRemoved(const ArtifactLocation &artLoc) override;
|
||||
void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override;
|
||||
void artifactDisassembled(const ArtifactLocation &artLoc) override;
|
||||
void artifactAssembled(const ArtifactLocation &artLoc) override;
|
||||
};
|
||||
|
||||
/// Artifacts can be placed there. Gets shown at the hero window
|
||||
@ -65,11 +65,11 @@ public:
|
||||
const CArtifactInstance * ourArt; // should be changed only with setArtifact()
|
||||
|
||||
CArtPlace(Point position, const CArtifactInstance * Art = nullptr); //c-tor
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void select ();
|
||||
void deselect ();
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
bool fitsHere (const CArtifactInstance * art) const; //returns true if given artifact can be placed here
|
||||
|
||||
void setMeAsDest(bool backpackAsVoid = true);
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
CComponent(Etype Type, int Subtype, int Val = 0, ESize imageSize=large);//c-tor
|
||||
CComponent(const Component &c, ESize imageSize=large); //c-tor
|
||||
|
||||
void clickRight(tribool down, bool previousState); //call-in
|
||||
void clickRight(tribool down, bool previousState) override; //call-in
|
||||
};
|
||||
|
||||
/// component that can be selected or deselected
|
||||
@ -68,10 +68,10 @@ public:
|
||||
bool selected; //if true, this component is selected
|
||||
std::function<void()> onSelect; //function called on selection change
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void select(bool on);
|
||||
|
||||
void clickLeft(tribool down, bool previousState); //call-in
|
||||
void clickLeft(tribool down, bool previousState) override; //call-in
|
||||
CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, std::function<void()> OnSelect = nullptr); //c-tor
|
||||
CSelectableComponent(const Component &c, std::function<void()> OnSelect = nullptr); //c-tor
|
||||
};
|
||||
|
@ -293,27 +293,30 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
|
||||
redraw();
|
||||
refr = true;
|
||||
}
|
||||
// we want to split
|
||||
else if( (owner->getSplittingMode() || LOCPLINT->shiftPressed())
|
||||
&& (!creature || creature == selection->creature) )
|
||||
refr = split();
|
||||
// swap
|
||||
else if(creature != selection->creature)
|
||||
{
|
||||
const CArmedInstance * selectedObj = owner->armedObjs[selection->upg];
|
||||
if (!creature && selectedObj->stacksCount() == 1)
|
||||
LOCPLINT->cb->splitStack(selectedObj, owner->armedObjs[upg], selection->ID, ID, selection->myStack->count - 1);
|
||||
else
|
||||
LOCPLINT->cb->swapCreatures(owner->armedObjs[upg], owner->armedObjs[selection->upg], ID, selection->ID);
|
||||
}
|
||||
// merge
|
||||
else
|
||||
{
|
||||
const CArmedInstance * selectedObj = owner->armedObjs[selection->upg];
|
||||
if (selectedObj->stacksCount() == 1)
|
||||
LOCPLINT->cb->splitStack(owner->armedObjs[upg], selectedObj, selection->ID, ID, 1);
|
||||
else
|
||||
LOCPLINT->cb->mergeStacks(owner->armedObjs[selection->upg], owner->armedObjs[upg], selection->ID, ID);
|
||||
bool lastHeroStackSelected = false;
|
||||
if(selectedObj->stacksCount() == 1
|
||||
&& owner->getSelection()->upg != upg
|
||||
&& dynamic_cast<const CGHeroInstance*>(selectedObj))
|
||||
{
|
||||
lastHeroStackSelected = true;
|
||||
}
|
||||
|
||||
if((owner->getSplittingMode() || LOCPLINT->shiftPressed()) // split window
|
||||
&& (!creature || creature == selection->creature))
|
||||
{
|
||||
refr = split();
|
||||
}
|
||||
else if(!creature && lastHeroStackSelected) // split all except last creature
|
||||
LOCPLINT->cb->splitStack(selectedObj, owner->armedObjs[upg], selection->ID, ID, selection->myStack->count - 1);
|
||||
else if(creature != selection->creature) // swap
|
||||
LOCPLINT->cb->swapCreatures(owner->armedObjs[upg], selectedObj, ID, selection->ID);
|
||||
else if(lastHeroStackSelected) // merge last stack to other hero stack
|
||||
refr = split();
|
||||
else // merge
|
||||
LOCPLINT->cb->mergeStacks(selectedObj, owner->armedObjs[upg], selection->ID, ID);
|
||||
}
|
||||
if(refr)
|
||||
{
|
||||
|
@ -47,12 +47,12 @@ class CGarrisonSlot : public CIntObject
|
||||
|
||||
void setHighlight(bool on);
|
||||
public:
|
||||
virtual void hover (bool on); //call-in
|
||||
virtual void hover (bool on) override; //call-in
|
||||
const CArmedInstance * getObj() const;
|
||||
bool our() const;
|
||||
bool ally() const;
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void update();
|
||||
CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg=EGarrisonType::UP, const CStackInstance * Creature=nullptr);
|
||||
|
||||
@ -132,7 +132,7 @@ class CWindowWithGarrison : public virtual CGarrisonHolder
|
||||
{
|
||||
public:
|
||||
CGarrisonInt *garr;
|
||||
virtual void updateGarrisons();
|
||||
virtual void updateGarrisons() override;
|
||||
};
|
||||
|
||||
/// Garrison window where you can take creatures out of the hero to place it on the garrison
|
||||
|
@ -49,8 +49,8 @@ public:
|
||||
|
||||
void scaleTo(Point size);
|
||||
void createSimpleRect(const Rect &r, bool screenFormat, ui32 color);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void convertToScreenBPP();
|
||||
void colorizeAndConvert(PlayerColor player);
|
||||
void colorize(PlayerColor player);
|
||||
@ -64,7 +64,7 @@ class CFilledTexture : CIntObject
|
||||
public:
|
||||
CFilledTexture(std::string imageName, Rect position);
|
||||
~CFilledTexture();
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
};
|
||||
|
||||
/// Class for displaying one image from animation
|
||||
@ -94,7 +94,7 @@ public:
|
||||
//makes image player-colored
|
||||
void playerColored(PlayerColor player);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// Base class for displaying animation, used as superclass for different animations
|
||||
@ -155,8 +155,8 @@ public:
|
||||
virtual void reset();
|
||||
|
||||
//show current frame and increase counter
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// Creature-dependend animations like attacking, moving,...
|
||||
@ -210,7 +210,7 @@ private:
|
||||
|
||||
public:
|
||||
//change anim to next if queue is not empty, call callback othervice
|
||||
void reset();
|
||||
void reset() override;
|
||||
|
||||
//add sequence to the end of queue
|
||||
void addLast(EAnimType newType);
|
||||
|
@ -28,7 +28,7 @@ class CHoverableArea: public virtual CIntObject
|
||||
public:
|
||||
std::string hoverText;
|
||||
|
||||
virtual void hover (bool on);
|
||||
virtual void hover (bool on) override;
|
||||
|
||||
CHoverableArea();
|
||||
virtual ~CHoverableArea();
|
||||
@ -45,8 +45,8 @@ public:
|
||||
virtual ~LRClickableAreaWText();
|
||||
void init();
|
||||
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
virtual void clickRight(tribool down, bool previousState);
|
||||
virtual void clickLeft(tribool down, bool previousState) override;
|
||||
virtual void clickRight(tribool down, bool previousState) override;
|
||||
};
|
||||
|
||||
/// base class for hero/town/garrison tooltips
|
||||
@ -88,7 +88,7 @@ private:
|
||||
CCreatureAnim *anim; //displayed animation
|
||||
CLabel * amount;
|
||||
|
||||
void show(SDL_Surface *to);
|
||||
void show(SDL_Surface *to) override;
|
||||
public:
|
||||
CCreaturePic(int x, int y, const CCreature *cre, bool Big=true, bool Animated=true); //c-tor
|
||||
|
||||
@ -100,8 +100,8 @@ class CMinorResDataBar : public CIntObject
|
||||
{
|
||||
public:
|
||||
SDL_Surface *bg; //background bitmap
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
CMinorResDataBar(); //c-tor
|
||||
~CMinorResDataBar(); //d-tor
|
||||
};
|
||||
@ -114,9 +114,9 @@ public:
|
||||
|
||||
CHeroArea(int x, int y, const CGHeroInstance * _hero);
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
};
|
||||
|
||||
/// Can interact on left and right mouse clicks
|
||||
@ -125,8 +125,8 @@ class LRClickableAreaWTextComp: public LRClickableAreaWText
|
||||
public:
|
||||
int baseType;
|
||||
int bonusValue, type;
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
virtual void clickRight(tribool down, bool previousState);
|
||||
virtual void clickLeft(tribool down, bool previousState) override;
|
||||
virtual void clickRight(tribool down, bool previousState) override;
|
||||
|
||||
LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1);
|
||||
CComponent * createComponent() const;
|
||||
@ -137,8 +137,8 @@ class LRClickableAreaOpenTown: public LRClickableAreaWTextComp
|
||||
{
|
||||
public:
|
||||
const CGTownInstance * town;
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
LRClickableAreaOpenTown();
|
||||
};
|
||||
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
|
||||
CLabel(int x=0, int y=0, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT,
|
||||
const SDL_Color &Color = Colors::WHITE, const std::string &Text = "");
|
||||
void showAll(SDL_Surface * to); //shows statusbar (with current text)
|
||||
void showAll(SDL_Surface * to) override; //shows statusbar (with current text)
|
||||
};
|
||||
|
||||
/// Small helper class to manage group of similar labels
|
||||
@ -85,8 +85,8 @@ public:
|
||||
|
||||
CMultiLineLabel(Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "");
|
||||
|
||||
void setText(const std::string &Txt);
|
||||
void showAll(SDL_Surface * to);
|
||||
void setText(const std::string &Txt) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void setVisibleSize(Rect visibleSize);
|
||||
// scrolls text visible in widget. Positive value will move text up
|
||||
@ -125,7 +125,7 @@ public:
|
||||
void clear();//clears statusbar and refreshes
|
||||
void setText(const std::string & Text) override; //prints text and refreshes statusbar
|
||||
|
||||
void show(SDL_Surface * to); //shows statusbar (with current text)
|
||||
void show(SDL_Surface * to) override; //shows statusbar (with current text)
|
||||
|
||||
CGStatusBar(CPicture *BG, EFonts Font = FONT_SMALL, EAlignment Align = CENTER, const SDL_Color &Color = Colors::WHITE); //given CPicture will be captured by created sbar and it's pos will be used as pos for sbar
|
||||
CGStatusBar(int x, int y, std::string name, int maxw=-1);
|
||||
|
@ -65,13 +65,13 @@ public:
|
||||
CTerrainRect();
|
||||
virtual ~CTerrainRect();
|
||||
CGPath * currentPath;
|
||||
void deactivate();
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void deactivate() override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void showAnim(SDL_Surface * to);
|
||||
void showPath(const SDL_Rect * extRect, SDL_Surface * to);
|
||||
int3 whichTileIsIt(const int & x, const int & y); //x,y are cursor position
|
||||
@ -92,14 +92,14 @@ public:
|
||||
std::vector<std::pair<int,int> > txtpos;
|
||||
std::string datetext;
|
||||
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
CResDataBar();
|
||||
CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist);
|
||||
~CResDataBar();
|
||||
|
||||
void draw(SDL_Surface * to);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// That's a huge class which handles general adventure map actions and
|
||||
@ -197,11 +197,11 @@ public:
|
||||
void fnextHero();
|
||||
void fendTurn();
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
void show(SDL_Surface * to); //redraws terrain
|
||||
void showAll(SDL_Surface * to); //shows and activates adv. map interface
|
||||
void show(SDL_Surface * to) override; //redraws terrain
|
||||
void showAll(SDL_Surface * to) override; //shows and activates adv. map interface
|
||||
|
||||
void select(const CArmedInstance *sel, bool centerView = true);
|
||||
void selectionChanged();
|
||||
@ -209,8 +209,8 @@ public:
|
||||
void centerOn(const CGObjectInstance *obj, bool fade = false);
|
||||
int3 verifyPos(int3 ver);
|
||||
void handleRightClick(std::string text, tribool down);
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
bool isActive();
|
||||
|
||||
bool isHeroSleeping(const CGHeroInstance *hero);
|
||||
|
@ -768,7 +768,7 @@ void CCastleBuildings::enterCastleGate()
|
||||
return;//only visiting hero can use castle gates
|
||||
}
|
||||
std::vector <int> availableTowns;
|
||||
std::vector <const CGTownInstance*> Towns = LOCPLINT->cb->getTownsInfo(false);
|
||||
std::vector <const CGTownInstance*> Towns = LOCPLINT->cb->getTownsInfo(true);
|
||||
for(auto & Town : Towns)
|
||||
{
|
||||
const CGTownInstance *t = Town;
|
||||
|
@ -51,12 +51,12 @@ public:
|
||||
CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str); //c-tor
|
||||
~CBuildingRect(); //d-tor
|
||||
bool operator<(const CBuildingRect & p2) const;
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void hover(bool on) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// Dwelling info box - right-click screen for dwellings
|
||||
@ -88,10 +88,10 @@ public:
|
||||
void setHighlight(bool on);
|
||||
void set(const CGHeroInstance *newHero);
|
||||
|
||||
void hover (bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void deactivate();
|
||||
void hover (bool on) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void deactivate() override;
|
||||
CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, HeroSlots * Owner); //c-tor
|
||||
~CHeroGSlot(); //d-tor
|
||||
};
|
||||
@ -150,8 +150,8 @@ public:
|
||||
void addBuilding(BuildingID building);
|
||||
void removeBuilding(BuildingID building);//FIXME: not tested!!!
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
/// Creature info window
|
||||
@ -172,9 +172,9 @@ public:
|
||||
CCreaInfo(Point position, const CGTownInstance *Town, int Level, bool compact=false, bool showAvailable=false);
|
||||
|
||||
void update();
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
};
|
||||
|
||||
/// Town hall and fort icons for town screen
|
||||
@ -187,8 +187,8 @@ public:
|
||||
//if (townHall) hall-capital else fort - castle
|
||||
CTownInfo(int posX, int posY, const CGTownInstance* town, bool townHall);
|
||||
|
||||
void hover(bool on);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
};
|
||||
|
||||
/// Class which manages the castle window
|
||||
@ -226,7 +226,7 @@ public:
|
||||
|
||||
void castleTeleport(int where);
|
||||
void townChange();
|
||||
void keyPressed(const SDL_KeyboardEvent & key);
|
||||
void keyPressed(const SDL_KeyboardEvent & key) override;
|
||||
void close();
|
||||
void addBuilding(BuildingID bid);
|
||||
void removeBuilding(BuildingID bid);
|
||||
@ -251,9 +251,9 @@ class CHallInterface : public CWindowObject
|
||||
|
||||
public:
|
||||
CBuildingBox(int x, int y, const CGTownInstance * Town, const CBuilding * Building);
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
};
|
||||
const CGTownInstance * town;
|
||||
|
||||
@ -294,7 +294,7 @@ class LabeledValue : public CIntObject
|
||||
public:
|
||||
LabeledValue(Rect size, std::string name, std::string descr, int min, int max);
|
||||
LabeledValue(Rect size, std::string name, std::string descr, int val);
|
||||
void hover(bool on);
|
||||
void hover(bool on) override;
|
||||
};
|
||||
|
||||
/// The fort screen where you can afford units
|
||||
@ -321,9 +321,9 @@ class CFortScreen : public CWindowObject
|
||||
RecruitArea(int posX, int posY, const CGTownInstance *town, int level);
|
||||
|
||||
void creaturesChanged();
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
};
|
||||
CLabel *title;
|
||||
std::vector<RecruitArea*> recAreas;
|
||||
@ -349,9 +349,9 @@ class CMageGuildScreen : public CWindowObject
|
||||
|
||||
public:
|
||||
Scroll(Point position, const CSpell *Spell);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
};
|
||||
CPicture *window;
|
||||
CButton *exit;
|
||||
|
@ -35,7 +35,7 @@ class CHeroSwitcher : public CIntObject
|
||||
const CGHeroInstance * hero;
|
||||
CAnimImage *image;
|
||||
public:
|
||||
virtual void clickLeft(tribool down, bool previousState);
|
||||
virtual void clickLeft(tribool down, bool previousState) override;
|
||||
|
||||
CHeroSwitcher(Point pos, const CGHeroInstance * hero);
|
||||
};
|
||||
@ -85,7 +85,7 @@ public:
|
||||
CHeroWindow(const CGHeroInstance *hero); //c-tor
|
||||
|
||||
void update(const CGHeroInstance * hero, bool redrawNeeded = false); //sets main displayed hero
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void dismissCurrent(); //dissmissed currently displayed hero (curHero)
|
||||
void questlog(); //show quest log in hero window
|
||||
|
@ -74,8 +74,8 @@ public:
|
||||
InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data);
|
||||
~InfoBox();
|
||||
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
|
||||
//Update object if data may have changed
|
||||
//void update();
|
||||
@ -121,13 +121,13 @@ protected:
|
||||
public:
|
||||
InfoBoxAbstractHeroData(InfoType Type);
|
||||
|
||||
std::string getValueText();
|
||||
std::string getNameText();
|
||||
std::string getImageName(InfoBox::InfoSize size);
|
||||
std::string getHoverText();
|
||||
size_t getImageIndex();
|
||||
std::string getValueText() override;
|
||||
std::string getNameText() override;
|
||||
std::string getImageName(InfoBox::InfoSize size) override;
|
||||
std::string getHoverText() override;
|
||||
size_t getImageIndex() override;
|
||||
|
||||
bool prepareMessage(std::string &text, CComponent **comp);
|
||||
bool prepareMessage(std::string &text, CComponent **comp) override;
|
||||
};
|
||||
|
||||
class InfoBoxHeroData : public InfoBoxAbstractHeroData
|
||||
@ -135,17 +135,17 @@ class InfoBoxHeroData : public InfoBoxAbstractHeroData
|
||||
const CGHeroInstance * hero;
|
||||
int index;//index of data in hero (0-7 for sec. skill, 0-3 for pr. skill)
|
||||
|
||||
int getSubID();
|
||||
si64 getValue();
|
||||
int getSubID() override;
|
||||
si64 getValue() override;
|
||||
|
||||
public:
|
||||
InfoBoxHeroData(InfoType Type, const CGHeroInstance *Hero, int Index=0);
|
||||
|
||||
//To get a bit different texts for hero window
|
||||
std::string getHoverText();
|
||||
std::string getValueText();
|
||||
std::string getHoverText() override;
|
||||
std::string getValueText() override;
|
||||
|
||||
bool prepareMessage(std::string &text, CComponent **comp);
|
||||
bool prepareMessage(std::string &text, CComponent **comp) override;
|
||||
};
|
||||
|
||||
class InfoBoxCustomHeroData : public InfoBoxAbstractHeroData
|
||||
@ -153,8 +153,8 @@ class InfoBoxCustomHeroData : public InfoBoxAbstractHeroData
|
||||
int subID;//subID of data (0=attack...)
|
||||
si64 value;//actual value of data, 64-bit to fit experience and negative values
|
||||
|
||||
int getSubID();
|
||||
si64 getValue();
|
||||
int getSubID() override;
|
||||
si64 getValue() override;
|
||||
|
||||
public:
|
||||
InfoBoxCustomHeroData(InfoType Type, int subID, si64 value);
|
||||
@ -171,13 +171,13 @@ public:
|
||||
|
||||
InfoBoxCustom(std::string ValueText, std::string NameText, std::string ImageName, size_t ImageIndex, std::string HoverText="");
|
||||
|
||||
std::string getValueText();
|
||||
std::string getNameText();
|
||||
std::string getImageName(InfoBox::InfoSize size);
|
||||
std::string getHoverText();
|
||||
size_t getImageIndex();
|
||||
std::string getValueText() override;
|
||||
std::string getNameText() override;
|
||||
std::string getImageName(InfoBox::InfoSize size) override;
|
||||
std::string getHoverText() override;
|
||||
size_t getImageIndex() override;
|
||||
|
||||
bool prepareMessage(std::string &text, CComponent **comp);
|
||||
bool prepareMessage(std::string &text, CComponent **comp) override;
|
||||
};
|
||||
|
||||
//TODO!!!
|
||||
@ -191,11 +191,11 @@ public:
|
||||
InfoBoxTownData(InfoType Type, const CGTownInstance * Town, int Index);
|
||||
InfoBoxTownData(InfoType Type, int SubID, int Value);
|
||||
|
||||
std::string getValueText();
|
||||
std::string getNameText();
|
||||
std::string getImageName(InfoBox::InfoSize size);
|
||||
std::string getHoverText();
|
||||
size_t getImageIndex();
|
||||
std::string getValueText() override;
|
||||
std::string getNameText() override;
|
||||
std::string getImageName(InfoBox::InfoSize size) override;
|
||||
std::string getHoverText() override;
|
||||
size_t getImageIndex() override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -250,11 +250,11 @@ public:
|
||||
CKingdomInterface();
|
||||
|
||||
void townChanged(const CGTownInstance *town);
|
||||
void updateGarrisons();
|
||||
void artifactRemoved(const ArtifactLocation &artLoc);
|
||||
void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc);
|
||||
void artifactDisassembled(const ArtifactLocation &artLoc);
|
||||
void artifactAssembled(const ArtifactLocation &artLoc);
|
||||
void updateGarrisons() override;
|
||||
void artifactRemoved(const ArtifactLocation &artLoc) override;
|
||||
void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override;
|
||||
void artifactDisassembled(const ArtifactLocation &artLoc) override;
|
||||
void artifactAssembled(const ArtifactLocation &artLoc) override;
|
||||
};
|
||||
|
||||
/// List item with town
|
||||
@ -277,7 +277,7 @@ public:
|
||||
|
||||
CTownItem(const CGTownInstance* town);
|
||||
|
||||
void updateGarrisons();
|
||||
void updateGarrisons() override;
|
||||
void update();
|
||||
};
|
||||
|
||||
@ -325,7 +325,7 @@ private:
|
||||
public:
|
||||
CKingdHeroList(size_t maxSize);
|
||||
|
||||
void updateGarrisons();
|
||||
void updateGarrisons() override;
|
||||
};
|
||||
|
||||
/// Tab with all town-specific data
|
||||
@ -344,5 +344,5 @@ public:
|
||||
CKingdTownList(size_t maxSize);
|
||||
|
||||
void townChanged(const CGTownInstance *town);
|
||||
void updateGarrisons();
|
||||
void updateGarrisons() override;
|
||||
};
|
||||
|
@ -41,8 +41,8 @@ public:
|
||||
|
||||
CQuestLabel (Rect position, EFonts Font = FONT_SMALL, EAlignment Align = TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text = "")
|
||||
: CMultiLineLabel (position, FONT_SMALL, TOPLEFT, Colors::WHITE, Text){};
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
class CQuestIcon : public CAnimImage
|
||||
@ -52,17 +52,17 @@ public:
|
||||
|
||||
CQuestIcon (const std::string &defname, int index, int x=0, int y=0);
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
class CQuestMinimap : public CMinimap
|
||||
{
|
||||
std::vector <shared_ptr<CQuestIcon>> icons;
|
||||
|
||||
void clickLeft(tribool down, bool previousState){}; //minimap ignores clicking on its surface
|
||||
void clickLeft(tribool down, bool previousState) override{}; //minimap ignores clicking on its surface
|
||||
void iconClicked();
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent){};
|
||||
void mouseMoved (const SDL_MouseMotionEvent & sEvent) override{};
|
||||
|
||||
public:
|
||||
|
||||
@ -73,7 +73,7 @@ public:
|
||||
void update();
|
||||
void addQuestMarks (const QuestInfo * q);
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
class CQuestLog : public CWindowObject
|
||||
@ -106,5 +106,5 @@ public:
|
||||
void recreateLabelList();
|
||||
void recreateQuestList (int pos);
|
||||
void toggleComplete(bool on);
|
||||
void showAll (SDL_Surface * to);
|
||||
void showAll (SDL_Surface * to) override;
|
||||
};
|
||||
|
@ -50,10 +50,10 @@ public:
|
||||
|
||||
void showAllAt(const Point &dstPos, const std::string &customSub, SDL_Surface * to);
|
||||
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover (bool on);
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover (bool on) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
std::string getName(int number = -1) const;
|
||||
CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial);
|
||||
};
|
||||
@ -74,7 +74,7 @@ public:
|
||||
|
||||
CTradeWindow(std::string bgName, const IMarket *Market, const CGHeroInstance *Hero, EMarketMode::EMarketMode Mode); //c
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void initSubs(bool Left);
|
||||
void initTypes();
|
||||
@ -109,19 +109,19 @@ public:
|
||||
void setMax();
|
||||
void sliderMoved(int to);
|
||||
void makeDeal();
|
||||
void selectionChanged(bool side); //true == left
|
||||
void selectionChanged(bool side) override; //true == left
|
||||
CMarketplaceWindow(const IMarket *Market, const CGHeroInstance *Hero = nullptr, EMarketMode::EMarketMode Mode = EMarketMode::RESOURCE_RESOURCE); //c-tor
|
||||
~CMarketplaceWindow(); //d-tor
|
||||
|
||||
Point selectionOffset(bool Left) const;
|
||||
std::string selectionSubtitle(bool Left) const;
|
||||
Point selectionOffset(bool Left) const override;
|
||||
std::string selectionSubtitle(bool Left) const override;
|
||||
|
||||
|
||||
void garrisonChanged(); //removes creatures with count 0 from the list (apparently whole stack has been sold)
|
||||
void artifactsChanged(bool left);
|
||||
void garrisonChanged() override; //removes creatures with count 0 from the list (apparently whole stack has been sold)
|
||||
void artifactsChanged(bool left) override;
|
||||
void resourceChanged(int type, int val);
|
||||
|
||||
void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const;
|
||||
void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const override;
|
||||
void updateTraderText();
|
||||
};
|
||||
|
||||
@ -141,24 +141,24 @@ public:
|
||||
CLabel *expToLevel, *expOnAltar;
|
||||
|
||||
|
||||
void selectionChanged(bool side); //true == left
|
||||
void selectionChanged(bool side) override; //true == left
|
||||
void SacrificeAll();
|
||||
void SacrificeBackpack();
|
||||
|
||||
void putOnAltar(int backpackIndex);
|
||||
bool putOnAltar(CTradeableItem* altarSlot, const CArtifactInstance *art);
|
||||
void makeDeal();
|
||||
void showAll(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
|
||||
void blockTrade();
|
||||
void sliderMoved(int to);
|
||||
void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const;
|
||||
void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const override;
|
||||
void mimicCres();
|
||||
|
||||
Point selectionOffset(bool Left) const;
|
||||
std::string selectionSubtitle(bool Left) const;
|
||||
void garrisonChanged();
|
||||
void artifactsChanged(bool left);
|
||||
Point selectionOffset(bool Left) const override;
|
||||
std::string selectionSubtitle(bool Left) const override;
|
||||
void garrisonChanged() override;
|
||||
void artifactsChanged(bool left) override;
|
||||
void calcTotalExp();
|
||||
void setExpToLevel();
|
||||
void updateRight(CTradeableItem *toUpdate);
|
||||
|
@ -39,9 +39,9 @@ protected:
|
||||
//Simple function with call to GH.popInt
|
||||
void close();
|
||||
//Used only if RCLICK_POPUP was set
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
//To display border
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
//change or set background image
|
||||
void setBackground(std::string filename);
|
||||
void updateShadow();
|
||||
|
@ -43,9 +43,9 @@ class CRecruitmentWindow : public CWindowObject
|
||||
CCreaturePic *pic; //creature's animation
|
||||
bool selected;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void showAll(SDL_Surface *to);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void showAll(SDL_Surface *to) override;
|
||||
public:
|
||||
const CCreature * creature;
|
||||
si32 amount;
|
||||
@ -88,7 +88,7 @@ class CRecruitmentWindow : public CWindowObject
|
||||
void buy();
|
||||
void sliderMoved(int to);
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
void showAll(SDL_Surface *to) override;
|
||||
public:
|
||||
const CGDwelling * const dwelling;
|
||||
CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const std::function<void(CreatureID,int)> & Recruit, int y_offset = 0); //creatures - pairs<creature_ID,amount> //c-tor
|
||||
@ -153,7 +153,7 @@ class CObjectListWindow : public CWindowObject
|
||||
CItem(CObjectListWindow *parent, size_t id, std::string text);
|
||||
|
||||
void select(bool on);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
};
|
||||
|
||||
std::function<void(int)> onSelect;//called when OK button is pressed, returns id of selected item.
|
||||
@ -180,7 +180,7 @@ public:
|
||||
CIntObject *genItem(size_t index);
|
||||
void elementSelected();//call callback and close this window
|
||||
void changeSelection(size_t which);
|
||||
void keyPressed (const SDL_KeyboardEvent & key);
|
||||
void keyPressed (const SDL_KeyboardEvent & key) override;
|
||||
};
|
||||
|
||||
class CSystemOptionsWindow : public CWindowObject
|
||||
@ -232,9 +232,9 @@ public:
|
||||
std::string description; // "XXX is a level Y ZZZ with N artifacts"
|
||||
const CGHeroInstance *h;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover (bool on);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover (bool on) override;
|
||||
HeroPortrait(int &sel, int id, int x, int y, const CGHeroInstance *H);
|
||||
|
||||
private:
|
||||
@ -255,7 +255,7 @@ public:
|
||||
|
||||
void recruitb();
|
||||
void thievesguildb();
|
||||
void show(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
};
|
||||
|
||||
class CExchangeWindow : public CWindowObject, public CWindowWithGarrison, public CWindowWithArtifacts
|
||||
@ -319,8 +319,8 @@ private:
|
||||
ui8 currentAlpha;
|
||||
|
||||
public:
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void show(SDL_Surface * to) override;
|
||||
|
||||
CPuzzleWindow(const int3 &grailPos, double discoveredRatio);
|
||||
};
|
||||
@ -339,7 +339,7 @@ public:
|
||||
CAnimImage *icon;
|
||||
|
||||
void move();
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void update();
|
||||
CItem(CTransformerWindow * parent, int size, int id);
|
||||
};
|
||||
@ -353,7 +353,7 @@ public:
|
||||
CGStatusBar *bar;
|
||||
void makeDeal();
|
||||
void addAll();
|
||||
void updateGarrisons();
|
||||
void updateGarrisons() override;
|
||||
CTransformerWindow(const CGHeroInstance * _hero, const CGTownInstance * _town); //c-tor
|
||||
};
|
||||
|
||||
@ -365,10 +365,10 @@ class CUniversityWindow : public CWindowObject
|
||||
int ID;//id of selected skill
|
||||
CUniversityWindow * parent;
|
||||
|
||||
void showAll(SDL_Surface * to);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void hover(bool on);
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void clickLeft(tribool down, bool previousState) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void hover(bool on) override;
|
||||
int state();//0=can't learn, 1=learned, 2=can learn
|
||||
CItem(CUniversityWindow * _parent, int _ID, int X, int Y);
|
||||
};
|
||||
@ -419,12 +419,12 @@ public:
|
||||
|
||||
CHillFortWindow(const CGHeroInstance *visitor, const CGObjectInstance *object); //c-tor
|
||||
|
||||
void showAll (SDL_Surface *to);
|
||||
void showAll (SDL_Surface *to) override;
|
||||
std::string getDefForSlot(SlotID slot);//return def name for this slot
|
||||
std::string getTextForSlot(SlotID slot);//return hover text for this slot
|
||||
void makeDeal(SlotID slot);//-1 for upgrading all creatures
|
||||
int getState(SlotID slot); //-1 = no creature 0=can't upgrade, 1=upgraded, 2=can upgrade
|
||||
void updateGarrisons();//update buttons after garrison changes
|
||||
void updateGarrisons() override;//update buttons after garrison changes
|
||||
};
|
||||
|
||||
class CThievesGuildWindow : public CWindowObject
|
||||
|
@ -31,7 +31,7 @@ class CSimpleWindow : public CIntObject
|
||||
{
|
||||
public:
|
||||
SDL_Surface * bitmap; //background
|
||||
virtual void show(SDL_Surface * to);
|
||||
virtual void show(SDL_Surface * to) override;
|
||||
CSimpleWindow():bitmap(nullptr){}; //c-tor
|
||||
virtual ~CSimpleWindow(); //d-tor
|
||||
};
|
||||
@ -53,8 +53,8 @@ public:
|
||||
void setDelComps(bool DelComps);
|
||||
virtual void close();
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
void sliderMoved(int to);
|
||||
|
||||
CInfoWindow(std::string Text, PlayerColor player, const TCompsInfo &comps = TCompsInfo(), const TButtonsInfo &Buttons = TButtonsInfo(), bool delComps = true); //c-tor
|
||||
@ -76,7 +76,7 @@ class CRClickPopup : public CIntObject
|
||||
{
|
||||
public:
|
||||
virtual void close();
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
|
||||
CRClickPopup();
|
||||
virtual ~CRClickPopup(); //d-tor
|
||||
@ -94,8 +94,8 @@ public:
|
||||
IShowActivatable *inner;
|
||||
bool delInner;
|
||||
|
||||
void show(SDL_Surface * to);
|
||||
void showAll(SDL_Surface * to);
|
||||
void show(SDL_Surface * to) override;
|
||||
void showAll(SDL_Surface * to) override;
|
||||
CRClickPopupInt(IShowActivatable *our, bool deleteInt); //c-tor
|
||||
virtual ~CRClickPopupInt(); //d-tor
|
||||
};
|
||||
@ -105,8 +105,8 @@ class CInfoPopup : public CRClickPopup
|
||||
public:
|
||||
bool free; //TODO: comment me
|
||||
SDL_Surface * bitmap; //popup background
|
||||
void close();
|
||||
void show(SDL_Surface * to);
|
||||
void close() override;
|
||||
void show(SDL_Surface * to) override;
|
||||
CInfoPopup(SDL_Surface * Bitmap, int x, int y, bool Free=false); //c-tor
|
||||
CInfoPopup(SDL_Surface * Bitmap, const Point &p, EAlignment alignment, bool Free=false); //c-tor
|
||||
CInfoPopup(SDL_Surface * Bitmap = nullptr, bool Free = false); //default c-tor
|
||||
|
@ -1313,7 +1313,8 @@
|
||||
"subtype" : 35,
|
||||
"type" : "SPELL_IMMUNITY",
|
||||
"val" : 0,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"addInfo" : 1
|
||||
}
|
||||
],
|
||||
"index" : 92,
|
||||
@ -1324,10 +1325,17 @@
|
||||
"bonuses" : [
|
||||
{
|
||||
"type" : "NEGATE_ALL_NATURAL_IMMUNITIES",
|
||||
"subtype" : 0,
|
||||
"val" : 0,
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"propagator": "BATTLE_WIDE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type" : "NEGATE_ALL_NATURAL_IMMUNITIES",
|
||||
"subtype" : 1,
|
||||
"val" : 0,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
}
|
||||
],
|
||||
"index" : 93,
|
||||
"type" : ["HERO"]
|
||||
@ -1812,7 +1820,8 @@
|
||||
"subtype" : "spell.armageddon",
|
||||
"type" : "SPELL_IMMUNITY",
|
||||
"val" : 0,
|
||||
"valueType" : "BASE_NUMBER"
|
||||
"valueType" : "BASE_NUMBER",
|
||||
"addInfo" : 1
|
||||
},
|
||||
{
|
||||
"subtype" : "primSkill.attack",
|
||||
|
@ -368,6 +368,11 @@
|
||||
"icon": "zvs/Lib1.res/E_OBST"
|
||||
}
|
||||
},
|
||||
|
||||
"NO_TERRAIN_PENALTY":
|
||||
{
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"NON_LIVING":
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
// macros:
|
||||
// ${val} - value of bonuses; Selector: type,subtype
|
||||
// ${subtype.creature} - creature name
|
||||
// ${subtype.creature} - creature name
|
||||
// ${subtype.spell} - spell name
|
||||
// ${MR} - magic resistance of bearer
|
||||
|
||||
@ -11,19 +11,19 @@
|
||||
"name": "Double Strike",
|
||||
"description": "Attacks twice"
|
||||
},
|
||||
|
||||
|
||||
"ADDITIONAL_RETALIATION":
|
||||
{
|
||||
"name": "Additional retaliations",
|
||||
"description": "May Retaliate ${val} extra times"
|
||||
},
|
||||
|
||||
|
||||
"AIR_IMMUNITY":
|
||||
{
|
||||
"name": "Immune to Air",
|
||||
"description": ""
|
||||
"name": "Air immunity",
|
||||
"description": "Immune to all Air school spells"
|
||||
},
|
||||
|
||||
|
||||
"ATTACKS_ALL_ADJACENT":
|
||||
{
|
||||
"name": "Attack all around",
|
||||
@ -35,19 +35,19 @@
|
||||
"name": "No retaliation",
|
||||
"description": "Enemy cannot Retaliate"
|
||||
},
|
||||
|
||||
|
||||
"CATAPULT":
|
||||
{
|
||||
"name": "Catapult",
|
||||
"description": "Attacks siege walls"
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
"CHANGES_SPELL_COST_FOR_ALLY":
|
||||
{
|
||||
"name": "Reduce Casting Cost (${val})",
|
||||
"description": "Reduce Casting Cost for hero"
|
||||
},
|
||||
|
||||
|
||||
"CHANGES_SPELL_COST_FOR_ENEMY":
|
||||
{
|
||||
"name": "Magic Damper (${val})",
|
||||
@ -59,31 +59,31 @@
|
||||
"name": "Immune to Charge",
|
||||
"description": "Immune to Champion charge"
|
||||
},
|
||||
|
||||
|
||||
"DAEMON_SUMMONING":
|
||||
{
|
||||
"name": "Summoner (${subtype.creature})",
|
||||
"description": "Can rise creatures from corpses"
|
||||
"description": "Can rise creatures from corpses"
|
||||
},
|
||||
|
||||
"DARKNESS":
|
||||
|
||||
"DARKNESS":
|
||||
{
|
||||
"name": "Darness cover",
|
||||
"description": "Adds ${val} darkness radius"
|
||||
},
|
||||
|
||||
|
||||
"DEATH_STARE":
|
||||
{
|
||||
"name": "Death Stare (${val}%)",
|
||||
"description": "${val}% chance to kill single creature"
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
"DEFENSIVE_STANCE":
|
||||
{
|
||||
"name": "Defense Bonus",
|
||||
"description": "+${val} Defense when defending"
|
||||
},
|
||||
|
||||
|
||||
"DOUBLE_DAMAGE_CHANCE":
|
||||
{
|
||||
"name": "Death Blow",
|
||||
@ -95,7 +95,7 @@
|
||||
"name": "Dragon",
|
||||
"description": "Creature has a Dragon Nature"
|
||||
},
|
||||
|
||||
|
||||
"DIRECT_DAMAGE_IMMUNITY":
|
||||
{
|
||||
"name": "Direct Damage Immunity",
|
||||
@ -104,62 +104,63 @@
|
||||
|
||||
"EARTH_IMMUNITY":
|
||||
{
|
||||
"name": "Immune to Earth",
|
||||
"description": ""
|
||||
"name": "Earth immunity",
|
||||
"description": "Immune to all Earth school spells"
|
||||
},
|
||||
|
||||
|
||||
"ENCHANTER":
|
||||
{
|
||||
"name": "Enchanter",
|
||||
"description": "Can cast mass ${subtype.spell} every turn"
|
||||
},
|
||||
|
||||
|
||||
"ENCHANTED":
|
||||
{
|
||||
"name": "Enchanted",
|
||||
"description": "Affected by permanent ${subtype.spell}"
|
||||
},
|
||||
},
|
||||
|
||||
"ENEMY_DEFENCE_REDUCTION":
|
||||
{
|
||||
"name": "Reduce Enemy Defense (${val}%)",
|
||||
"description": "Reduces Defense for one attack"
|
||||
},
|
||||
|
||||
|
||||
"GENERAL_DAMAGE_REDUCTION":
|
||||
{
|
||||
"name": "Reduce Damage (${val}%)",
|
||||
"description": "Reduces physical damage"
|
||||
},
|
||||
|
||||
|
||||
"FIRE_IMMUNITY":
|
||||
{
|
||||
"name": "Immune to Fire",
|
||||
"description": ""
|
||||
"name": "Fire immunity",
|
||||
"description": "Immune to all Fire school spells"
|
||||
},
|
||||
|
||||
"FIRE_SHIELD":
|
||||
{
|
||||
"name": "Fire Shield (${val}%)",
|
||||
"description": "Reflects melee damage"
|
||||
"description": "Reflects melee damage"
|
||||
},
|
||||
|
||||
"FEAR":
|
||||
{
|
||||
"name": "Fear",
|
||||
"description": "Causes Fear on an enemy stack"
|
||||
},
|
||||
|
||||
|
||||
"FEARLESS":
|
||||
{
|
||||
"name": "Fearless",
|
||||
"description": "Immune to Fear ability"
|
||||
},
|
||||
|
||||
|
||||
"FLYING":
|
||||
{
|
||||
"name": "Fly",
|
||||
"description": "Can Fly (ignores obstacles)"
|
||||
},
|
||||
},
|
||||
|
||||
"FREE_SHOOTING":
|
||||
{
|
||||
@ -172,51 +173,55 @@
|
||||
"name": "Regeneration",
|
||||
"description": "May Regenerate full Health"
|
||||
},
|
||||
|
||||
|
||||
"HATE":
|
||||
{
|
||||
"name": "Hates ${subtype.creature}",
|
||||
"description": "Does ${val}% more damage"
|
||||
},
|
||||
|
||||
|
||||
"HEALER":
|
||||
{
|
||||
"name": "Healer",
|
||||
"description": "Heals allied units"
|
||||
},
|
||||
|
||||
|
||||
"HP_REGENERATION":
|
||||
{
|
||||
"name": "Regeneration",
|
||||
"description": "Heals ${val} hit points every round"
|
||||
},
|
||||
|
||||
"JOUSTING":
|
||||
{
|
||||
"name": "Champion Charge",
|
||||
"description": "+5% damage per hex travelled"
|
||||
},
|
||||
|
||||
|
||||
"KING1":
|
||||
{
|
||||
"name": "King1"
|
||||
"name": "King1",
|
||||
"description": "Vulnerable to basic SLAYER"
|
||||
},
|
||||
|
||||
|
||||
"KING2":
|
||||
{
|
||||
"name": "King2"
|
||||
"name": "King2",
|
||||
"description": "Vulnerable to adv. SLAYER"
|
||||
},
|
||||
|
||||
|
||||
"KING3":
|
||||
{
|
||||
"name": "King3"
|
||||
"name": "King3",
|
||||
"description":"Vulnerable to expert SLAYER"
|
||||
},
|
||||
|
||||
|
||||
"LEVEL_SPELL_IMMUNITY":
|
||||
{
|
||||
"name": "Spell immunity 1-${val}",
|
||||
"description": "Immune to spells levels 1-${val}"
|
||||
},
|
||||
|
||||
|
||||
"LIFE_DRAIN":
|
||||
{
|
||||
"name": "Drain life (${val}%)",
|
||||
@ -228,6 +233,7 @@
|
||||
"name": "Magic Channel ${val}%",
|
||||
"description": "Gives mana spent by enemy"
|
||||
},
|
||||
|
||||
"MANA_DRAIN":
|
||||
{
|
||||
"name": "Mana Drain",
|
||||
@ -257,19 +263,19 @@
|
||||
"name": "No distance penalty",
|
||||
"description": "Full damage from any distance"
|
||||
},
|
||||
|
||||
"NO_MELEE_PENALTY":
|
||||
{
|
||||
"name": "No melee penalty",
|
||||
"description": "Creature has no Melee Penalty"
|
||||
},
|
||||
|
||||
|
||||
|
||||
"NO_MORALE":
|
||||
{
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
|
||||
"NO_WALL_PENALTY":
|
||||
{
|
||||
"name": "No wall penalty",
|
||||
@ -280,7 +286,7 @@
|
||||
{
|
||||
"name": "Non living",
|
||||
"description": "Immunity to many effects"
|
||||
},
|
||||
},
|
||||
|
||||
"RANDOM_SPELLCASTER":
|
||||
{
|
||||
@ -298,48 +304,49 @@
|
||||
"name": "Rebirth (${val}%)",
|
||||
"description": "${val}% of stack will rise after death"
|
||||
},
|
||||
|
||||
|
||||
"RETURN_AFTER_STRIKE":
|
||||
{
|
||||
"name": "Attack and Return",
|
||||
"description": "Returns after melee attack"
|
||||
},
|
||||
|
||||
|
||||
"SELF_LUCK":
|
||||
{
|
||||
"name": "Positive luck",
|
||||
"description": "Always has Positive Luck"
|
||||
},
|
||||
|
||||
|
||||
"SELF_MORALE":
|
||||
{
|
||||
"name": "Positive morale",
|
||||
"description": "Always has Positive Morale"
|
||||
},
|
||||
|
||||
|
||||
"SHOOTER":
|
||||
{
|
||||
"name": "Ranged",
|
||||
"description": "Creature can shoot"
|
||||
},
|
||||
},
|
||||
|
||||
"SPELLCASTER":
|
||||
{
|
||||
"name": "Spellcaster",
|
||||
"description": "Can cast ${subtype.spell}"
|
||||
},
|
||||
|
||||
|
||||
"SPELL_AFTER_ATTACK":
|
||||
{
|
||||
"name": "Caster - ${subtype.spell}",
|
||||
"description": "${val}% chance to cast after attack"
|
||||
"name": "After attack cast",
|
||||
"description": "${val}% to cast ${subtype.spell} after attack"
|
||||
},
|
||||
|
||||
|
||||
"SPELL_BEFORE_ATTACK":
|
||||
{
|
||||
"name": "Caster - ${subtype.spell}",
|
||||
"description": "${val}% chance to cast before attack"
|
||||
"name": "Before attack cast",
|
||||
"description": "${val}% to cast ${subtype.spell} before attack"
|
||||
},
|
||||
|
||||
|
||||
"SPELL_DAMAGE_REDUCTION":
|
||||
{
|
||||
"name": "Spell Resistance",
|
||||
@ -348,17 +355,16 @@
|
||||
|
||||
"SPELL_IMMUNITY":
|
||||
{
|
||||
"name": "Immune to ${subtype.spell}",
|
||||
"description": ""
|
||||
"name": "Spell immunity",
|
||||
"description": "Immune to ${subtype.spell}"
|
||||
},
|
||||
|
||||
|
||||
"SPELL_LIKE_ATTACK":
|
||||
{
|
||||
"name": "Spell-like attack",
|
||||
"description": "Attacks with ${subtype.spell}"
|
||||
},
|
||||
|
||||
|
||||
"SPELL_RESISTANCE_AURA":
|
||||
{
|
||||
"name": "Aura of Resistance",
|
||||
@ -371,8 +377,6 @@
|
||||
"description": "Breath Attack (2-hex range)"
|
||||
},
|
||||
|
||||
|
||||
|
||||
"THREE_HEADED_ATTACK":
|
||||
{
|
||||
"name": "Three-headed attack",
|
||||
@ -384,14 +388,16 @@
|
||||
"name": "Undead",
|
||||
"description": "Creature is Undead"
|
||||
},
|
||||
|
||||
"UNLIMITED_RETALIATIONS":
|
||||
{
|
||||
"name": "Unlimited retaliations",
|
||||
"description": "Retaliate any number of attacks"
|
||||
},
|
||||
|
||||
"WATER_IMMUNITY":
|
||||
{
|
||||
"name": "Immune to Water",
|
||||
"description": ""
|
||||
"name": "Water immunity",
|
||||
"description": "Immune to all Water school spells"
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,14 @@
|
||||
"blindImmunity" :
|
||||
{
|
||||
"type" : "SPELL_IMMUNITY",
|
||||
"subtype" : "spell.blind"
|
||||
"subtype" : "spell.blind",
|
||||
"addInfo" : 1
|
||||
},
|
||||
"petrifyImmunity" :
|
||||
{
|
||||
"type" : "SPELL_IMMUNITY",
|
||||
"subtype" : "spell.stoneGaze"
|
||||
"subtype" : "spell.stoneGaze",
|
||||
"addInfo" : 1
|
||||
}
|
||||
},
|
||||
"upgrades": ["infernalTroglodyte"],
|
||||
@ -42,12 +44,14 @@
|
||||
"blindImmunity" :
|
||||
{
|
||||
"type" : "SPELL_IMMUNITY",
|
||||
"subtype" : "spell.blind"
|
||||
"subtype" : "spell.blind",
|
||||
"addInfo" : 1
|
||||
},
|
||||
"petrifyImmunity" :
|
||||
{
|
||||
"type" : "SPELL_IMMUNITY",
|
||||
"subtype" : "spell.stoneGaze"
|
||||
"subtype" : "spell.stoneGaze",
|
||||
"addInfo" : 1
|
||||
}
|
||||
},
|
||||
"graphics" :
|
||||
|
@ -475,6 +475,15 @@
|
||||
"index": 142,
|
||||
"level": 3,
|
||||
"faction": "neutral",
|
||||
"abilities":
|
||||
{
|
||||
"sandWalker" :
|
||||
{
|
||||
"type" : "NO_TERRAIN_PENALTY",
|
||||
"subtype" : 1,
|
||||
"propagator" : "HERO"
|
||||
}
|
||||
},
|
||||
"doubleWide" : true,
|
||||
"graphics" :
|
||||
{
|
||||
|
@ -564,7 +564,7 @@
|
||||
"subtype" : "primSkill.defence",
|
||||
"val" : -3,
|
||||
"valueType" : "ADDITIVE_VALUE",
|
||||
"duration" : "N_TURNS"
|
||||
"duration" : "PERMANENT"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1170,6 +1170,17 @@ bool CStack::canBeHealed() const
|
||||
&& !hasBonusOfType(Bonus::SIEGE_WEAPON);
|
||||
}
|
||||
|
||||
ui32 CStack::calculateHealedHealthPoints(ui32 toHeal, const bool resurrect) const
|
||||
{
|
||||
if(!resurrect && !alive())
|
||||
{
|
||||
logGlobal->warnStream() <<"Attempt to heal corpse detected.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::min<ui32>(toHeal, MaxHealth() - firstHPleft + (resurrect ? (baseAmount - count) * MaxHealth() : 0));
|
||||
}
|
||||
|
||||
ui8 CStack::getSpellSchoolLevel(const CSpell * spell, int * outSelectedSchool) const
|
||||
{
|
||||
int skill = valOfBonuses(Selector::typeSubtype(Bonus::SPELLCASTER, spell->id));
|
||||
@ -1181,10 +1192,39 @@ ui8 CStack::getSpellSchoolLevel(const CSpell * spell, int * outSelectedSchool) c
|
||||
|
||||
ui32 CStack::getSpellBonus(const CSpell * spell, ui32 base, const CStack * affectedStack) const
|
||||
{
|
||||
//stacks does not have spellpower etc. (yet?)
|
||||
//stacks does not have sorcery-like bonuses (yet?)
|
||||
return base;
|
||||
}
|
||||
|
||||
int CStack::getEffectLevel(const CSpell * spell) const
|
||||
{
|
||||
return getSpellSchoolLevel(spell);
|
||||
}
|
||||
|
||||
int CStack::getEffectPower(const CSpell * spell) const
|
||||
{
|
||||
return valOfBonuses(Bonus::CREATURE_SPELL_POWER) * count / 100;
|
||||
}
|
||||
|
||||
int CStack::getEnchantPower(const CSpell * spell) const
|
||||
{
|
||||
int res = valOfBonuses(Bonus::CREATURE_ENCHANT_POWER);
|
||||
if(res<=0)
|
||||
res = 3;//default for creatures
|
||||
return res;
|
||||
}
|
||||
|
||||
int CStack::getEffectValue(const CSpell * spell) const
|
||||
{
|
||||
return valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, spell->id.toEnum()) * count;
|
||||
}
|
||||
|
||||
const PlayerColor CStack::getOwner() const
|
||||
{
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
||||
bool CMP_stack::operator()( const CStack* a, const CStack* b )
|
||||
{
|
||||
switch(phase)
|
||||
|
@ -203,6 +203,8 @@ public:
|
||||
bool waited(int turn = 0) const;
|
||||
bool canMove(int turn = 0) const; //if stack can move
|
||||
bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines
|
||||
///returns actual heal value based on internal state
|
||||
ui32 calculateHealedHealthPoints(ui32 toHeal, const bool resurrect) const;
|
||||
ui32 level() const;
|
||||
si32 magicResistance() const override; //include aura of resistance
|
||||
static void stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse);
|
||||
@ -233,6 +235,20 @@ public:
|
||||
///ISpellCaster
|
||||
ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = nullptr) const override;
|
||||
ui32 getSpellBonus(const CSpell * spell, ui32 base, const CStack * affectedStack) const override;
|
||||
|
||||
///default spell school level for effect calculation
|
||||
int getEffectLevel(const CSpell * spell) const override;
|
||||
|
||||
///default spell-power for damage/heal calculation
|
||||
int getEffectPower(const CSpell * spell) const override;
|
||||
|
||||
///default spell-power for timed effects duration
|
||||
int getEnchantPower(const CSpell * spell) const override;
|
||||
|
||||
///damage/heal override(ignores spell configuration, effect level and effect power)
|
||||
int getEffectValue(const CSpell * spell) const override;
|
||||
|
||||
const PlayerColor getOwner() const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -577,10 +577,12 @@ bool CArtHandler::legalArtifact(ArtifactID id)
|
||||
{
|
||||
auto art = artifacts[id];
|
||||
//assert ( (!art->constituents) || art->constituents->size() ); //artifacts is not combined or has some components
|
||||
return (art->possibleSlots[ArtBearer::HERO].size() ||
|
||||
(art->possibleSlots[ArtBearer::COMMANDER].size() && VLC->modh->modules.COMMANDERS) ||
|
||||
(art->possibleSlots[ArtBearer::CREATURE].size() && VLC->modh->modules.STACK_ARTIFACT)) &&
|
||||
!(art->constituents); //no combo artifacts spawning
|
||||
return ((art->possibleSlots[ArtBearer::HERO].size() ||
|
||||
(art->possibleSlots[ArtBearer::COMMANDER].size() && VLC->modh->modules.COMMANDERS) ||
|
||||
(art->possibleSlots[ArtBearer::CREATURE].size() && VLC->modh->modules.STACK_ARTIFACT)) &&
|
||||
!(art->constituents) && //no combo artifacts spawning
|
||||
art->aClass >= CArtifact::ART_TREASURE &&
|
||||
art->aClass <= CArtifact::ART_RELIC);
|
||||
}
|
||||
|
||||
bool CArtHandler::isTradableArtifact(ArtifactID id) const
|
||||
@ -609,17 +611,12 @@ void CArtHandler::initAllowedArtifactsList(const std::vector<bool> &allowed)
|
||||
|
||||
for (ArtifactID i=ArtifactID::SPELLBOOK; i<ArtifactID::ART_SELECTION; i.advance(1))
|
||||
{
|
||||
//check artifacts allowed on a map
|
||||
//TODO: This line will be different when custom map format is implemented
|
||||
if (allowed[i] && legalArtifact(i))
|
||||
allowedArtifacts.push_back(artifacts[i]);
|
||||
}
|
||||
if (VLC->modh->modules.COMMANDERS) //allow all commander artifacts for testing
|
||||
{
|
||||
for (int i = 146; i <= 155; ++i)
|
||||
{
|
||||
allowedArtifacts.push_back(artifacts[i]);
|
||||
}
|
||||
}
|
||||
for (int i = GameConstants::ARTIFACTS_QUANTITY; i < artifacts.size(); ++i) //allow all new artifacts by default
|
||||
for (ArtifactID i = ArtifactID::ART_SELECTION; i<ArtifactID(artifacts.size()); i.advance(1)) //try to allow all artifacts added by mods
|
||||
{
|
||||
if (legalArtifact(ArtifactID(i)))
|
||||
allowedArtifacts.push_back(artifacts[i]);
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
std::vector <std::pair <ui16, Bonus> > bonusesPerLevel; //bonus given each n levels
|
||||
std::vector <std::pair <ui16, Bonus> > thresholdBonuses; //after certain level they will be added once
|
||||
|
||||
void levelUpArtifact (CArtifactInstance * art);
|
||||
void levelUpArtifact (CArtifactInstance * art) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -335,6 +335,11 @@ int CBattleInfoEssentials::battleCastSpells(ui8 side) const
|
||||
return getBattle()->sides[side].castSpellsCount;
|
||||
}
|
||||
|
||||
const IBonusBearer * CBattleInfoEssentials::getBattleNode() const
|
||||
{
|
||||
return getBattle();
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastSpell(PlayerColor player, ECastingMode::ECastingMode mode) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
@ -1587,9 +1592,15 @@ std::vector<BattleHex> CBattleInfoCallback::getAttackableBattleHexes() const
|
||||
return attackableBattleHexes;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell( PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode ) const
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
if(caster == nullptr)
|
||||
{
|
||||
logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpell: no spellcaster.";
|
||||
return ESpellCastProblem::INVALID;
|
||||
}
|
||||
const PlayerColor player = caster->getOwner();
|
||||
const ui8 side = playerToSide(player);
|
||||
if(!battleDoWeKnowAbout(side))
|
||||
return ESpellCastProblem::INVALID;
|
||||
@ -1598,16 +1609,11 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
if(genProblem != ESpellCastProblem::OK)
|
||||
return genProblem;
|
||||
|
||||
//Casting hero, set only if he is an actual caster.
|
||||
const CGHeroInstance *castingHero = mode == ECastingMode::HERO_CASTING
|
||||
? battleGetFightingHero(side)
|
||||
: nullptr;
|
||||
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case ECastingMode::HERO_CASTING:
|
||||
{
|
||||
const CGHeroInstance * castingHero = dynamic_cast<const CGHeroInstance *>(caster);//todo: unify hero|creature spell cost
|
||||
assert(castingHero);
|
||||
if(!castingHero->canCastThisSpell(spell))
|
||||
return ESpellCastProblem::HERO_DOESNT_KNOW_SPELL;
|
||||
@ -1617,11 +1623,10 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(!spell->combatSpell)
|
||||
return ESpellCastProblem::ADVMAP_SPELL_INSTEAD_OF_BATTLE_SPELL;
|
||||
|
||||
const ESpellCastProblem::ESpellCastProblem specificProblem = spell->canBeCasted(this, player);
|
||||
const ESpellCastProblem::ESpellCastProblem specificProblem = spell->canBeCast(this, player);
|
||||
|
||||
if(specificProblem != ESpellCastProblem::OK)
|
||||
return specificProblem;
|
||||
@ -1634,7 +1639,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
auto stacks = spell->isNegative() ? battleAliveStacks(!side) : battleAliveStacks();
|
||||
for(auto stack : stacks)
|
||||
{
|
||||
if(ESpellCastProblem::OK == spell->isImmuneByStack(castingHero, stack))
|
||||
if(ESpellCastProblem::OK == spell->isImmuneByStack(caster, stack))
|
||||
{
|
||||
allStacksImmune = false;
|
||||
break;
|
||||
@ -1645,7 +1650,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
|
||||
if(battleMaxSpellLevel() < spell->level) //effect like Recanter's Cloak or Orb of Inhibition
|
||||
if(battleMaxSpellLevel(side) < spell->level) //effect like Recanter's Cloak or Orb of Inhibition
|
||||
return ESpellCastProblem::SPELL_LEVEL_LIMIT_EXCEEDED;
|
||||
|
||||
//checking if there exists an appropriate target
|
||||
@ -1654,8 +1659,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
case CSpell::CREATURE:
|
||||
if(mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
const CGHeroInstance * caster = battleGetFightingHero(side);
|
||||
const CSpell::TargetInfo ti = spell->getTargetInfo(caster->getSpellSchoolLevel(spell));
|
||||
const CSpell::TargetInfo ti(spell, caster->getSpellSchoolLevel(spell));
|
||||
bool targetExists = false;
|
||||
|
||||
for(const CStack * stack : battleGetAllStacks()) //dead stacks will be immune anyway
|
||||
@ -1710,7 +1714,7 @@ std::vector<BattleHex> CBattleInfoCallback::battleGetPossibleTargets(PlayerColor
|
||||
case CSpell::CREATURE:
|
||||
{
|
||||
const CGHeroInstance * caster = battleGetFightingHero(playerToSide(player)); //TODO
|
||||
const CSpell::TargetInfo ti = spell->getTargetInfo(caster->getSpellSchoolLevel(spell));
|
||||
const CSpell::TargetInfo ti(spell, caster->getSpellSchoolLevel(spell));
|
||||
|
||||
for(const CStack * stack : battleAliveStacks())
|
||||
{
|
||||
@ -1772,10 +1776,16 @@ ui32 CBattleInfoCallback::battleGetSpellCost(const CSpell * sp, const CGHeroInst
|
||||
return ret - manaReduction + manaIncrease;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpellHere( PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest ) const
|
||||
ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpellHere(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ESpellCastProblem::ESpellCastProblem moreGeneralProblem = battleCanCastThisSpell(player, spell, mode);
|
||||
if(caster == nullptr)
|
||||
{
|
||||
logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpellHere: no spellcaster.";
|
||||
return ESpellCastProblem::INVALID;
|
||||
}
|
||||
const PlayerColor player = caster->getOwner();
|
||||
ESpellCastProblem::ESpellCastProblem moreGeneralProblem = battleCanCastThisSpell(caster, spell, mode);
|
||||
if(moreGeneralProblem != ESpellCastProblem::OK)
|
||||
return moreGeneralProblem;
|
||||
|
||||
@ -1826,8 +1836,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
{
|
||||
if(!deadStack && !aliveStack)
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
if(spell->id == SpellID::ANIMATE_DEAD && deadStack && !deadStack->hasBonusOfType(Bonus::UNDEAD))
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
if(deadStack && deadStack->owner != player) //you can resurrect only your own stacks //FIXME: it includes alive stacks as well
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
@ -1840,11 +1848,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
||||
if(spell->isPositive() && aliveStack->owner != player)
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
|
||||
const CGHeroInstance * caster = nullptr;
|
||||
if (mode == ECastingMode::HERO_CASTING)
|
||||
caster = battleGetFightingHero(playerToSide(player));
|
||||
|
||||
return spell->isImmuneAt(this, caster, mode, dest);
|
||||
}
|
||||
|
||||
@ -1927,7 +1930,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) co
|
||||
{
|
||||
if (subject->hasBonusFrom(Bonus::SPELL_EFFECT, spellID)
|
||||
//TODO: this ability has special limitations
|
||||
|| battleCanCastThisSpellHere(subject->owner, spellID.toSpell(), ECastingMode::CREATURE_ACTIVE_CASTING, subject->position) != ESpellCastProblem::OK)
|
||||
|| battleCanCastThisSpellHere(subject, spellID.toSpell(), ECastingMode::CREATURE_ACTIVE_CASTING, subject->position) != ESpellCastProblem::OK)
|
||||
continue;
|
||||
|
||||
switch (spellID)
|
||||
@ -2060,12 +2063,14 @@ int CBattleInfoCallback::battleGetSurrenderCost(PlayerColor Player) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
si8 CBattleInfoCallback::battleMaxSpellLevel() const
|
||||
si8 CBattleInfoCallback::battleMaxSpellLevel(ui8 side) const
|
||||
{
|
||||
const CBonusSystemNode *node = nullptr;
|
||||
if(const CGHeroInstance *h = battleGetFightingHero(battleGetMySide()))
|
||||
const IBonusBearer *node = nullptr;
|
||||
if(const CGHeroInstance * h = battleGetFightingHero(side))
|
||||
node = h;
|
||||
//TODO else use battle node
|
||||
else
|
||||
node = getBattleNode();
|
||||
|
||||
if(!node)
|
||||
return GameConstants::SPELL_LEVELS;
|
||||
|
||||
@ -2163,21 +2168,12 @@ ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCastThisSpe
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
return CBattleInfoCallback::battleCanCastThisSpell(*player, spell, ECastingMode::HERO_CASTING);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCastThisSpell(const CSpell * spell, BattleHex destination) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
return battleCanCastThisSpellHere(*player, spell, ECastingMode::HERO_CASTING, destination);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID);
|
||||
ASSERT_IF_CALLED_WITH_PLAYER
|
||||
return battleCanCastThisSpellHere(*player, spell, ECastingMode::CREATURE_ACTIVE_CASTING, destination);
|
||||
const ISpellCaster * hero = battleGetMyHero();
|
||||
if(hero == nullptr)
|
||||
return ESpellCastProblem::INVALID;
|
||||
else
|
||||
return CBattleInfoCallback::battleCanCastThisSpell(hero, spell, ECastingMode::HERO_CASTING);
|
||||
}
|
||||
|
||||
bool CPlayerBattleCallback::battleCanFlee() const
|
||||
|
@ -15,6 +15,7 @@ class CGameState;
|
||||
class CGTownInstance;
|
||||
class CGHeroInstance;
|
||||
class CStack;
|
||||
class ISpellCaster;
|
||||
class CSpell;
|
||||
struct BattleInfo;
|
||||
struct CObstacleInstance;
|
||||
@ -158,6 +159,7 @@ class DLL_LINKAGE CBattleInfoEssentials : public virtual CCallbackBase
|
||||
{
|
||||
protected:
|
||||
bool battleDoWeKnowAbout(ui8 side) const;
|
||||
const IBonusBearer * getBattleNode() const;
|
||||
public:
|
||||
enum EStackOwnership
|
||||
{
|
||||
@ -189,7 +191,7 @@ public:
|
||||
ui8 playerToSide(PlayerColor player) const;
|
||||
ui8 battleGetSiegeLevel() const; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||
bool battleHasHero(ui8 side) const;
|
||||
int battleCastSpells(ui8 side) const; //how many spells has given side casted
|
||||
int battleCastSpells(ui8 side) const; //how many spells has given side cast
|
||||
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //depracated for players callback, easy to get wrong
|
||||
const CArmedInstance * battleGetArmyObject(ui8 side) const;
|
||||
InfoAboutHero battleGetHeroInfo(ui8 side) const;
|
||||
@ -276,12 +278,11 @@ public:
|
||||
std::vector<BattleHex> getAttackableBattleHexes() const;
|
||||
|
||||
//*** MAGIC
|
||||
si8 battleMaxSpellLevel() const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
|
||||
si8 battleMaxSpellLevel(ui8 side) const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
|
||||
ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastSpell(PlayerColor player, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode) const; //checks if given player can cast given spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode) const; //checks if given player can cast given spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode
|
||||
std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const;
|
||||
|
||||
SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;
|
||||
@ -324,9 +325,8 @@ class DLL_LINKAGE CPlayerBattleCallback : public CBattleInfoCallback
|
||||
public:
|
||||
bool battleCanFlee() const; //returns true if caller can flee from the battle
|
||||
TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true) const; //returns stacks on battlefield
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) const; //determines if given spell can be casted (and returns problem description)
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell, BattleHex destination) const; //if hero can cast spell here
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) const; //determines if given spell can be cast (and returns problem description)
|
||||
|
||||
int battleGetSurrenderCost() const; //returns cost of surrendering battle, -1 if surrendering is not possible
|
||||
|
||||
bool battleCanCastSpell(ESpellCastProblem::ESpellCastProblem *outProblem = nullptr) const; //returns true, if caller can cast a spell. If not, if pointer is given via arg, the reason will be written.
|
||||
|
@ -853,34 +853,42 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars
|
||||
case 'B': //Blind
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::BLIND;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case 'H': //Hypnotize
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::HYPNOTIZE;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case 'I': //Implosion
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::IMPLOSION;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case 'K': //Berserk
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::BERSERK;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case 'M': //Meteor Shower
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::METEOR_SHOWER;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case 'N': //dispell beneficial spells
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::DISPEL_HELPFUL_SPELLS;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case 'R': //Armageddon
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::ARMAGEDDON;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case 'S': //Slow
|
||||
b.type = Bonus::SPELL_IMMUNITY;
|
||||
b.subtype = SpellID::SLOW;
|
||||
b.additionalInfo = 0;//normal immunity
|
||||
break;
|
||||
case '6':
|
||||
case '7':
|
||||
|
@ -199,7 +199,7 @@ public:
|
||||
/// generates tier-specific bonus tree entries
|
||||
void buildBonusTreeForTiers();
|
||||
|
||||
void afterLoadFinalization();
|
||||
void afterLoadFinalization() override;
|
||||
|
||||
std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
|
||||
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
std::string getQuantityTXT(bool capitalized = true) const;
|
||||
virtual int getExpRank() const;
|
||||
virtual int getLevel() const; //different for regular stack and commander
|
||||
si32 magicResistance() const;
|
||||
si32 magicResistance() const override;
|
||||
CreatureID getCreatureID() const; //-1 if not available
|
||||
std::string getName() const; //plural or singular
|
||||
virtual void init();
|
||||
@ -104,12 +104,12 @@ public:
|
||||
CCommanderInstance (CreatureID id);
|
||||
~CCommanderInstance();
|
||||
void setAlive (bool alive);
|
||||
void giveStackExp (TExpType exp);
|
||||
void giveStackExp (TExpType exp) override;
|
||||
void levelUp ();
|
||||
|
||||
bool gainsLevel() const; //true if commander has lower level than should upon his experience
|
||||
ui64 getPower() const {return 0;};
|
||||
int getExpRank() const;
|
||||
ui64 getPower() const override {return 0;};
|
||||
int getExpRank() const override;
|
||||
int getLevel() const override;
|
||||
ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet
|
||||
|
||||
|
@ -182,7 +182,7 @@ int CGameInfoCallback::estimateSpellDamage(const CSpell * sp, const CGHeroInstan
|
||||
ERROR_RET_VAL_IF(hero && !canGetFullInfo(hero), "Cannot get info about caster!", -1);
|
||||
|
||||
if (hero) //we see hero's spellbook
|
||||
return sp->calculateDamage(hero, nullptr, hero->getSpellSchoolLevel(sp), hero->getPrimSkillLevel(PrimarySkill::SPELL_POWER));
|
||||
return sp->calculateDamage(hero, nullptr, hero->getEffectLevel(sp), hero->getEffectPower(sp));
|
||||
else
|
||||
return 0; //mage guild
|
||||
}
|
||||
|
@ -127,26 +127,26 @@ public:
|
||||
virtual std::string getBattleAIName() const = 0; //has to return name of the battle AI to be used
|
||||
|
||||
//battle interface
|
||||
virtual BattleAction activeStack(const CStack * stack);
|
||||
virtual void yourTacticPhase(int distance);
|
||||
virtual void battleNewRound(int round);
|
||||
virtual void battleCatapultAttacked(const CatapultAttack & ca);
|
||||
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);
|
||||
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa);
|
||||
virtual void actionStarted(const BattleAction &action);
|
||||
virtual void battleNewRoundFirst(int round);
|
||||
virtual void actionFinished(const BattleAction &action);
|
||||
virtual void battleStacksEffectsSet(const SetStackEffect & sse);
|
||||
virtual BattleAction activeStack(const CStack * stack) override;
|
||||
virtual void yourTacticPhase(int distance) override;
|
||||
virtual void battleNewRound(int round) override;
|
||||
virtual void battleCatapultAttacked(const CatapultAttack & ca) override;
|
||||
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override;
|
||||
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) override;
|
||||
virtual void actionStarted(const BattleAction &action) override;
|
||||
virtual void battleNewRoundFirst(int round) override;
|
||||
virtual void actionFinished(const BattleAction &action) override;
|
||||
virtual void battleStacksEffectsSet(const SetStackEffect & sse) override;
|
||||
//virtual void battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
virtual void battleStacksRemoved(const BattleStacksRemoved & bsr);
|
||||
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles);
|
||||
virtual void battleNewStackAppeared(const CStack * stack);
|
||||
virtual void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance);
|
||||
virtual void battleAttack(const BattleAttack *ba);
|
||||
virtual void battleSpellCast(const BattleSpellCast *sc);
|
||||
virtual void battleEnd(const BattleResult *br);
|
||||
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom);
|
||||
virtual void battleStacksRemoved(const BattleStacksRemoved & bsr) override;
|
||||
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles) override;
|
||||
virtual void battleNewStackAppeared(const CStack * stack) override;
|
||||
virtual void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) override;
|
||||
virtual void battleAttack(const BattleAttack *ba) override;
|
||||
virtual void battleSpellCast(const BattleSpellCast *sc) override;
|
||||
virtual void battleEnd(const BattleResult *br) override;
|
||||
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, bool tentHeal, si32 lifeDrainFrom) override;
|
||||
|
||||
virtual void saveGame(COSer & h, const int version); //saving
|
||||
virtual void loadGame(CISer & h, const int version); //loading
|
||||
virtual void saveGame(COSer & h, const int version) override; //saving
|
||||
virtual void loadGame(CISer & h, const int version) override; //loading
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
template <typename T> class CApplyOnGS : public CBaseForGSApply
|
||||
{
|
||||
public:
|
||||
void applyOnGS(CGameState *gs, void *pack) const
|
||||
void applyOnGS(CGameState *gs, void *pack) const override
|
||||
{
|
||||
T *ptr = static_cast<T*>(pack);
|
||||
|
||||
|
@ -159,7 +159,7 @@ void Unicode::trimRight(std::string & text, const size_t amount/* =1 */)
|
||||
class LocaleWithComma: public std::numpunct<char>
|
||||
{
|
||||
protected:
|
||||
char do_decimal_point() const
|
||||
char do_decimal_point() const override
|
||||
{
|
||||
return ',';
|
||||
}
|
||||
|
@ -178,9 +178,9 @@ public:
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||
|
||||
void afterLoadFinalization();
|
||||
void afterLoadFinalization() override;
|
||||
|
||||
std::vector<bool> getDefaultAllowed() const;
|
||||
std::vector<bool> getDefaultAllowed() const override;
|
||||
|
||||
~CHeroClassHandler();
|
||||
|
||||
@ -244,7 +244,7 @@ public:
|
||||
CHeroHandler(); //c-tor
|
||||
~CHeroHandler(); //d-tor
|
||||
|
||||
std::vector<bool> getDefaultAllowed() const;
|
||||
std::vector<bool> getDefaultAllowed() const override;
|
||||
|
||||
/**
|
||||
* Gets a list of default allowed abilities. OH3 abilities/skills are all allowed by default.
|
||||
|
@ -1551,7 +1551,7 @@ public:
|
||||
|
||||
void openNextFile(const std::string &fname); //throws!
|
||||
void clear();
|
||||
void reportState(CLogger * out);
|
||||
void reportState(CLogger * out) override;
|
||||
|
||||
void putMagicBytes(const std::string &text);
|
||||
|
||||
@ -1578,7 +1578,7 @@ public:
|
||||
|
||||
void openNextFile(const boost::filesystem::path & fname, int minimalVersion); //throws!
|
||||
void clear();
|
||||
void reportState(CLogger * out);
|
||||
void reportState(CLogger * out) override;
|
||||
|
||||
void checkMagicBytes(const std::string & text);
|
||||
|
||||
@ -1616,7 +1616,7 @@ class DLL_LINKAGE CConnection
|
||||
CConnection(void);
|
||||
|
||||
void init();
|
||||
void reportState(CLogger * out);
|
||||
void reportState(CLogger * out) override;
|
||||
public:
|
||||
CISer iser;
|
||||
COSer oser;
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace GameConstants
|
||||
{
|
||||
const std::string VCMI_VERSION = "VCMI 0.98d";
|
||||
const std::string VCMI_VERSION = "VCMI 0.98e";
|
||||
|
||||
const int BFIELD_WIDTH = 17;
|
||||
const int BFIELD_HEIGHT = 11;
|
||||
@ -51,6 +51,7 @@ namespace GameConstants
|
||||
const int SPELLS_QUANTITY=70;
|
||||
const int CREATURES_COUNT = 197;
|
||||
|
||||
const ui32 BASE_MOVEMENT_COST = 100; //default cost for non-diagonal movement
|
||||
}
|
||||
|
||||
class CArtifact;
|
||||
@ -414,7 +415,8 @@ namespace ECastingMode
|
||||
{
|
||||
HERO_CASTING, AFTER_ATTACK_CASTING, //also includes cast before attack
|
||||
MAGIC_MIRROR, CREATURE_ACTIVE_CASTING, ENCHANTER_CASTING,
|
||||
SPELL_LIKE_ATTACK
|
||||
SPELL_LIKE_ATTACK,
|
||||
PASSIVE_CASTING//f.e. opening battle spells
|
||||
};
|
||||
}
|
||||
|
||||
@ -699,6 +701,7 @@ namespace Battle
|
||||
{
|
||||
enum ActionType
|
||||
{
|
||||
CANCEL = -3,
|
||||
END_TACTIC_PHASE = -2,
|
||||
INVALID = -1,
|
||||
NO_ACTION = 0,
|
||||
@ -823,6 +826,7 @@ public:
|
||||
//BLACKSHARD_OF_THE_DEAD_KNIGHT = 8,
|
||||
TITANS_THUNDER = 135,
|
||||
//CORNUCOPIA = 140,
|
||||
//FIXME: the following is only true if WoG is enabled. Otherwise other mod artifacts will take these slots.
|
||||
ART_SELECTION = 144,
|
||||
ART_LOCK = 145,
|
||||
AXE_OF_SMASHING = 146,
|
||||
|
@ -504,7 +504,7 @@ const TBonusListPtr IBonusBearer::getSpellBonuses() const
|
||||
CSelector selector = Selector::sourceType(Bonus::SPELL_EFFECT)
|
||||
.And(CSelector([](const Bonus * b)->bool
|
||||
{
|
||||
return !b->type == Bonus::NONE;
|
||||
return b->type != Bonus::NONE;
|
||||
}));
|
||||
return getBonuses(selector, Selector::anyRange(), cachingStr.str());
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ public:
|
||||
BONUS_NAME(SPELL_RESISTANCE_AURA) /*eg. unicorns, value - resistance bonus in % for adjacent creatures*/ \
|
||||
BONUS_NAME(LEVEL_SPELL_IMMUNITY) /*creature is immune to all spell with level below or equal to value of this bonus*/ \
|
||||
BONUS_NAME(BLOCK_MAGIC_ABOVE) /*blocks casting spells of the level > value */ \
|
||||
BONUS_NAME(BLOCK_ALL_MAGIC) /*blocks casting spells of the level > value */ \
|
||||
BONUS_NAME(BLOCK_ALL_MAGIC) /*blocks casting spells*/ \
|
||||
BONUS_NAME(TWO_HEX_ATTACK_BREATH) /*eg. dragons*/ \
|
||||
BONUS_NAME(SPELL_DAMAGE_REDUCTION) /*eg. golems; value - reduction in %, subtype - spell school; -1 - all, 0 - air, 1 - fire, 2 - water, 3 - earth*/ \
|
||||
BONUS_NAME(NO_WALL_PENALTY) \
|
||||
@ -207,16 +207,18 @@ public:
|
||||
BONUS_NAME(RECEPTIVE) /*accepts friendly spells even with immunity*/\
|
||||
BONUS_NAME(DIRECT_DAMAGE_IMMUNITY) /*direct damage spells, that is*/\
|
||||
BONUS_NAME(CASTS) /*how many times creature can cast activated spell*/ \
|
||||
BONUS_NAME(SPECIFIC_SPELL_POWER) /* value used for Thunderbolt and Resurrection casted by units, subtype - spell id */\
|
||||
BONUS_NAME(SPECIFIC_SPELL_POWER) /* value used for Thunderbolt and Resurrection cast by units, subtype - spell id */\
|
||||
BONUS_NAME(CREATURE_SPELL_POWER) /* value per unit, divided by 100 (so faerie Dragons have 800)*/ \
|
||||
BONUS_NAME(CREATURE_ENCHANT_POWER) /* total duration of spells casted by creature */ \
|
||||
BONUS_NAME(CREATURE_ENCHANT_POWER) /* total duration of spells cast by creature */ \
|
||||
BONUS_NAME(ENCHANTED) /* permanently enchanted with spell subID of level = val, if val > 3 then spell is mass and has level of val-3*/ \
|
||||
BONUS_NAME(REBIRTH) /* val - percent of life restored, subtype = 0 - regular, 1 - at least one unit (sacred Phoenix) */\
|
||||
BONUS_NAME(ADDITIONAL_UNITS) /*val of units with id = subtype will be added to hero's army at the beginning of battle */\
|
||||
BONUS_NAME(SPOILS_OF_WAR) /*val * 10^-6 * gained exp resources of subtype will be given to hero after battle*/\
|
||||
BONUS_NAME(BLOCK)\
|
||||
BONUS_NAME(DISGUISED) /* subtype - spell level */\
|
||||
BONUS_NAME(VISIONS) /* subtype - spell level */
|
||||
BONUS_NAME(VISIONS) /* subtype - spell level */\
|
||||
BONUS_NAME(NO_TERRAIN_PENALTY) /* subtype - terrain type */\
|
||||
/* end of list */
|
||||
|
||||
|
||||
#define BONUS_SOURCE_LIST \
|
||||
@ -539,7 +541,7 @@ class DLL_LINKAGE CPropagatorNodeType : public IPropagator
|
||||
public:
|
||||
CPropagatorNodeType();
|
||||
CPropagatorNodeType(int NodeType);
|
||||
bool shouldBeAttached(CBonusSystemNode *dest);
|
||||
bool shouldBeAttached(CBonusSystemNode *dest) override;
|
||||
//CBonusSystemNode *getDestNode(CBonusSystemNode *source, CBonusSystemNode *redParent, CBonusSystemNode *redChild) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -651,7 +653,7 @@ public:
|
||||
|
||||
void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here
|
||||
TBonusListPtr limitBonuses(const BonusList &allBonuses) const; //same as above, returns out by val for convienence
|
||||
const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const;
|
||||
const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const override;
|
||||
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
|
||||
const Bonus *getBonusLocalFirst(const CSelector &selector) const;
|
||||
|
||||
|
@ -167,10 +167,11 @@ struct YourTurn : public CPackForClient //100
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
|
||||
PlayerColor player;
|
||||
boost::optional<ui8> daysWithoutCastle;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & player;
|
||||
h & player & daysWithoutCastle;
|
||||
}
|
||||
};
|
||||
|
||||
@ -986,7 +987,6 @@ struct NewTurn : public CPackForClient //101
|
||||
std::map<PlayerColor, TResources> res; //player ID => resource value[res_id]
|
||||
std::map<ObjectInstanceID, SetAvailableCreatures> cres;//creatures to be placed in towns
|
||||
ui32 day;
|
||||
bool resetBuilded;
|
||||
ui8 specialWeek; //weekType
|
||||
CreatureID creatureid; //for creature weeks
|
||||
|
||||
@ -994,7 +994,7 @@ struct NewTurn : public CPackForClient //101
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & heroes & cres & res & day & resetBuilded & specialWeek & creatureid;
|
||||
h & heroes & cres & res & day & specialWeek & creatureid;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1324,7 +1324,7 @@ struct StacksHealedOrResurrected : public CPackForClient //3013
|
||||
{
|
||||
ui32 stackID;
|
||||
ui32 healedHP;
|
||||
ui8 lowLevelResurrection; //in case this stack is resurrected by this heal, it will be marked as SUMMONED //TODO: replace with separate counter
|
||||
bool lowLevelResurrection; //in case this stack is resurrected by this heal, it will be marked as SUMMONED //TODO: replace with separate counter
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & stackID & healedHP & lowLevelResurrection;
|
||||
@ -1503,7 +1503,7 @@ struct BattleSpellCast : public CPackForClient//3009
|
||||
std::vector<CustomEffect> customEffects;
|
||||
std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
|
||||
si32 casterStack;// -1 if not cated by creature, >=0 caster stack ID
|
||||
bool castByHero; //if true - spell has been casted by hero, otherwise by a creature
|
||||
bool castByHero; //if true - spell has been cast by hero, otherwise by a creature
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & dmgToDisplay & side & id & skill & manaGained & tile & customEffects & affectedCres & casterStack & castByHero;
|
||||
@ -1605,7 +1605,7 @@ struct BattleStacksRemoved : public CPackForClient //3016
|
||||
BattleStacksRemoved(){type = 3016;}
|
||||
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
void applyCl(CClient *cl);
|
||||
void applyFirstCl(CClient *cl);//inform client before stack objects are destroyed
|
||||
|
||||
std::set<ui32> stackIDs; //IDs of removed stacks
|
||||
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
numbers.clear();
|
||||
}
|
||||
void toString(std::string &dst) const;
|
||||
std::string toString() const;
|
||||
std::string toString() const override;
|
||||
void getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst) const;
|
||||
|
||||
MetaString()
|
||||
|
@ -468,6 +468,12 @@ static int getDir(int3 src, int3 dst)
|
||||
void TryMoveHero::applyGs( CGameState *gs )
|
||||
{
|
||||
CGHeroInstance *h = gs->getHero(id);
|
||||
if (!h)
|
||||
{
|
||||
logGlobal->errorStream() << "Attempt ot move unavailable hero " << id;
|
||||
return;
|
||||
}
|
||||
|
||||
h->movement = movePoints;
|
||||
|
||||
if((result == SUCCESS || result == BLOCKING_VISIT || result == EMBARK || result == DISEMBARK) && start != end)
|
||||
@ -1136,7 +1142,7 @@ DLL_LINKAGE void BattleTriggerEffect::applyGs( CGameState *gs )
|
||||
}
|
||||
case Bonus::POISON:
|
||||
{
|
||||
Bonus * b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, 71)
|
||||
Bonus * b = st->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT, SpellID::POISON)
|
||||
.And(Selector::type(Bonus::STACK_HEALTH)));
|
||||
if (b)
|
||||
b->val = val;
|
||||
@ -1459,21 +1465,17 @@ DLL_LINKAGE void StacksHealedOrResurrected::applyGs( CGameState *gs )
|
||||
}
|
||||
}
|
||||
vstd::amin(changedStack->firstHPleft, changedStack->MaxHealth());
|
||||
//removal of negative effects
|
||||
if(resurrected)
|
||||
{
|
||||
//removing all features from negative spells
|
||||
const BonusList tmpFeatures = changedStack->getBonusList();
|
||||
//changedStack->bonuses.clear();
|
||||
|
||||
for(Bonus *b : tmpFeatures)
|
||||
//removing all effects from negative spells
|
||||
auto selector = [](const Bonus * b)
|
||||
{
|
||||
const CSpell *s = b->sourceSpell();
|
||||
if(s && s->isNegative())
|
||||
{
|
||||
changedStack->removeBonus(b);
|
||||
}
|
||||
}
|
||||
//Special case: DISRUPTING_RAY is "immune" to dispell
|
||||
//Other even PERMANENT effects can be removed
|
||||
return (s != nullptr) && s->isNegative() && (s->id != SpellID::DISRUPTING_RAY);
|
||||
};
|
||||
changedStack->popBonuses(selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1621,18 +1623,8 @@ DLL_LINKAGE void YourTurn::applyGs( CGameState *gs )
|
||||
{
|
||||
gs->currentPlayer = player;
|
||||
|
||||
//count days without town
|
||||
auto & playerState = gs->players[player];
|
||||
if(playerState.towns.empty())
|
||||
{
|
||||
if(playerState.daysWithoutCastle)
|
||||
++(*playerState.daysWithoutCastle);
|
||||
else playerState.daysWithoutCastle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
playerState.daysWithoutCastle = boost::none;
|
||||
}
|
||||
playerState.daysWithoutCastle = daysWithoutCastle;
|
||||
}
|
||||
|
||||
DLL_LINKAGE Component::Component(const CStackBasicDescriptor &stack)
|
||||
|
@ -30,6 +30,7 @@
|
||||
<Add option="-lboost_thread$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_chrono$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_locale$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_date_time$(#boost.libsuffix)" />
|
||||
<Add option="-liconv" />
|
||||
<Add option="-ldbghelp" />
|
||||
<Add directory="$(#sdl2.lib)" />
|
||||
@ -59,6 +60,7 @@
|
||||
<Add option="-lboost_thread$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_chrono$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_locale$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_date_time$(#boost.libsuffix)" />
|
||||
<Add option="-liconv" />
|
||||
<Add option="-ldbghelp" />
|
||||
<Add directory="$(#sdl2.lib)" />
|
||||
@ -89,6 +91,7 @@
|
||||
<Add option="-lboost_thread$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_chrono$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_locale$(#boost.libsuffix)" />
|
||||
<Add option="-lboost_date_time$(#boost.libsuffix)" />
|
||||
<Add option="-liconv" />
|
||||
<Add option="-ldbghelp" />
|
||||
<Add directory="$(#sdl2.lib64)" />
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
bool existsResource(const ResourceID & resourceName) const override;
|
||||
std::string getMountPoint() const override;
|
||||
boost::optional<std::string> getResourceName(const ResourceID & resourceName) const override;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
|
||||
|
||||
private:
|
||||
/** A list of files in this map
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
std::unique_ptr<CInputStream> load(const ResourceID & resourceName) const override;
|
||||
bool existsResource(const ResourceID & resourceName) const override;
|
||||
std::string getMountPoint() const override;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -116,7 +116,7 @@ private:
|
||||
/**
|
||||
* Decompresses data to ensure that buffer has newSize bytes or end of stream was reached
|
||||
*/
|
||||
si64 readMore(ui8 * data, si64 size);
|
||||
si64 readMore(ui8 * data, si64 size) override;
|
||||
|
||||
/** The file stream with compressed data. */
|
||||
std::unique_ptr<CInputStream> gzipStream;
|
||||
|
@ -58,56 +58,49 @@ static int lowestSpeed(const CGHeroInstance * chi)
|
||||
|
||||
ui32 CGHeroInstance::getTileCost(const TerrainTile &dest, const TerrainTile &from) const
|
||||
{
|
||||
//base move cost
|
||||
unsigned ret = 100;
|
||||
unsigned ret = GameConstants::BASE_MOVEMENT_COST;
|
||||
|
||||
//if there is road both on dest and src tiles - use road movement cost
|
||||
if(dest.roadType != ERoadType::NO_ROAD && from.roadType != ERoadType::NO_ROAD)
|
||||
if(dest.roadType != ERoadType::NO_ROAD && from.roadType != ERoadType::NO_ROAD)
|
||||
{
|
||||
int road = std::min(dest.roadType,from.roadType); //used road ID
|
||||
int road = std::min(dest.roadType,from.roadType); //used road ID
|
||||
switch(road)
|
||||
{
|
||||
case ERoadType::DIRT_ROAD:
|
||||
case ERoadType::DIRT_ROAD:
|
||||
ret = 75;
|
||||
break;
|
||||
case ERoadType::GRAVEL_ROAD:
|
||||
case ERoadType::GRAVEL_ROAD:
|
||||
ret = 65;
|
||||
break;
|
||||
case ERoadType::COBBLESTONE_ROAD:
|
||||
case ERoadType::COBBLESTONE_ROAD:
|
||||
ret = 50;
|
||||
break;
|
||||
default:
|
||||
logGlobal->errorStream() << "Unknown road type: " << road << "... Something wrong!";
|
||||
logGlobal->errorStream() << "Unknown road type: " << road << "... Something wrong!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(!hasBonusOfType(Bonus::NO_TERRAIN_PENALTY, from.terType))
|
||||
{
|
||||
//FIXME: in H3 presence of Nomad in army will remove terrain penalty for sand. Bonus not implemented in VCMI
|
||||
|
||||
// NOTE: in H3 neutral stacks will ignore terrain penalty only if placed as topmost stack(s) in hero army.
|
||||
// This is clearly bug in H3 however intended behaviour is not clear.
|
||||
// Current VCMI behaviour will ignore neutrals in calculations so army in VCMI
|
||||
// will always have best penalty without any influence from player-defined stacks order
|
||||
|
||||
bool nativeArmy = true;
|
||||
for(auto stack : stacks)
|
||||
{
|
||||
int nativeTerrain = VLC->townh->factions[stack.second->type->faction]->nativeTerrain;
|
||||
|
||||
if (nativeTerrain != -1 && nativeTerrain != from.terType)
|
||||
if(nativeTerrain != -1 && nativeTerrain != from.terType)
|
||||
{
|
||||
nativeArmy = false;
|
||||
ret = VLC->heroh->terrCosts[from.terType];
|
||||
ret -= getSecSkillLevel(SecondarySkill::PATHFINDING) * 25;
|
||||
if(ret < GameConstants::BASE_MOVEMENT_COST)
|
||||
ret = GameConstants::BASE_MOVEMENT_COST;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nativeArmy)
|
||||
{
|
||||
ret = VLC->heroh->terrCosts[from.terType];
|
||||
ret-=getSecSkillLevel(SecondarySkill::PATHFINDING)*25;
|
||||
ret = ret < 100 ? 100 : ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -902,6 +895,33 @@ ui32 CGHeroInstance::getSpellBonus(const CSpell * spell, ui32 base, const CStack
|
||||
return base;
|
||||
}
|
||||
|
||||
int CGHeroInstance::getEffectLevel(const CSpell * spell) const
|
||||
{
|
||||
if(hasBonusOfType(Bonus::MAXED_SPELL, spell->id))
|
||||
return 3;//todo: recheck specialty from where this bonus is. possible bug
|
||||
else
|
||||
return getSpellSchoolLevel(spell);
|
||||
}
|
||||
|
||||
int CGHeroInstance::getEffectPower(const CSpell * spell) const
|
||||
{
|
||||
return getPrimSkillLevel(PrimarySkill::SPELL_POWER);
|
||||
}
|
||||
|
||||
int CGHeroInstance::getEnchantPower(const CSpell * spell) const
|
||||
{
|
||||
return getPrimSkillLevel(PrimarySkill::SPELL_POWER) + valOfBonuses(Bonus::SPELL_DURATION);
|
||||
}
|
||||
|
||||
int CGHeroInstance::getEffectValue(const CSpell * spell) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const PlayerColor CGHeroInstance::getOwner() const
|
||||
{
|
||||
return tempOwner;
|
||||
}
|
||||
|
||||
bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const
|
||||
{
|
||||
@ -939,7 +959,7 @@ bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const
|
||||
{//hero has this spell in spellbook
|
||||
logGlobal->errorStream() << "Banned spell " << spell->name << " in spellbook.";
|
||||
}
|
||||
return specificBonus;
|
||||
return specificBonus || schoolBonus || levelBonus;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -117,18 +117,18 @@ public:
|
||||
} skillsInfo;
|
||||
|
||||
//int3 getSightCenter() const; //"center" tile from which the sight distance is calculated
|
||||
int getSightRadious() const; //sight distance (should be used if player-owned structure)
|
||||
int getSightRadious() const override; //sight distance (should be used if player-owned structure)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||
void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed
|
||||
int getBoatType() const override; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool hasSpellbook() const;
|
||||
EAlignment::EAlignment getAlignment() const;
|
||||
const std::string &getBiography() const;
|
||||
bool needsLastStack()const;
|
||||
bool needsLastStack()const override;
|
||||
ui32 getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||
ui32 getLowestCreatureSpeed() const;
|
||||
int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
|
||||
@ -177,7 +177,7 @@ public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setType(si32 ID, si32 subID);
|
||||
void setType(si32 ID, si32 subID) override;
|
||||
|
||||
void initHero();
|
||||
void initHero(HeroTypeID SUBID);
|
||||
@ -210,6 +210,20 @@ public:
|
||||
ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = nullptr) const override;
|
||||
ui32 getSpellBonus(const CSpell * spell, ui32 base, const CStack * affectedStack) const override;
|
||||
|
||||
///default spell school level for effect calculation
|
||||
int getEffectLevel(const CSpell * spell) const override;
|
||||
|
||||
///default spell-power for damage/heal calculation
|
||||
int getEffectPower(const CSpell * spell) const override;
|
||||
|
||||
///default spell-power for timed effects duration
|
||||
int getEnchantPower(const CSpell * spell) const override;
|
||||
|
||||
///damage/heal override(ignores spell configuration, effect level and effect power)
|
||||
int getEffectValue(const CSpell * spell) const override;
|
||||
|
||||
const PlayerColor getOwner() const override;
|
||||
|
||||
void deserializationFix();
|
||||
|
||||
void initObj() override;
|
||||
|
@ -76,7 +76,7 @@ class DLL_LINKAGE CGUniversity : public CGMarket
|
||||
public:
|
||||
std::vector<int> skills; //available skills
|
||||
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
||||
void initObj() override;//set skills for trade
|
||||
void onHeroVisit(const CGHeroInstance * h) const override; //open window
|
||||
|
||||
|
@ -184,7 +184,7 @@ void CGDwelling::updateGuards() const
|
||||
//default condition - creatures are of level 5 or higher
|
||||
for (auto creatureEntry : creatures)
|
||||
{
|
||||
if (VLC->creh->creatures[creatureEntry.second.at(0)]->level >= 5)
|
||||
if (VLC->creh->creatures[creatureEntry.second.at(0)]->level >= 5 && ID != Obj::REFUGEE_CAMP)
|
||||
{
|
||||
guarded = true;
|
||||
break;
|
||||
|
@ -203,21 +203,21 @@ public:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool passableFor(PlayerColor color) const;
|
||||
bool passableFor(PlayerColor color) const override;
|
||||
//int3 getSightCenter() const override; //"center" tile from which the sight distance is calculated
|
||||
int getSightRadious() const override; //returns sight distance
|
||||
int getBoatType() const; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||
void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed. Parameter will be cleared
|
||||
int getBoatType() const override; //0 - evil (if a ship can be evil...?), 1 - good, 2 - neutral
|
||||
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed. Parameter will be cleared
|
||||
int getMarketEfficiency() const override; //=market count
|
||||
bool allowsTrade(EMarketMode::EMarketMode mode) const;
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const;
|
||||
bool allowsTrade(EMarketMode::EMarketMode mode) const override;
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
||||
|
||||
void setType(si32 ID, si32 subID);
|
||||
void setType(si32 ID, si32 subID) override;
|
||||
void updateAppearance();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool needsLastStack() const;
|
||||
bool needsLastStack() const override;
|
||||
CGTownInstance::EFortLevel fortLevel() const;
|
||||
int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
|
||||
int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
|
||||
|
@ -156,7 +156,7 @@ protected:
|
||||
class DLL_LINKAGE CGKeymasterTent : public CGKeys
|
||||
{
|
||||
public:
|
||||
bool wasVisited (PlayerColor player) const;
|
||||
bool wasVisited (PlayerColor player) const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -173,9 +173,9 @@ public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
|
||||
void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = nullptr) const override;
|
||||
void getRolloverText (MetaString &text, bool onHover) const;
|
||||
bool checkQuest (const CGHeroInstance * h) const;
|
||||
bool checkQuest (const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -313,17 +313,15 @@ void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRando
|
||||
si32 selectedChance = rng.nextInt(totalChance - 1);
|
||||
//logGlobal->debugStream() << "Selected chance for bank config is " << selectedChance;
|
||||
|
||||
int cumulativeChance = 0;
|
||||
for (auto & node : levels)
|
||||
{
|
||||
if (selectedChance < node["chance"].Float())
|
||||
cumulativeChance += node["chance"].Float();
|
||||
if (selectedChance < cumulativeChance)
|
||||
{
|
||||
bank->setConfig(generateConfig(node, rng));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedChance -= node["chance"].Float();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,16 @@ protected:
|
||||
public:
|
||||
CDefaultObjectTypeHandler(){}
|
||||
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const override
|
||||
{
|
||||
return createTyped(tmpl);
|
||||
}
|
||||
|
||||
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
||||
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const
|
||||
virtual std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -58,24 +58,24 @@ class CObstacleConstructor : public CDefaultObjectTypeHandler<CGObjectInstance>
|
||||
{
|
||||
public:
|
||||
CObstacleConstructor();
|
||||
bool isStaticObject();
|
||||
bool isStaticObject() override;
|
||||
};
|
||||
|
||||
class CTownInstanceConstructor : public CDefaultObjectTypeHandler<CGTownInstance>
|
||||
{
|
||||
JsonNode filtersJson;
|
||||
protected:
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const override;
|
||||
void initTypeData(const JsonNode & input) override;
|
||||
|
||||
public:
|
||||
CFaction * faction;
|
||||
std::map<std::string, LogicalExpression<BuildingID>> filters;
|
||||
|
||||
CTownInstanceConstructor();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
void afterLoadFinalization();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const override;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
||||
void afterLoadFinalization() override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -88,17 +88,17 @@ class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance
|
||||
{
|
||||
JsonNode filtersJson;
|
||||
protected:
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const override;
|
||||
void initTypeData(const JsonNode & input) override;
|
||||
|
||||
public:
|
||||
CHeroClass * heroClass;
|
||||
std::map<std::string, LogicalExpression<HeroTypeID>> filters;
|
||||
|
||||
CHeroInstanceConstructor();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
void afterLoadFinalization();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const override;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
||||
void afterLoadFinalization() override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -114,14 +114,14 @@ class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling
|
||||
JsonNode guards;
|
||||
|
||||
protected:
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const override;
|
||||
void initTypeData(const JsonNode & input) override;
|
||||
|
||||
public:
|
||||
|
||||
CDwellingInstanceConstructor();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const override;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
||||
|
||||
bool producesCreature(const CCreature * crea) const;
|
||||
std::vector<const CCreature *> getProducedCreatures() const;
|
||||
@ -163,13 +163,13 @@ public:
|
||||
TPossibleGuards getPossibleGuards() const;
|
||||
|
||||
// These functions should try to evaluate minimal possible/max possible guards to give provide information on possible thread to AI
|
||||
CArmyStructure minGuards() const;
|
||||
CArmyStructure maxGuards() const;
|
||||
CArmyStructure minGuards() const override;
|
||||
CArmyStructure maxGuards() const override;
|
||||
|
||||
bool givesResources() const;
|
||||
bool givesArtifacts() const;
|
||||
bool givesCreatures() const;
|
||||
bool givesSpells() const;
|
||||
bool givesResources() const override;
|
||||
bool givesArtifacts() const override;
|
||||
bool givesCreatures() const override;
|
||||
bool givesSpells() const override;
|
||||
};
|
||||
|
||||
class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank>
|
||||
@ -178,7 +178,7 @@ class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank>
|
||||
|
||||
JsonVector levels;
|
||||
protected:
|
||||
void initTypeData(const JsonNode & input);
|
||||
void initTypeData(const JsonNode & input) override;
|
||||
|
||||
public:
|
||||
// all banks of this type will be reset N days after clearing,
|
||||
@ -186,10 +186,10 @@ public:
|
||||
|
||||
CBankInstanceConstructor();
|
||||
|
||||
CGObjectInstance *create(ObjectTemplate tmpl) const;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
CGObjectInstance *create(ObjectTemplate tmpl) const override;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
||||
|
||||
std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const;
|
||||
std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ class DLL_LINKAGE CPlayersVisited: public CGObjectInstance
|
||||
public:
|
||||
std::set<PlayerColor> players; //players that visited this object
|
||||
|
||||
bool wasVisited(PlayerColor player) const;
|
||||
bool wasVisited(PlayerColor player) const override;
|
||||
bool wasVisited(TeamID team) const;
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
|
||||
@ -394,7 +394,7 @@ public:
|
||||
class CGShipyard : public CGObjectInstance, public IShipyard
|
||||
{
|
||||
public:
|
||||
void getOutOffsets(std::vector<int3> &offsets) const; //offsets to obj pos when we boat can be placed
|
||||
void getOutOffsets(std::vector<int3> &offsets) const override; //offsets to obj pos when we boat can be placed
|
||||
CGShipyard();
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
|
@ -50,14 +50,14 @@ public:
|
||||
*
|
||||
* @return a unique ptr of the loaded map class
|
||||
*/
|
||||
std::unique_ptr<CMap> loadMap();
|
||||
std::unique_ptr<CMap> loadMap() override;
|
||||
|
||||
/**
|
||||
* Loads the VCMI/H3 map header.
|
||||
*
|
||||
* @return a unique ptr of the loaded map header class
|
||||
*/
|
||||
std::unique_ptr<CMapHeader> loadMapHeader();
|
||||
std::unique_ptr<CMapHeader> loadMapHeader() override;
|
||||
|
||||
/** true if you want to enable the map loader profiler to see how long a specific part took; default=false */
|
||||
static const bool IS_PROFILING_ENABLED;
|
||||
|
@ -31,20 +31,20 @@ public:
|
||||
*
|
||||
* @return a unique ptr of the loaded map class
|
||||
*/
|
||||
std::unique_ptr<CMap> loadMap();
|
||||
std::unique_ptr<CMap> loadMap() override;
|
||||
|
||||
/**
|
||||
* Loads the VCMI/Json map header.
|
||||
*
|
||||
* @return a unique ptr of the loaded map header class
|
||||
*/
|
||||
std::unique_ptr<CMapHeader> loadMapHeader();
|
||||
std::unique_ptr<CMapHeader> loadMapHeader() override;
|
||||
|
||||
/**
|
||||
* Modifies supplied map header using Json data
|
||||
*
|
||||
*/
|
||||
void patchMapHeader(std::unique_ptr<CMapHeader> & header);
|
||||
void patchMapHeader(std::unique_ptr<CMapHeader> & header) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -93,8 +93,8 @@ void CMapGenerator::initQuestArtsRemaining()
|
||||
{
|
||||
for (auto art : VLC->arth->artifacts)
|
||||
{
|
||||
if (art->aClass == CArtifact::ART_TREASURE && art->constituentOf.empty()) //don't use parts of combined artifacts
|
||||
questArtifacts.push_back(art->id);
|
||||
if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->id) && art->constituentOf.empty()) //don't use parts of combined artifacts
|
||||
questArtifacts.push_back(art->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,12 +28,12 @@ public:
|
||||
|
||||
const std::map<std::string, CRmgTemplate *> & getTemplates() const;
|
||||
|
||||
std::vector<bool> getDefaultAllowed() const;
|
||||
std::vector<JsonNode> loadLegacyData(size_t dataSize);
|
||||
std::vector<bool> getDefaultAllowed() const override;
|
||||
std::vector<JsonNode> loadLegacyData(size_t dataSize) override;
|
||||
|
||||
/// loads single object into game. Scope is namespace of this object, same as name of source mod
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data);
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index);
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||
|
||||
private:
|
||||
CRmgTemplate::CSize parseMapTemplateSize(const std::string & text) const;
|
||||
|
@ -1506,7 +1506,10 @@ bool CRmgTemplateZone::placeMines (CMapGenerator* gen)
|
||||
mine->subID = static_cast<si32>(res);
|
||||
mine->producedResource = res;
|
||||
mine->producedQuantity = mine->defaultResProduction();
|
||||
addCloseObject(mine, 1500);
|
||||
if (!i)
|
||||
addCloseObject(mine, 1500); //only firts one is close
|
||||
else
|
||||
addRequiredObject(mine, 1500);
|
||||
}
|
||||
}
|
||||
for (const auto & res : preciousResources)
|
||||
@ -1587,7 +1590,12 @@ bool CRmgTemplateZone::createRequiredObjects(CMapGenerator* gen)
|
||||
// smallest distance to zone center, greatest distance to nearest object
|
||||
auto isCloser = [this, gen](const int3 & lhs, const int3 & rhs) -> bool
|
||||
{
|
||||
return (this->pos.dist2dSQ(lhs) * 0.5f - gen->getNearestObjectDistance(lhs)) < (this->pos.dist2dSQ(rhs) * 0.5f - gen->getNearestObjectDistance(rhs));
|
||||
float lDist = this->pos.dist2d(lhs);
|
||||
float rDist = this->pos.dist2d(rhs);
|
||||
lDist *= (lDist > 12) ? 10 : 1; //objects within 12 tile radius are preferred (smaller distance rating)
|
||||
rDist *= (rDist > 12) ? 10 : 1;
|
||||
|
||||
return (lDist * 0.5f - std::sqrt(gen->getNearestObjectDistance(lhs))) < (rDist * 0.5f - std::sqrt(gen->getNearestObjectDistance(rhs)));
|
||||
};
|
||||
|
||||
boost::sort (tiles, isCloser);
|
||||
|
@ -13,6 +13,37 @@
|
||||
|
||||
#include "../NetPacks.h"
|
||||
#include "../BattleState.h"
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
|
||||
///HealingSpellMechanics
|
||||
void HealingSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
EHealLevel healLevel = getHealLevel(parameters.effectLevel);
|
||||
int hpGained = calculateHealedHP(env, parameters, ctx);
|
||||
StacksHealedOrResurrected shr;
|
||||
shr.lifeDrain = false;
|
||||
shr.tentHealing = false;
|
||||
|
||||
const bool resurrect = (healLevel != EHealLevel::HEAL);
|
||||
for(auto & attackedCre : ctx.attackedCres)
|
||||
{
|
||||
StacksHealedOrResurrected::HealInfo hi;
|
||||
hi.stackID = (attackedCre)->ID;
|
||||
int stackHPgained = parameters.caster->getSpellBonus(owner, hpGained, attackedCre);
|
||||
hi.healedHP = attackedCre->calculateHealedHealthPoints(stackHPgained, resurrect);
|
||||
hi.lowLevelResurrection = (healLevel == EHealLevel::RESURRECT);
|
||||
shr.healedStacks.push_back(hi);
|
||||
}
|
||||
if(!shr.healedStacks.empty())
|
||||
env->sendAndApply(&shr);
|
||||
}
|
||||
|
||||
int HealingSpellMechanics::calculateHealedHP(const SpellCastEnvironment* env, const BattleSpellCastParameters& parameters, SpellCastContext& ctx) const
|
||||
{
|
||||
if(parameters.effectValue != 0)
|
||||
return parameters.effectValue; //Archangel
|
||||
return owner->calculateRawEffectValue(parameters.effectLevel, parameters.effectPower); //???
|
||||
}
|
||||
|
||||
///AntimagicMechanics
|
||||
void AntimagicMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const
|
||||
@ -67,7 +98,7 @@ std::set<const CStack *> ChainLightningMechanics::getAffectedStacks(SpellTargeti
|
||||
}
|
||||
|
||||
///CloneMechanics
|
||||
void CloneMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void CloneMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
const CStack * clonedStack = nullptr;
|
||||
if(ctx.attackedCres.size())
|
||||
@ -101,23 +132,21 @@ void CloneMechanics::applyBattleEffects(const SpellCastEnvironment * env, Battle
|
||||
env->sendAndApply(&ssp);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CloneMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
|
||||
ESpellCastProblem::ESpellCastProblem CloneMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
|
||||
{
|
||||
//can't clone already cloned creature
|
||||
if(vstd::contains(obj->state, EBattleStackState::CLONED))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
if(obj->cloneID != -1)
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
//TODO: how about stacks casting Clone?
|
||||
//currently Clone casted by stack is assumed Expert level
|
||||
ui8 schoolLevel;
|
||||
if(caster)
|
||||
{
|
||||
schoolLevel = caster->getSpellSchoolLevel(owner);
|
||||
schoolLevel = caster->getEffectLevel(owner);
|
||||
}
|
||||
else
|
||||
{
|
||||
schoolLevel = 3;
|
||||
schoolLevel = 3;//todo: remove
|
||||
}
|
||||
|
||||
if(schoolLevel < 3)
|
||||
@ -146,6 +175,11 @@ void CureMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * pac
|
||||
});
|
||||
}
|
||||
|
||||
HealingSpellMechanics::EHealLevel CureMechanics::getHealLevel(int effectLevel) const
|
||||
{
|
||||
return EHealLevel::HEAL;
|
||||
}
|
||||
|
||||
///DispellMechanics
|
||||
void DispellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const
|
||||
{
|
||||
@ -153,21 +187,35 @@ void DispellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast *
|
||||
doDispell(battle, packet, Selector::sourceType(Bonus::SPELL_EFFECT));
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem DispellMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
|
||||
ESpellCastProblem::ESpellCastProblem DispellMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
|
||||
{
|
||||
//DISPELL ignores all immunities, so do not call default
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "source_" << Bonus::SPELL_EFFECT;
|
||||
|
||||
if(obj->hasBonus(Selector::sourceType(Bonus::SPELL_EFFECT), cachingStr.str()))
|
||||
{
|
||||
return ESpellCastProblem::OK;
|
||||
//just in case
|
||||
if(!obj->alive())
|
||||
return ESpellCastProblem::WRONG_SPELL_TARGET;
|
||||
}
|
||||
//DISPELL ignores all immunities, except specific absolute immunity
|
||||
{
|
||||
//SPELL_IMMUNITY absolute case
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "type_" << Bonus::SPELL_IMMUNITY << "subtype_" << owner->id.toEnum() << "addInfo_1";
|
||||
if(obj->hasBonus(Selector::typeSubtypeInfo(Bonus::SPELL_IMMUNITY, owner->id.toEnum(), 1), cachingStr.str()))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
{
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "source_" << Bonus::SPELL_EFFECT;
|
||||
|
||||
if(obj->hasBonus(Selector::sourceType(Bonus::SPELL_EFFECT), cachingStr.str()))
|
||||
{
|
||||
return ESpellCastProblem::OK;
|
||||
}
|
||||
}
|
||||
return ESpellCastProblem::WRONG_SPELL_TARGET;
|
||||
//any other immunities are ignored - do not execute default algorithm
|
||||
}
|
||||
|
||||
void DispellMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void DispellMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
DefaultSpellMechanics::applyBattleEffects(env, parameters, ctx);
|
||||
|
||||
@ -190,15 +238,15 @@ void DispellMechanics::applyBattleEffects(const SpellCastEnvironment * env, Batt
|
||||
}
|
||||
|
||||
///EarthquakeMechanics
|
||||
void EarthquakeMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void EarthquakeMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
if(nullptr == parameters.cb->town)
|
||||
if(nullptr == parameters.cb->battleGetDefendedTown())
|
||||
{
|
||||
env->complain("EarthquakeMechanics: not town siege");
|
||||
return;
|
||||
}
|
||||
|
||||
if(CGTownInstance::NONE == parameters.cb->town->fortLevel())
|
||||
if(CGTownInstance::NONE == parameters.cb->battleGetDefendedTown()->fortLevel())
|
||||
{
|
||||
env->complain("EarthquakeMechanics: town has no fort");
|
||||
return;
|
||||
@ -277,7 +325,7 @@ void EarthquakeMechanics::applyBattleEffects(const SpellCastEnvironment * env, B
|
||||
env->sendAndApply(&ca);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem EarthquakeMechanics::canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
ESpellCastProblem::ESpellCastProblem EarthquakeMechanics::canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
{
|
||||
if(nullptr == cb->battleGetDefendedTown())
|
||||
{
|
||||
@ -288,8 +336,9 @@ ESpellCastProblem::ESpellCastProblem EarthquakeMechanics::canBeCasted(const CBat
|
||||
{
|
||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||
}
|
||||
|
||||
if(owner->getTargetInfo(0).smart) //TODO: use real spell level
|
||||
|
||||
CSpell::TargetInfo ti(owner, 0);//TODO: use real spell level
|
||||
if(ti.smart)
|
||||
{
|
||||
//if spell targeting is smart, then only attacker can use it
|
||||
if(cb->playerToSide(player) != 0)
|
||||
@ -300,15 +349,15 @@ ESpellCastProblem::ESpellCastProblem EarthquakeMechanics::canBeCasted(const CBat
|
||||
}
|
||||
|
||||
///HypnotizeMechanics
|
||||
ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
|
||||
ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
|
||||
{
|
||||
if(nullptr != caster) //do not resist hypnotize casted after attack, for example
|
||||
//todo: maybe do not resist on passive cast
|
||||
if(nullptr != caster)
|
||||
{
|
||||
//TODO: what with other creatures casting hypnotize, Faerie Dragons style?
|
||||
ui64 subjectHealth = (obj->count - 1) * obj->MaxHealth() + obj->firstHPleft;
|
||||
//apply 'damage' bonus for hypnotize, including hero specialty
|
||||
ui64 maxHealth = caster->getSpellBonus(owner, caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER)
|
||||
* owner->power + owner->getPower(caster->getSpellSchoolLevel(owner)), obj);
|
||||
ui64 maxHealth = caster->getSpellBonus(owner, owner->calculateRawEffectValue(caster->getEffectLevel(owner), caster->getEffectPower(owner)), obj);
|
||||
if (subjectHealth > maxHealth)
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
@ -316,9 +365,9 @@ ESpellCastProblem::ESpellCastProblem HypnotizeMechanics::isImmuneByStack(const C
|
||||
}
|
||||
|
||||
///ObstacleMechanics
|
||||
void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
auto placeObstacle = [&, this](BattleHex pos)
|
||||
auto placeObstacle = [&, this](const BattleHex & pos)
|
||||
{
|
||||
static int obstacleIdToGive = parameters.cb->obstacles.size()
|
||||
? (parameters.cb->obstacles.back()->uniqueID+1)
|
||||
@ -355,8 +404,8 @@ void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, Bat
|
||||
obstacle->pos = pos;
|
||||
obstacle->casterSide = parameters.casterSide;
|
||||
obstacle->ID = owner->id;
|
||||
obstacle->spellLevel = parameters.spellLvl;
|
||||
obstacle->casterSpellPower = parameters.usedSpellPower;
|
||||
obstacle->spellLevel = parameters.effectLevel;
|
||||
obstacle->casterSpellPower = parameters.effectPower;
|
||||
obstacle->uniqueID = obstacleIdToGive++;
|
||||
|
||||
BattleObstaclePlaced bop;
|
||||
@ -364,6 +413,8 @@ void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, Bat
|
||||
env->sendAndApply(&bop);
|
||||
};
|
||||
|
||||
const BattleHex destination = parameters.getFirstDestinationHex();
|
||||
|
||||
switch(owner->id)
|
||||
{
|
||||
case SpellID::QUICKSAND:
|
||||
@ -388,12 +439,22 @@ void ObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, Bat
|
||||
|
||||
break;
|
||||
case SpellID::FORCE_FIELD:
|
||||
placeObstacle(parameters.destination);
|
||||
if(!destination.isValid())
|
||||
{
|
||||
env->complain("Invalid destination for FORCE_FIELD");
|
||||
return;
|
||||
}
|
||||
placeObstacle(destination);
|
||||
break;
|
||||
case SpellID::FIRE_WALL:
|
||||
{
|
||||
if(!destination.isValid())
|
||||
{
|
||||
env->complain("Invalid destination for FIRE_WALL");
|
||||
return;
|
||||
}
|
||||
//fire wall is build from multiple obstacles - one fire piece for each affected hex
|
||||
auto affectedHexes = owner->rangeInHexes(parameters.destination, parameters.spellLvl, parameters.casterSide);
|
||||
auto affectedHexes = owner->rangeInHexes(destination, parameters.spellLvl, parameters.casterSide);
|
||||
for(BattleHex hex : affectedHexes)
|
||||
placeObstacle(hex);
|
||||
}
|
||||
@ -442,9 +503,9 @@ std::vector<BattleHex> WallMechanics::rangeInHexes(BattleHex centralHex, ui8 sch
|
||||
}
|
||||
|
||||
///RemoveObstacleMechanics
|
||||
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
if(auto obstacleToRemove = parameters.cb->battleGetObstacleOnPos(parameters.destination, false))
|
||||
if(auto obstacleToRemove = parameters.cb->battleGetObstacleOnPos(parameters.getFirstDestinationHex(), false))
|
||||
{
|
||||
ObstaclesRemoved obr;
|
||||
obr.obstacles.insert(obstacleToRemove->uniqueID);
|
||||
@ -454,20 +515,34 @@ void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * en
|
||||
env->complain("There's no obstacle to remove!");
|
||||
}
|
||||
|
||||
///SpecialRisingSpellMechanics
|
||||
ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
HealingSpellMechanics::EHealLevel RisingSpellMechanics::getHealLevel(int effectLevel) const
|
||||
{
|
||||
//this may be even distinct class
|
||||
if((effectLevel <= 1) && (owner->id == SpellID::RESURRECTION))
|
||||
return EHealLevel::RESURRECT;
|
||||
|
||||
return EHealLevel::TRUE_RESURRECT;
|
||||
}
|
||||
|
||||
///SacrificeMechanics
|
||||
ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
{
|
||||
// for sacrifice we have to check for 2 targets (one dead to resurrect and one living to destroy)
|
||||
|
||||
bool targetExists = false;
|
||||
bool targetToSacrificeExists = false;
|
||||
|
||||
const CGHeroInstance * caster = nullptr; //todo: use ISpellCaster
|
||||
|
||||
if(cb->battleHasHero(cb->playerToSide(player)))
|
||||
caster = cb->battleGetFightingHero(cb->playerToSide(player));
|
||||
|
||||
for(const CStack * stack : cb->battleGetAllStacks())
|
||||
{
|
||||
//using isImmuneBy directly as this mechanics does not have overridden immunity check
|
||||
//therefore we do not need to check caster and casting mode
|
||||
//TODO: check that we really should check immunity for both stacks
|
||||
ESpellCastProblem::ESpellCastProblem res = owner->isImmuneBy(stack);
|
||||
ESpellCastProblem::ESpellCastProblem res = owner->internalIsImmune(caster, stack);
|
||||
const bool immune = ESpellCastProblem::OK != res && ESpellCastProblem::NOT_DECIDED != res;
|
||||
const bool casterStack = stack->owner == player;
|
||||
|
||||
@ -489,39 +564,57 @@ ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCasted(const CBatt
|
||||
}
|
||||
|
||||
|
||||
void SacrificeMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void SacrificeMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
RisingSpellMechanics::applyBattleEffects(env, parameters, ctx);
|
||||
|
||||
if(parameters.selectedStack == parameters.cb->battleActiveStack())
|
||||
//set another active stack than the one removed, or bad things will happen
|
||||
//TODO: make that part of BattleStacksRemoved? what about client update?
|
||||
const CStack * victim = nullptr;
|
||||
if(parameters.destinations.size() == 2)
|
||||
{
|
||||
//makeStackDoNothing(gs->curB->getStack (selectedStack));
|
||||
|
||||
BattleSetActiveStack sas;
|
||||
|
||||
//std::vector<const CStack *> hlp;
|
||||
//battleGetStackQueue(hlp, 1, selectedStack); //next after this one
|
||||
|
||||
//if(hlp.size())
|
||||
//{
|
||||
// sas.stack = hlp[0]->ID;
|
||||
//}
|
||||
//else
|
||||
// complain ("No new stack to activate!");
|
||||
sas.stack = parameters.cb->getNextStack()->ID; //why the hell next stack has same ID as current?
|
||||
env->sendAndApply(&sas);
|
||||
|
||||
victim = parameters.destinations[1].stackValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo: remove and report error
|
||||
victim = parameters.selectedStack;
|
||||
}
|
||||
if(nullptr == victim)
|
||||
{
|
||||
env->complain("SacrificeMechanics: No stack to sacrifice");
|
||||
return;
|
||||
}
|
||||
//resurrect target after basic checks
|
||||
RisingSpellMechanics::applyBattleEffects(env, parameters, ctx);
|
||||
//it is safe to remove even active stack
|
||||
BattleStacksRemoved bsr;
|
||||
bsr.stackIDs.insert(parameters.selectedStack->ID); //somehow it works for teleport?
|
||||
bsr.stackIDs.insert(victim->ID);
|
||||
env->sendAndApply(&bsr);
|
||||
}
|
||||
|
||||
int SacrificeMechanics::calculateHealedHP(const SpellCastEnvironment* env, const BattleSpellCastParameters& parameters, SpellCastContext& ctx) const
|
||||
{
|
||||
int res = 0;
|
||||
const CStack * victim = nullptr;
|
||||
|
||||
if(parameters.destinations.size() == 2)
|
||||
{
|
||||
victim = parameters.destinations[1].stackValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo: remove and report error
|
||||
victim = parameters.selectedStack;
|
||||
}
|
||||
if(nullptr == victim)
|
||||
{
|
||||
env->complain("SacrificeMechanics: No stack to sacrifice");
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = (parameters.effectPower + victim->MaxHealth() + owner->getPower(parameters.effectLevel)) * victim->count;
|
||||
return res;
|
||||
}
|
||||
|
||||
///SpecialRisingSpellMechanics
|
||||
ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
|
||||
ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
|
||||
{
|
||||
// following does apply to resurrect and animate dead(?) only
|
||||
// for sacrifice health calculation and health limit check don't matter
|
||||
@ -529,18 +622,19 @@ ESpellCastProblem::ESpellCastProblem SpecialRisingSpellMechanics::isImmuneByStac
|
||||
if(obj->count >= obj->baseAmount)
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
|
||||
if(caster) //FIXME: Archangels can cast immune stack
|
||||
{
|
||||
auto maxHealth = calculateHealedHP(caster, obj, nullptr);
|
||||
if (maxHealth < obj->MaxHealth()) //must be able to rise at least one full creature
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
//FIXME: Archangels can cast immune stack and this should be applied for them and not hero
|
||||
// if(caster)
|
||||
// {
|
||||
// auto maxHealth = calculateHealedHP(caster, obj, nullptr);
|
||||
// if (maxHealth < obj->MaxHealth()) //must be able to rise at least one full creature
|
||||
// return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
// }
|
||||
|
||||
return DefaultSpellMechanics::isImmuneByStack(caster,obj);
|
||||
}
|
||||
|
||||
///SummonMechanics
|
||||
ESpellCastProblem::ESpellCastProblem SummonMechanics::canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
ESpellCastProblem::ESpellCastProblem SummonMechanics::canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
{
|
||||
const ui8 side = cb->playerToSide(player);
|
||||
|
||||
@ -559,7 +653,7 @@ ESpellCastProblem::ESpellCastProblem SummonMechanics::canBeCasted(const CBattleI
|
||||
return ESpellCastProblem::OK;
|
||||
}
|
||||
|
||||
void SummonMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void SummonMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
BattleStackAdded bsa;
|
||||
bsa.creID = creatureToSummon;
|
||||
@ -570,7 +664,7 @@ void SummonMechanics::applyBattleEffects(const SpellCastEnvironment * env, Battl
|
||||
//TODO stack casting -> probably power will be zero; set the proper number of creatures manually
|
||||
int percentBonus = parameters.casterHero ? parameters.casterHero->valOfBonuses(Bonus::SPECIFIC_SPELL_DAMAGE, owner->id.toEnum()) : 0;
|
||||
|
||||
bsa.amount = parameters.usedSpellPower
|
||||
bsa.amount = parameters.effectPower
|
||||
* owner->getPower(parameters.spellLvl)
|
||||
* (100 + percentBonus) / 100.0; //new feature - percentage bonus
|
||||
if(bsa.amount)
|
||||
@ -580,15 +674,46 @@ void SummonMechanics::applyBattleEffects(const SpellCastEnvironment * env, Battl
|
||||
}
|
||||
|
||||
///TeleportMechanics
|
||||
void TeleportMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void TeleportMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
BattleStackMoved bsm;
|
||||
bsm.distance = -1;
|
||||
bsm.stack = parameters.selectedStack->ID;
|
||||
std::vector<BattleHex> tiles;
|
||||
tiles.push_back(parameters.destination);
|
||||
bsm.tilesToMove = tiles;
|
||||
bsm.teleporting = true;
|
||||
env->sendAndApply(&bsm);
|
||||
//todo: check legal teleport
|
||||
if(parameters.destinations.size() == 2)
|
||||
{
|
||||
//first destination creature to move
|
||||
const CStack * target = parameters.destinations[0].stackValue;
|
||||
if(nullptr == target)
|
||||
{
|
||||
env->complain("TeleportMechanics: no stack to teleport");
|
||||
return;
|
||||
}
|
||||
//second destination hex to move to
|
||||
const BattleHex destination = parameters.destinations[1].hexValue;
|
||||
if(!destination.isValid())
|
||||
{
|
||||
env->complain("TeleportMechanics: invalid teleport destination");
|
||||
return;
|
||||
}
|
||||
BattleStackMoved bsm;
|
||||
bsm.distance = -1;
|
||||
bsm.stack = target->ID;
|
||||
std::vector<BattleHex> tiles;
|
||||
tiles.push_back(destination);
|
||||
bsm.tilesToMove = tiles;
|
||||
bsm.teleporting = true;
|
||||
env->sendAndApply(&bsm);
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo: remove and report error
|
||||
BattleStackMoved bsm;
|
||||
bsm.distance = -1;
|
||||
bsm.stack = parameters.selectedStack->ID;
|
||||
std::vector<BattleHex> tiles;
|
||||
tiles.push_back(parameters.getFirstDestinationHex());
|
||||
bsm.tilesToMove = tiles;
|
||||
bsm.teleporting = true;
|
||||
env->sendAndApply(&bsm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,23 @@
|
||||
|
||||
#include "CDefaultSpellMechanics.h"
|
||||
|
||||
class DLL_LINKAGE HealingSpellMechanics : public DefaultSpellMechanics
|
||||
{
|
||||
public:
|
||||
enum class EHealLevel
|
||||
{
|
||||
HEAL,
|
||||
RESURRECT,
|
||||
TRUE_RESURRECT
|
||||
};
|
||||
|
||||
HealingSpellMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
virtual int calculateHealedHP(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const;
|
||||
virtual EHealLevel getHealLevel(int effectLevel) const = 0;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE AntimagicMechanics : public DefaultSpellMechanics
|
||||
{
|
||||
public:
|
||||
@ -31,44 +48,46 @@ class DLL_LINKAGE CloneMechanics : public DefaultSpellMechanics
|
||||
{
|
||||
public:
|
||||
CloneMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CureMechanics : public DefaultSpellMechanics
|
||||
class DLL_LINKAGE CureMechanics : public HealingSpellMechanics
|
||||
{
|
||||
public:
|
||||
CureMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
CureMechanics(CSpell * s): HealingSpellMechanics(s){};
|
||||
|
||||
void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final;
|
||||
|
||||
EHealLevel getHealLevel(int effectLevel) const override final;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE DispellMechanics : public DefaultSpellMechanics
|
||||
{
|
||||
public:
|
||||
DispellMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
|
||||
|
||||
void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final;
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE EarthquakeMechanics : public DefaultSpellMechanics
|
||||
{
|
||||
public:
|
||||
EarthquakeMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE HypnotizeMechanics : public DefaultSpellMechanics
|
||||
{
|
||||
public:
|
||||
HypnotizeMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE ObstacleMechanics : public DefaultSpellMechanics
|
||||
@ -77,7 +96,7 @@ public:
|
||||
ObstacleMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE WallMechanics : public ObstacleMechanics
|
||||
@ -92,15 +111,15 @@ class DLL_LINKAGE RemoveObstacleMechanics : public DefaultSpellMechanics
|
||||
public:
|
||||
RemoveObstacleMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
///all rising spells
|
||||
class DLL_LINKAGE RisingSpellMechanics : public DefaultSpellMechanics
|
||||
class DLL_LINKAGE RisingSpellMechanics : public HealingSpellMechanics
|
||||
{
|
||||
public:
|
||||
RisingSpellMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
|
||||
RisingSpellMechanics(CSpell * s): HealingSpellMechanics(s){};
|
||||
EHealLevel getHealLevel(int effectLevel) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE SacrificeMechanics : public RisingSpellMechanics
|
||||
@ -108,9 +127,10 @@ class DLL_LINKAGE SacrificeMechanics : public RisingSpellMechanics
|
||||
public:
|
||||
SacrificeMechanics(CSpell * s): RisingSpellMechanics(s){};
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
int calculateHealedHP(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
///all rising spells but SACRIFICE
|
||||
@ -118,7 +138,7 @@ class DLL_LINKAGE SpecialRisingSpellMechanics : public RisingSpellMechanics
|
||||
{
|
||||
public:
|
||||
SpecialRisingSpellMechanics(CSpell * s): RisingSpellMechanics(s){};
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE SummonMechanics : public DefaultSpellMechanics
|
||||
@ -126,9 +146,9 @@ class DLL_LINKAGE SummonMechanics : public DefaultSpellMechanics
|
||||
public:
|
||||
SummonMechanics(CSpell * s, CreatureID cre): DefaultSpellMechanics(s), creatureToSummon(cre){};
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
private:
|
||||
CreatureID creatureToSummon;
|
||||
};
|
||||
@ -138,5 +158,5 @@ class DLL_LINKAGE TeleportMechanics: public DefaultSpellMechanics
|
||||
public:
|
||||
TeleportMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
@ -139,7 +139,7 @@ void DefaultSpellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCa
|
||||
//check for each bonus if it should be removed
|
||||
const bool isSpellEffect = Selector::sourceType(Bonus::SPELL_EFFECT)(b);
|
||||
const int spellID = isSpellEffect ? b->sid : -1;
|
||||
|
||||
//No exceptions, ANY spell can be countered, even if it can`t be dispelled.
|
||||
return isSpellEffect && vstd::contains(owner->counteredSpells, spellID);
|
||||
});
|
||||
}
|
||||
@ -223,29 +223,35 @@ ESpellCastResult DefaultSpellMechanics::applyAdventureEffects(const SpellCastEnv
|
||||
|
||||
void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
|
||||
{
|
||||
logGlobal->debugStream() << "Started spell cast. Spell: "<<owner->name<<"; mode:"<<parameters.mode;
|
||||
|
||||
if(nullptr == parameters.caster)
|
||||
{
|
||||
env->complain("No spell-caster provided.");
|
||||
return;
|
||||
}
|
||||
|
||||
BattleSpellCast sc;
|
||||
sc.side = parameters.casterSide;
|
||||
sc.id = owner->id;
|
||||
sc.skill = parameters.spellLvl;
|
||||
sc.tile = parameters.destination;
|
||||
sc.dmgToDisplay = 0;
|
||||
sc.castByHero = nullptr != parameters.casterHero;
|
||||
sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1);
|
||||
sc.manaGained = 0;
|
||||
|
||||
prepareBattleCast(parameters, sc);
|
||||
|
||||
//check it there is opponent hero
|
||||
const ui8 otherSide = 1-parameters.casterSide;
|
||||
const CGHeroInstance * otherHero = nullptr;
|
||||
if(parameters.cb->battleHasHero(otherSide))
|
||||
otherHero = parameters.cb->battleGetFightingHero(otherSide);
|
||||
int spellCost = 0;
|
||||
|
||||
//calculate spell cost
|
||||
if(parameters.casterHero)
|
||||
if(parameters.mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
spellCost = parameters.cb->battleGetSpellCost(owner, parameters.casterHero);
|
||||
|
||||
if(parameters.secHero && parameters.mode == ECastingMode::HERO_CASTING) //handle mana channel
|
||||
{
|
||||
if(nullptr != otherHero) //handle mana channel
|
||||
{
|
||||
int manaChannel = 0;
|
||||
for(const CStack * stack : parameters.cb->battleGetAllStacks(true)) //TODO: shouldn't bonus system handle it somehow?
|
||||
{
|
||||
if(stack->owner == parameters.secHero->tempOwner)
|
||||
if(stack->owner == otherHero->tempOwner)
|
||||
{
|
||||
vstd::amax(manaChannel, stack->valOfBonuses(Bonus::MANA_CHANNELING));
|
||||
}
|
||||
@ -253,53 +259,36 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
||||
sc.manaGained = (manaChannel * spellCost) / 100;
|
||||
}
|
||||
}
|
||||
logGlobal->debugStream() << "spellCost: " << spellCost;
|
||||
|
||||
//calculating affected creatures for all spells
|
||||
//must be vector, as in Chain Lightning order matters
|
||||
std::vector<const CStack*> attackedCres; //CStack vector is somewhat more suitable than ID vector
|
||||
|
||||
auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.casterColor, parameters.spellLvl, parameters.destination, parameters.casterHero);
|
||||
auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.casterColor, parameters.spellLvl, parameters.getFirstDestinationHex(), parameters.caster);
|
||||
std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres));
|
||||
|
||||
logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks";
|
||||
|
||||
std::vector <const CStack*> reflected;//for magic mirror
|
||||
|
||||
//checking if creatures resist
|
||||
//resistance/reflection is applied only to negative spells
|
||||
if(owner->isNegative())
|
||||
//checking if creatures resist
|
||||
handleResistance(env, attackedCres, sc);
|
||||
//it is actual spell and can be reflected to single target, no recurrence
|
||||
const bool tryMagicMirror = owner->isNegative() && owner->level && owner->getLevelInfo(0).range == "0";
|
||||
if(tryMagicMirror)
|
||||
{
|
||||
//it is actual spell and can be reflected to single target, no recurrence
|
||||
const bool tryMagicMirror = parameters.mode != ECastingMode::MAGIC_MIRROR && owner->level && owner->getLevelInfo(0).range == "0";
|
||||
std::vector <const CStack*> resisted;
|
||||
for(auto s : attackedCres)
|
||||
{
|
||||
//magic resistance
|
||||
const int prob = std::min((s)->magicResistance(), 100); //probability of resistance in %
|
||||
|
||||
if(env->getRandomGenerator().nextInt(99) < prob)
|
||||
{
|
||||
resisted.push_back(s);
|
||||
}
|
||||
//magic mirror
|
||||
if(tryMagicMirror)
|
||||
{
|
||||
const int mirrorChance = (s)->valOfBonuses(Bonus::MAGIC_MIRROR);
|
||||
if(env->getRandomGenerator().nextInt(99) < mirrorChance)
|
||||
reflected.push_back(s);
|
||||
}
|
||||
const int mirrorChance = (s)->valOfBonuses(Bonus::MAGIC_MIRROR);
|
||||
if(env->getRandomGenerator().nextInt(99) < mirrorChance)
|
||||
reflected.push_back(s);
|
||||
}
|
||||
|
||||
vstd::erase_if(attackedCres, [&resisted, reflected](const CStack * s)
|
||||
vstd::erase_if(attackedCres, [&reflected](const CStack * s)
|
||||
{
|
||||
return vstd::contains(resisted, s) || vstd::contains(reflected, s);
|
||||
return vstd::contains(reflected, s);
|
||||
});
|
||||
|
||||
for(auto s : resisted)
|
||||
{
|
||||
BattleSpellCast::CustomEffect effect;
|
||||
effect.effect = 78;
|
||||
effect.stack = s->ID;
|
||||
sc.customEffects.push_back(effect);
|
||||
}
|
||||
for(auto s : reflected)
|
||||
{
|
||||
BattleSpellCast::CustomEffect effect;
|
||||
@ -316,13 +305,12 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
||||
|
||||
StacksInjured si;
|
||||
SpellCastContext ctx(attackedCres, sc, si);
|
||||
|
||||
applyBattleEffects(env, parameters, ctx);
|
||||
|
||||
env->sendAndApply(&sc);
|
||||
|
||||
//spend mana
|
||||
if(parameters.casterHero)
|
||||
if(parameters.mode == ECastingMode::HERO_CASTING)
|
||||
{
|
||||
SetMana sm;
|
||||
sm.absolute = false;
|
||||
@ -334,9 +322,9 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
||||
|
||||
if(sc.manaGained > 0)
|
||||
{
|
||||
assert(parameters.secHero);
|
||||
assert(otherHero);
|
||||
|
||||
sm.hid = parameters.secHero->id;
|
||||
sm.hid = otherHero->id;
|
||||
sm.val = sc.manaGained;
|
||||
env->sendAndApply(&sm);
|
||||
}
|
||||
@ -358,7 +346,7 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
||||
ssp.absolute = false;
|
||||
env->sendAndApply(&ssp);
|
||||
}
|
||||
|
||||
logGlobal->debugStream() << "Finished spell cast. Spell: "<<owner->name<<"; mode:"<<parameters.mode;
|
||||
//Magic Mirror effect
|
||||
for(auto & attackedCre : reflected)
|
||||
{
|
||||
@ -373,18 +361,17 @@ void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleS
|
||||
{
|
||||
int targetHex = (*RandomGeneratorUtil::nextItem(mirrorTargets, env->getRandomGenerator()))->position;
|
||||
|
||||
BattleSpellCastParameters mirrorParameters = parameters;
|
||||
BattleSpellCastParameters mirrorParameters(parameters.cb, attackedCre, owner);
|
||||
mirrorParameters.spellLvl = 0;
|
||||
mirrorParameters.casterSide = 1-parameters.casterSide;
|
||||
mirrorParameters.casterColor = (attackedCre)->owner;
|
||||
mirrorParameters.casterHero = nullptr;
|
||||
mirrorParameters.destination = targetHex;
|
||||
mirrorParameters.secHero = parameters.casterHero;
|
||||
mirrorParameters.aimToHex(targetHex);
|
||||
mirrorParameters.mode = ECastingMode::MAGIC_MIRROR;
|
||||
mirrorParameters.casterStack = (attackedCre);
|
||||
mirrorParameters.selectedStack = nullptr;
|
||||
|
||||
battleCast(env, mirrorParameters);
|
||||
mirrorParameters.spellLvl = parameters.spellLvl;
|
||||
mirrorParameters.effectLevel = parameters.effectLevel;
|
||||
mirrorParameters.effectPower = parameters.effectPower;
|
||||
mirrorParameters.effectValue = parameters.effectValue;
|
||||
mirrorParameters.enchantPower = parameters.enchantPower;
|
||||
castMagicMirror(env, mirrorParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -486,74 +473,21 @@ void DefaultSpellMechanics::battleLogSingleTarget(std::vector<std::string> & log
|
||||
}
|
||||
}
|
||||
|
||||
int DefaultSpellMechanics::calculateDuration(const CGHeroInstance * caster, int usedSpellPower) const
|
||||
void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
if(caster == nullptr)
|
||||
{
|
||||
if (!usedSpellPower)
|
||||
return 3; //default duration of all creature spells
|
||||
else
|
||||
return usedSpellPower; //use creature spell power
|
||||
}
|
||||
else
|
||||
return caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + caster->valOfBonuses(Bonus::SPELL_DURATION);
|
||||
}
|
||||
|
||||
ui32 DefaultSpellMechanics::calculateHealedHP(const CGHeroInstance* caster, const CStack* stack, const CStack* sacrificedStack) const
|
||||
{
|
||||
int healedHealth;
|
||||
|
||||
if(!owner->isHealingSpell())
|
||||
{
|
||||
logGlobal->errorStream() << "calculateHealedHP called for nonhealing spell "<< owner->name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int spellPowerSkill = caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER);
|
||||
const int levelPower = owner->getPower(caster->getSpellSchoolLevel(owner));
|
||||
|
||||
if (owner->id == SpellID::SACRIFICE && sacrificedStack)
|
||||
healedHealth = (spellPowerSkill + sacrificedStack->MaxHealth() + levelPower) * sacrificedStack->count;
|
||||
else
|
||||
healedHealth = spellPowerSkill * owner->power + levelPower; //???
|
||||
healedHealth = caster->getSpellBonus(owner, healedHealth, stack);
|
||||
return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (owner->isRisingSpell() ? stack->baseAmount * stack->MaxHealth() : 0));
|
||||
}
|
||||
|
||||
|
||||
void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
int effectLevel = parameters.spellLvl;
|
||||
{
|
||||
//MAXED_SPELL bonus.
|
||||
if(parameters.casterHero != nullptr)
|
||||
if(parameters.casterHero->hasBonusOfType(Bonus::MAXED_SPELL, owner->id))
|
||||
effectLevel = 3;
|
||||
}
|
||||
|
||||
//applying effects
|
||||
if(owner->isOffensiveSpell())
|
||||
{
|
||||
int spellDamage = 0;
|
||||
if(parameters.casterStack && parameters.mode != ECastingMode::MAGIC_MIRROR)
|
||||
{
|
||||
int unitSpellPower = parameters.casterStack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, owner->id.toEnum());
|
||||
if(unitSpellPower)
|
||||
ctx.sc.dmgToDisplay = spellDamage = parameters.casterStack->count * unitSpellPower; //TODO: handle immunities
|
||||
else //Faerie Dragon
|
||||
{
|
||||
parameters.usedSpellPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_SPELL_POWER) * parameters.casterStack->count / 100;
|
||||
ctx.sc.dmgToDisplay = 0;
|
||||
}
|
||||
}
|
||||
int spellDamage = parameters.effectValue;
|
||||
|
||||
int chainLightningModifier = 0;
|
||||
for(auto & attackedCre : ctx.attackedCres)
|
||||
{
|
||||
BattleStackAttacked bsa;
|
||||
if(spellDamage)
|
||||
bsa.damageAmount = spellDamage >> chainLightningModifier;
|
||||
if(spellDamage != 0)
|
||||
bsa.damageAmount = owner->adjustRawDamage(parameters.caster, attackedCre, spellDamage) >> chainLightningModifier;
|
||||
else
|
||||
bsa.damageAmount = owner->calculateDamage(parameters.casterHero, attackedCre, effectLevel, parameters.usedSpellPower) >> chainLightningModifier;
|
||||
bsa.damageAmount = owner->calculateDamage(parameters.caster, attackedCre, parameters.effectLevel, parameters.effectPower) >> chainLightningModifier;
|
||||
|
||||
ctx.sc.dmgToDisplay += bsa.damageAmount;
|
||||
|
||||
@ -572,19 +506,14 @@ void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env,
|
||||
|
||||
if(owner->hasEffects())
|
||||
{
|
||||
int stackSpellPower = 0;
|
||||
if(parameters.casterStack && parameters.mode != ECastingMode::MAGIC_MIRROR)
|
||||
{
|
||||
stackSpellPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_ENCHANT_POWER);
|
||||
}
|
||||
SetStackEffect sse;
|
||||
//get default spell duration (spell power with bonuses for heroes)
|
||||
int duration = calculateDuration(parameters.casterHero, stackSpellPower ? stackSpellPower : parameters.usedSpellPower);
|
||||
int duration = parameters.enchantPower;
|
||||
//generate actual stack bonuses
|
||||
{
|
||||
int maxDuration = 0;
|
||||
std::vector<Bonus> tmp;
|
||||
owner->getEffects(tmp, effectLevel);
|
||||
owner->getEffects(tmp, parameters.effectLevel);
|
||||
for(Bonus& b : tmp)
|
||||
{
|
||||
//use configured duration if present
|
||||
@ -664,49 +593,7 @@ void DefaultSpellMechanics::applyBattleEffects(const SpellCastEnvironment * env,
|
||||
if(!sse.stacks.empty())
|
||||
env->sendAndApply(&sse);
|
||||
|
||||
}
|
||||
|
||||
if(owner->isHealingSpell())
|
||||
{
|
||||
int hpGained = 0;
|
||||
if(parameters.casterStack)
|
||||
{
|
||||
int unitSpellPower = parameters.casterStack->valOfBonuses(Bonus::SPECIFIC_SPELL_POWER, owner->id.toEnum());
|
||||
if(unitSpellPower)
|
||||
hpGained = parameters.casterStack->count * unitSpellPower; //Archangel
|
||||
else //Faerie Dragon-like effect - unused so far
|
||||
parameters.usedSpellPower = parameters.casterStack->valOfBonuses(Bonus::CREATURE_SPELL_POWER) * parameters.casterStack->count / 100;
|
||||
}
|
||||
StacksHealedOrResurrected shr;
|
||||
shr.lifeDrain = false;
|
||||
shr.tentHealing = false;
|
||||
for(auto & attackedCre : ctx.attackedCres)
|
||||
{
|
||||
StacksHealedOrResurrected::HealInfo hi;
|
||||
hi.stackID = (attackedCre)->ID;
|
||||
if (parameters.casterStack) //casted by creature
|
||||
{
|
||||
const bool resurrect = owner->isRisingSpell();
|
||||
if (hpGained)
|
||||
{
|
||||
//archangel
|
||||
hi.healedHP = std::min<ui32>(hpGained, attackedCre->MaxHealth() - attackedCre->firstHPleft + (resurrect ? attackedCre->baseAmount * attackedCre->MaxHealth() : 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
//any typical spell (commander's cure or animate dead)
|
||||
int healedHealth = parameters.usedSpellPower * owner->power + owner->getPower(effectLevel);
|
||||
hi.healedHP = std::min<ui32>(healedHealth, attackedCre->MaxHealth() - attackedCre->firstHPleft + (resurrect ? attackedCre->baseAmount * attackedCre->MaxHealth() : 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
hi.healedHP = calculateHealedHP(parameters.casterHero, attackedCre, parameters.selectedStack); //Casted by hero
|
||||
hi.lowLevelResurrection = (effectLevel <= 1) && (owner->id != SpellID::ANIMATE_DEAD);
|
||||
shr.healedStacks.push_back(hi);
|
||||
}
|
||||
if(!shr.healedStacks.empty())
|
||||
env->sendAndApply(&shr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<BattleHex> DefaultSpellMechanics::rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes) const
|
||||
@ -849,24 +736,125 @@ std::set<const CStack *> DefaultSpellMechanics::getAffectedStacks(SpellTargeting
|
||||
return attackedCres;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
{
|
||||
//no problems by default, this method is for spell-specific problems
|
||||
return ESpellCastProblem::OK;
|
||||
}
|
||||
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
|
||||
ESpellCastProblem::ESpellCastProblem DefaultSpellMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
|
||||
{
|
||||
//by default use general algorithm
|
||||
return owner->isImmuneBy(obj);
|
||||
return owner->internalIsImmune(caster, obj);
|
||||
}
|
||||
|
||||
void DefaultSpellMechanics::doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const
|
||||
{
|
||||
auto localSelector = [](const Bonus * bonus)
|
||||
{
|
||||
const CSpell * sourceSpell = bonus->sourceSpell();
|
||||
if(sourceSpell != nullptr)
|
||||
{
|
||||
//Special case: DISRUPTING_RAY is "immune" to dispell
|
||||
//Other even PERMANENT effects can be removed (f.e. BIND)
|
||||
if(sourceSpell->id == SpellID::DISRUPTING_RAY)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
for(auto stackID : packet->affectedCres)
|
||||
{
|
||||
CStack *s = battle->getStack(stackID);
|
||||
s->popBonuses(selector);
|
||||
s->popBonuses(CSelector(localSelector).And(selector));
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultSpellMechanics::castMagicMirror(const SpellCastEnvironment* env, BattleSpellCastParameters& parameters) const
|
||||
{
|
||||
logGlobal->debugStream() << "Started spell cast. Spell: "<<owner->name<<"; mode: MAGIC_MIRROR";
|
||||
if(parameters.mode != ECastingMode::MAGIC_MIRROR)
|
||||
{
|
||||
env->complain("MagicMirror: invalid mode");
|
||||
return;
|
||||
}
|
||||
BattleHex destination = parameters.getFirstDestinationHex();
|
||||
if(!destination.isValid())
|
||||
{
|
||||
env->complain("MagicMirror: invalid destination");
|
||||
return;
|
||||
}
|
||||
|
||||
BattleSpellCast sc;
|
||||
prepareBattleCast(parameters, sc);
|
||||
|
||||
//calculating affected creatures for all spells
|
||||
//must be vector, as in Chain Lightning order matters
|
||||
std::vector<const CStack*> attackedCres; //CStack vector is somewhat more suitable than ID vector
|
||||
|
||||
auto creatures = owner->getAffectedStacks(parameters.cb, parameters.mode, parameters.casterColor, parameters.spellLvl, destination, parameters.caster);
|
||||
std::copy(creatures.begin(), creatures.end(), std::back_inserter(attackedCres));
|
||||
|
||||
logGlobal->debugStream() << "will affect: " << attackedCres.size() << " stacks";
|
||||
|
||||
handleResistance(env, attackedCres, sc);
|
||||
|
||||
for(auto cre : attackedCres)
|
||||
{
|
||||
sc.affectedCres.insert(cre->ID);
|
||||
}
|
||||
|
||||
StacksInjured si;
|
||||
SpellCastContext ctx(attackedCres, sc, si);
|
||||
applyBattleEffects(env, parameters, ctx);
|
||||
|
||||
env->sendAndApply(&sc);
|
||||
if(!si.stacks.empty()) //after spellcast info shows
|
||||
env->sendAndApply(&si);
|
||||
logGlobal->debugStream() << "Finished spell cast. Spell: "<<owner->name<<"; mode: MAGIC_MIRROR";
|
||||
}
|
||||
|
||||
void DefaultSpellMechanics::handleResistance(const SpellCastEnvironment * env, std::vector<const CStack* >& attackedCres, BattleSpellCast& sc) const
|
||||
{
|
||||
//checking if creatures resist
|
||||
//resistance/reflection is applied only to negative spells
|
||||
if(owner->isNegative())
|
||||
{
|
||||
std::vector <const CStack*> resisted;
|
||||
for(auto s : attackedCres)
|
||||
{
|
||||
//magic resistance
|
||||
const int prob = std::min((s)->magicResistance(), 100); //probability of resistance in %
|
||||
|
||||
if(env->getRandomGenerator().nextInt(99) < prob)
|
||||
{
|
||||
resisted.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
vstd::erase_if(attackedCres, [&resisted](const CStack * s)
|
||||
{
|
||||
return vstd::contains(resisted, s);
|
||||
});
|
||||
|
||||
for(auto s : resisted)
|
||||
{
|
||||
BattleSpellCast::CustomEffect effect;
|
||||
effect.effect = 78;
|
||||
effect.stack = s->ID;
|
||||
sc.customEffects.push_back(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DefaultSpellMechanics::prepareBattleCast(const BattleSpellCastParameters& parameters, BattleSpellCast& sc) const
|
||||
{
|
||||
sc.side = parameters.casterSide;
|
||||
sc.id = owner->id;
|
||||
sc.skill = parameters.spellLvl;
|
||||
sc.tile = parameters.getFirstDestinationHex();
|
||||
sc.dmgToDisplay = 0;
|
||||
sc.castByHero = parameters.mode == ECastingMode::HERO_CASTING;
|
||||
sc.casterStack = (parameters.casterStack ? parameters.casterStack->ID : -1);
|
||||
sc.manaGained = 0;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,9 @@ class StacksInjured;
|
||||
struct SpellCastContext
|
||||
{
|
||||
SpellCastContext(std::vector<const CStack *> & attackedCres, BattleSpellCast & sc, StacksInjured & si):
|
||||
attackedCres(attackedCres), sc(sc), si(si){};
|
||||
attackedCres(attackedCres), sc(sc), si(si)
|
||||
{
|
||||
};
|
||||
std::vector<const CStack *> & attackedCres;
|
||||
BattleSpellCast & sc;
|
||||
StacksInjured & si;
|
||||
@ -40,26 +42,25 @@ public:
|
||||
std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const override;
|
||||
std::set<const CStack *> getAffectedStacks(SpellTargetingContext & ctx) const override;
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const override;
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
|
||||
|
||||
virtual void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override;
|
||||
bool adventureCast(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const override final;
|
||||
void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const override;
|
||||
void battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const override final;
|
||||
|
||||
void battleLogSingleTarget(std::vector<std::string> & logLines, const BattleSpellCast * packet,
|
||||
const std::string & casterName, const CStack * attackedStack, bool & displayDamage) const override;
|
||||
protected:
|
||||
virtual void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const;
|
||||
|
||||
virtual int calculateDuration(const CGHeroInstance * caster, int usedSpellPower) const;
|
||||
|
||||
///calculate healed HP for all spells casted by hero
|
||||
ui32 calculateHealedHP(const CGHeroInstance * caster, const CStack * stack, const CStack * sacrificedStack) const;
|
||||
virtual void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const;
|
||||
|
||||
///actual adventure cast implementation
|
||||
virtual ESpellCastResult applyAdventureEffects(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const;
|
||||
|
||||
void doDispell(BattleInfo * battle, const BattleSpellCast * packet, const CSelector & selector) const;
|
||||
private:
|
||||
void castMagicMirror(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const;
|
||||
void handleResistance(const SpellCastEnvironment * env, std::vector<const CStack*> & attackedCres, BattleSpellCast & sc) const;
|
||||
void prepareBattleCast(const BattleSpellCastParameters & parameters, BattleSpellCast & sc) const;
|
||||
};
|
||||
|
@ -23,10 +23,11 @@
|
||||
#include "../CModHandler.h"
|
||||
#include "../StringConstants.h"
|
||||
|
||||
#include "../mapObjects/CGHeroInstance.h"
|
||||
#include "../BattleState.h"
|
||||
#include "../CBattleCallback.h"
|
||||
#include "../CGameState.h"
|
||||
#include "../CGameState.h" //todo: remove
|
||||
|
||||
#include "../NetPacks.h" //todo: remove
|
||||
|
||||
#include "ISpellMechanics.h"
|
||||
|
||||
@ -71,13 +72,6 @@ namespace SpellConfig
|
||||
};
|
||||
}
|
||||
|
||||
BattleSpellCastParameters::BattleSpellCastParameters(const BattleInfo* cb)
|
||||
: spellLvl(0), destination(BattleHex::INVALID), casterSide(0),casterColor(PlayerColor::CANNOT_DETERMINE),casterHero(nullptr), secHero(nullptr),
|
||||
usedSpellPower(0),mode(ECastingMode::HERO_CASTING), casterStack(nullptr), selectedStack(nullptr), cb(cb)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///CSpell::LevelInfo
|
||||
CSpell::LevelInfo::LevelInfo()
|
||||
:description(""),cost(0),power(0),AIValue(0),smartTarget(true), clearTarget(false), clearAffected(false), range("0")
|
||||
@ -121,9 +115,13 @@ bool CSpell::adventureCast(const SpellCastEnvironment * env, AdventureSpellCastP
|
||||
}
|
||||
|
||||
void CSpell::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
|
||||
{
|
||||
{
|
||||
assert(env);
|
||||
|
||||
if(parameters.destinations.size()<1)
|
||||
{
|
||||
env->complain("Spell must have at least one destination");
|
||||
return;
|
||||
}
|
||||
mechanics->battleCast(env, parameters);
|
||||
}
|
||||
|
||||
@ -140,52 +138,15 @@ const CSpell::LevelInfo & CSpell::getLevelInfo(const int level) const
|
||||
|
||||
ui32 CSpell::calculateDamage(const ISpellCaster * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const
|
||||
{
|
||||
ui32 ret = 0; //value to return
|
||||
|
||||
//check if spell really does damage - if not, return 0
|
||||
if(!isDamageSpell())
|
||||
return 0;
|
||||
|
||||
ret = usedSpellPower * power;
|
||||
ret += getPower(spellSchoolLevel);
|
||||
|
||||
//affected creature-specific part
|
||||
if(nullptr != affectedCreature)
|
||||
{
|
||||
//applying protections - when spell has more then one elements, only one protection should be applied (I think)
|
||||
forEachSchool([&](const SpellSchoolInfo & cnf, bool & stop)
|
||||
{
|
||||
if(affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, (ui8)cnf.id))
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, (ui8)cnf.id);
|
||||
ret /= 100;
|
||||
stop = true;//only bonus from one school is used
|
||||
}
|
||||
});
|
||||
|
||||
//general spell dmg reduction
|
||||
if(affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, -1))
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, -1);
|
||||
ret /= 100;
|
||||
}
|
||||
|
||||
//dmg increasing
|
||||
if(affectedCreature->hasBonusOfType(Bonus::MORE_DAMAGE_FROM_SPELL, id))
|
||||
{
|
||||
ret *= 100 + affectedCreature->valOfBonuses(Bonus::MORE_DAMAGE_FROM_SPELL, id.toEnum());
|
||||
ret /= 100;
|
||||
}
|
||||
}
|
||||
|
||||
if(nullptr != caster) //todo: make sure that caster always present
|
||||
ret = caster->getSpellBonus(this, ret, affectedCreature);
|
||||
return ret;
|
||||
return adjustRawDamage(caster, affectedCreature, calculateRawEffectValue(spellSchoolLevel, usedSpellPower));
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const
|
||||
{
|
||||
return mechanics->canBeCasted(cb, player);
|
||||
return mechanics->canBeCast(cb, player);
|
||||
}
|
||||
|
||||
std::vector<BattleHex> CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool *outDroppedHexes) const
|
||||
@ -193,7 +154,7 @@ std::vector<BattleHex> CSpell::rangeInHexes(BattleHex centralHex, ui8 schoolLvl,
|
||||
return mechanics->rangeInHexes(centralHex,schoolLvl,side,outDroppedHexes);
|
||||
}
|
||||
|
||||
std::set<const CStack *> CSpell::getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, PlayerColor casterColor, int spellLvl, BattleHex destination, const CGHeroInstance * caster) const
|
||||
std::set<const CStack *> CSpell::getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, PlayerColor casterColor, int spellLvl, BattleHex destination, const ISpellCaster * caster) const
|
||||
{
|
||||
ISpellMechanics::SpellTargetingContext ctx(this, cb,mode,casterColor,spellLvl,destination);
|
||||
|
||||
@ -217,12 +178,6 @@ CSpell::ETargetType CSpell::getTargetType() const
|
||||
return targetType;
|
||||
}
|
||||
|
||||
CSpell::TargetInfo CSpell::getTargetInfo(const int level) const
|
||||
{
|
||||
TargetInfo info(this, level);
|
||||
return info;
|
||||
}
|
||||
|
||||
void CSpell::forEachSchool(const std::function<void(const SpellSchoolInfo &, bool &)>& cb) const
|
||||
{
|
||||
bool stop = false;
|
||||
@ -351,7 +306,7 @@ void CSpell::getEffects(std::vector<Bonus> & lst, const int level) const
|
||||
}
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const CGHeroInstance * caster, ECastingMode::ECastingMode mode, BattleHex destination) const
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const
|
||||
{
|
||||
// Get all stacks at destination hex. only alive if not rising spell
|
||||
TStacks stacks = cb->battleGetStacksIf([=](const CStack * s){
|
||||
@ -402,7 +357,48 @@ ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallbac
|
||||
return ESpellCastProblem::OK;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj) const
|
||||
int CSpell::adjustRawDamage(const ISpellCaster * caster, const CStack * affectedCreature, int rawDamage) const
|
||||
{
|
||||
int ret = rawDamage;
|
||||
//affected creature-specific part
|
||||
if(nullptr != affectedCreature)
|
||||
{
|
||||
//applying protections - when spell has more then one elements, only one protection should be applied (I think)
|
||||
forEachSchool([&](const SpellSchoolInfo & cnf, bool & stop)
|
||||
{
|
||||
if(affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, (ui8)cnf.id))
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, (ui8)cnf.id);
|
||||
ret /= 100;
|
||||
stop = true;//only bonus from one school is used
|
||||
}
|
||||
});
|
||||
|
||||
//general spell dmg reduction
|
||||
if(affectedCreature->hasBonusOfType(Bonus::SPELL_DAMAGE_REDUCTION, -1))
|
||||
{
|
||||
ret *= affectedCreature->valOfBonuses(Bonus::SPELL_DAMAGE_REDUCTION, -1);
|
||||
ret /= 100;
|
||||
}
|
||||
|
||||
//dmg increasing
|
||||
if(affectedCreature->hasBonusOfType(Bonus::MORE_DAMAGE_FROM_SPELL, id))
|
||||
{
|
||||
ret *= 100 + affectedCreature->valOfBonuses(Bonus::MORE_DAMAGE_FROM_SPELL, id.toEnum());
|
||||
ret /= 100;
|
||||
}
|
||||
}
|
||||
if(caster != nullptr)
|
||||
ret = caster->getSpellBonus(this, ret, affectedCreature);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CSpell::calculateRawEffectValue(int effectLevel, int effectPower) const
|
||||
{
|
||||
return effectPower * power + getPower(effectLevel);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::internalIsImmune(const ISpellCaster * caster, const CStack *obj) const
|
||||
{
|
||||
//todo: use new bonus API
|
||||
//1. Check absolute limiters
|
||||
@ -419,25 +415,46 @@ ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj)
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
|
||||
//spell-based spell immunity (only ANTIMAGIC in OH3) is treated as absolute
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "type_" << Bonus::LEVEL_SPELL_IMMUNITY << "source_" << Bonus::SPELL_EFFECT;
|
||||
|
||||
TBonusListPtr levelImmunitiesFromSpell = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY).And(Selector::sourceType(Bonus::SPELL_EFFECT)), cachingStr.str());
|
||||
|
||||
if(levelImmunitiesFromSpell->size() > 0 && levelImmunitiesFromSpell->totalValue() >= level && level)
|
||||
{
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
//spell-based spell immunity (only ANTIMAGIC in OH3) is treated as absolute
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "type_" << Bonus::LEVEL_SPELL_IMMUNITY << "source_" << Bonus::SPELL_EFFECT;
|
||||
|
||||
TBonusListPtr levelImmunitiesFromSpell = obj->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY).And(Selector::sourceType(Bonus::SPELL_EFFECT)), cachingStr.str());
|
||||
|
||||
if(levelImmunitiesFromSpell->size() > 0 && levelImmunitiesFromSpell->totalValue() >= level && level)
|
||||
{
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
}
|
||||
{
|
||||
//SPELL_IMMUNITY absolute case
|
||||
std::stringstream cachingStr;
|
||||
cachingStr << "type_" << Bonus::SPELL_IMMUNITY << "subtype_" << id.toEnum() << "addInfo_1";
|
||||
if(obj->hasBonus(Selector::typeSubtypeInfo(Bonus::SPELL_IMMUNITY, id.toEnum(), 1), cachingStr.str()))
|
||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||
}
|
||||
|
||||
//check receptivity
|
||||
if (isPositive() && obj->hasBonusOfType(Bonus::RECEPTIVE)) //accept all positive spells
|
||||
return ESpellCastProblem::OK;
|
||||
|
||||
//3. Check negation
|
||||
//FIXME: Orb of vulnerability mechanics is not such trivial
|
||||
if(obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES)) //Orb of vulnerability
|
||||
//Orb of vulnerability
|
||||
//FIXME: Orb of vulnerability mechanics is not such trivial (issue 1791)
|
||||
const bool battleWideNegation = obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES, 0);
|
||||
const bool heroNegation = obj->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES, 1);
|
||||
//anyone can cast on artifact holder`s stacks
|
||||
if(heroNegation)
|
||||
return ESpellCastProblem::NOT_DECIDED;
|
||||
//this stack is from other player
|
||||
//todo: check that caster is always present (not trivial is this case)
|
||||
//todo: NEGATE_ALL_NATURAL_IMMUNITIES special cases: dispell, chain lightning
|
||||
else if(battleWideNegation && caster)
|
||||
{
|
||||
if(obj->owner != caster->getOwner())
|
||||
return ESpellCastProblem::NOT_DECIDED;
|
||||
}
|
||||
|
||||
//4. Check negatable limit
|
||||
for(auto b : limiters)
|
||||
@ -491,7 +508,7 @@ ESpellCastProblem::ESpellCastProblem CSpell::isImmuneBy(const IBonusBearer* obj)
|
||||
return ESpellCastProblem::NOT_DECIDED;
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
|
||||
ESpellCastProblem::ESpellCastProblem CSpell::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
|
||||
{
|
||||
const auto immuneResult = mechanics->isImmuneByStack(caster,obj);
|
||||
|
||||
|
@ -30,6 +30,9 @@ struct BattleSpellCast;
|
||||
class CGameInfoCallback;
|
||||
class CRandomGenerator;
|
||||
class CMap;
|
||||
struct AdventureSpellCastParameters;
|
||||
struct BattleSpellCastParameters;
|
||||
class SpellCastEnvironment;
|
||||
|
||||
struct SpellSchoolInfo
|
||||
{
|
||||
@ -41,45 +44,6 @@ struct SpellSchoolInfo
|
||||
Bonus::BonusType knoledgeBonus;
|
||||
};
|
||||
|
||||
///callback to be provided by server
|
||||
class DLL_LINKAGE SpellCastEnvironment
|
||||
{
|
||||
public:
|
||||
virtual ~SpellCastEnvironment(){};
|
||||
virtual void sendAndApply(CPackForClient * info) const = 0;
|
||||
|
||||
virtual CRandomGenerator & getRandomGenerator() const = 0;
|
||||
virtual void complain(const std::string & problem) const = 0;
|
||||
|
||||
virtual const CMap * getMap() const = 0;
|
||||
virtual const CGameInfoCallback * getCb() const = 0;
|
||||
|
||||
virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) const =0; //TODO: remove
|
||||
};
|
||||
|
||||
///helper struct
|
||||
struct DLL_LINKAGE BattleSpellCastParameters
|
||||
{
|
||||
public:
|
||||
BattleSpellCastParameters(const BattleInfo * cb);
|
||||
int spellLvl;
|
||||
BattleHex destination;
|
||||
ui8 casterSide;
|
||||
PlayerColor casterColor;
|
||||
const CGHeroInstance * casterHero; //deprecated
|
||||
const CGHeroInstance * secHero;
|
||||
int usedSpellPower;
|
||||
ECastingMode::ECastingMode mode;
|
||||
const CStack * casterStack;
|
||||
const CStack * selectedStack;
|
||||
const BattleInfo * cb;
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE AdventureSpellCastParameters
|
||||
{
|
||||
const CGHeroInstance * caster;
|
||||
int3 pos;
|
||||
};
|
||||
|
||||
enum class VerticalPosition : ui8{TOP, CENTER, BOTTOM};
|
||||
|
||||
@ -136,10 +100,10 @@ public:
|
||||
///displayed on caster.
|
||||
TAnimationQueue cast;
|
||||
|
||||
///displayed on target hex. If spell was casted with no target selection displayed on entire battlefield (f.e. ARMAGEDDON)
|
||||
///displayed on target hex. If spell was cast with no target selection displayed on entire battlefield (f.e. ARMAGEDDON)
|
||||
TAnimationQueue hit;
|
||||
|
||||
///displayed "between" caster and (first) target. Ignored if spell was casted with no target selection.
|
||||
///displayed "between" caster and (first) target. Ignored if spell was cast with no target selection.
|
||||
///use selectProjectile to access
|
||||
std::vector<ProjectileInfo> projectile;
|
||||
|
||||
@ -188,7 +152,7 @@ public:
|
||||
enum ETargetType {NO_TARGET, CREATURE, OBSTACLE, LOCATION};
|
||||
enum ESpellPositiveness {NEGATIVE = -1, NEUTRAL = 0, POSITIVE = 1};
|
||||
|
||||
struct TargetInfo
|
||||
struct DLL_LINKAGE TargetInfo
|
||||
{
|
||||
ETargetType type;
|
||||
bool smart;
|
||||
@ -231,8 +195,6 @@ public:
|
||||
std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr ) const; //convert range to specific hexes; last optional out parameter is set to true, if spell would cover unavailable hexes (that are not included in ret)
|
||||
ETargetType getTargetType() const; //deprecated
|
||||
|
||||
CSpell::TargetInfo getTargetInfo(const int level) const;
|
||||
|
||||
bool isCombatSpell() const;
|
||||
bool isAdventureSpell() const;
|
||||
bool isCreatureAbility() const;
|
||||
@ -251,17 +213,12 @@ public:
|
||||
bool hasEffects() const;
|
||||
void getEffects(std::vector<Bonus> &lst, const int level) const;
|
||||
|
||||
///checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into account general problems such as not having spellbook or mana points etc.
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneAt(const CBattleInfoCallback * cb, const CGHeroInstance * caster, ECastingMode::ECastingMode mode, BattleHex destination) const;
|
||||
|
||||
//internal, for use only by Mechanics classes
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneBy(const IBonusBearer *obj) const;
|
||||
|
||||
///calculate spell damage on stack taking caster`s secondary skills and affectedCreature`s bonuses into account
|
||||
ui32 calculateDamage(const ISpellCaster * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const;
|
||||
|
||||
///selects from allStacks actually affected stacks
|
||||
std::set<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, PlayerColor casterColor, int spellLvl, BattleHex destination, const CGHeroInstance * caster = nullptr) const;
|
||||
std::set<const CStack *> getAffectedStacks(const CBattleInfoCallback * cb, ECastingMode::ECastingMode mode, PlayerColor casterColor, int spellLvl, BattleHex destination, const ISpellCaster * caster) const;
|
||||
|
||||
si32 getCost(const int skillLevel) const;
|
||||
|
||||
@ -310,10 +267,13 @@ public:
|
||||
///internal interface (for callbacks)
|
||||
|
||||
///Checks general but spell-specific problems for all casting modes. Use only during battle.
|
||||
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const;
|
||||
ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const;
|
||||
|
||||
///checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into account general problems such as not having spellbook or mana points etc.
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const;
|
||||
|
||||
///checks for creature immunity / anything that prevent casting *at given target* - doesn't take into account general problems such as not having spellbook or mana points etc.
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const;
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const;
|
||||
public:
|
||||
///Server logic. Has write access to GameState via packets.
|
||||
///May be executed on client side by (future) non-cheat-proof scripts.
|
||||
@ -328,11 +288,17 @@ public:
|
||||
///implementation of BattleSpellCast applying
|
||||
void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const;
|
||||
|
||||
public:
|
||||
///Client logic.
|
||||
|
||||
public://Client logic.
|
||||
void prepareBattleLog(const CBattleInfoCallback * cb, const BattleSpellCast * packet, std::vector<std::string> & logLines) const;
|
||||
|
||||
public://internal, for use only by Mechanics classes
|
||||
///applies caster`s secondary skills and affectedCreature`s to raw damage
|
||||
int adjustRawDamage(const ISpellCaster * caster, const CStack * affectedCreature, int rawDamage) const;
|
||||
///returns raw damage or healed HP
|
||||
int calculateRawEffectValue(int effectLevel, int effectPower) const;
|
||||
///generic immunity calculation
|
||||
ESpellCastProblem::ESpellCastProblem internalIsImmune(const ISpellCaster * caster, const CStack *obj) const;
|
||||
|
||||
private:
|
||||
void setIsOffensive(const bool val);
|
||||
void setIsRising(const bool val);
|
||||
|
@ -16,17 +16,18 @@
|
||||
#include "../BattleState.h"
|
||||
|
||||
///AcidBreathDamageMechanics
|
||||
void AcidBreathDamageMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void AcidBreathDamageMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
//todo: this should be effectValue
|
||||
//calculating dmg to display
|
||||
ctx.sc.dmgToDisplay = parameters.usedSpellPower;
|
||||
ctx.sc.dmgToDisplay = parameters.effectPower;
|
||||
|
||||
for(auto & attackedCre : ctx.attackedCres) //no immunities
|
||||
{
|
||||
BattleStackAttacked bsa;
|
||||
bsa.flags |= BattleStackAttacked::SPELL_EFFECT;
|
||||
bsa.spellID = owner->id;
|
||||
bsa.damageAmount = parameters.usedSpellPower; //damage times the number of attackers
|
||||
bsa.damageAmount = parameters.effectPower; //damage times the number of attackers
|
||||
bsa.stackAttacked = (attackedCre)->ID;
|
||||
bsa.attackerID = -1;
|
||||
(attackedCre)->prepareAttacked(bsa, env->getRandomGenerator());
|
||||
@ -35,10 +36,10 @@ void AcidBreathDamageMechanics::applyBattleEffects(const SpellCastEnvironment *
|
||||
}
|
||||
|
||||
///DeathStareMechanics
|
||||
void DeathStareMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
void DeathStareMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
|
||||
{
|
||||
//calculating dmg to display
|
||||
ctx.sc.dmgToDisplay = parameters.usedSpellPower;
|
||||
ctx.sc.dmgToDisplay = parameters.effectPower;
|
||||
if(!ctx.attackedCres.empty())
|
||||
vstd::amin(ctx.sc.dmgToDisplay, (*ctx.attackedCres.begin())->count); //stack is already reduced after attack
|
||||
|
||||
@ -47,7 +48,7 @@ void DeathStareMechanics::applyBattleEffects(const SpellCastEnvironment * env, B
|
||||
BattleStackAttacked bsa;
|
||||
bsa.flags |= BattleStackAttacked::SPELL_EFFECT;
|
||||
bsa.spellID = owner->id;
|
||||
bsa.damageAmount = parameters.usedSpellPower * (attackedCre)->valOfBonuses(Bonus::STACK_HEALTH);
|
||||
bsa.damageAmount = parameters.effectPower * (attackedCre)->valOfBonuses(Bonus::STACK_HEALTH);//todo: move here all DeathStare calculation
|
||||
bsa.stackAttacked = (attackedCre)->ID;
|
||||
bsa.attackerID = -1;
|
||||
(attackedCre)->prepareAttacked(bsa, env->getRandomGenerator());
|
||||
@ -63,7 +64,7 @@ void DispellHelpfulMechanics::applyBattle(BattleInfo * battle, const BattleSpell
|
||||
doDispell(battle, packet, Selector::positiveSpellEffects);
|
||||
}
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem DispellHelpfulMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
|
||||
ESpellCastProblem::ESpellCastProblem DispellHelpfulMechanics::isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const
|
||||
{
|
||||
TBonusListPtr spellBon = obj->getSpellBonuses();
|
||||
bool hasPositiveSpell = false;
|
||||
|
@ -18,7 +18,7 @@ class DLL_LINKAGE AcidBreathDamageMechanics : public DefaultSpellMechanics
|
||||
public:
|
||||
AcidBreathDamageMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE DeathStareMechanics : public DefaultSpellMechanics
|
||||
@ -26,7 +26,7 @@ class DLL_LINKAGE DeathStareMechanics : public DefaultSpellMechanics
|
||||
public:
|
||||
DeathStareMechanics(CSpell * s): DefaultSpellMechanics(s){};
|
||||
protected:
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
void applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE DispellHelpfulMechanics : public DefaultSpellMechanics
|
||||
@ -36,5 +36,5 @@ public:
|
||||
|
||||
void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final;
|
||||
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;
|
||||
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const override;
|
||||
};
|
||||
|
@ -11,12 +11,71 @@
|
||||
#include "StdInc.h"
|
||||
#include "ISpellMechanics.h"
|
||||
|
||||
#include "../BattleState.h"
|
||||
#include "../NetPacks.h"
|
||||
|
||||
#include "CDefaultSpellMechanics.h"
|
||||
|
||||
#include "AdventureSpellMechanics.h"
|
||||
#include "BattleSpellMechanics.h"
|
||||
#include "CreatureSpellMechanics.h"
|
||||
|
||||
BattleSpellCastParameters::Destination::Destination(const CStack * destination):
|
||||
stackValue(destination),
|
||||
hexValue(destination->position)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BattleSpellCastParameters::Destination::Destination(const BattleHex & destination):
|
||||
stackValue(nullptr),
|
||||
hexValue(destination)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BattleSpellCastParameters::BattleSpellCastParameters(const BattleInfo * cb, const ISpellCaster * caster, const CSpell * spell)
|
||||
: cb(cb), caster(caster), casterColor(caster->getOwner()), casterSide(cb->whatSide(casterColor)),
|
||||
casterHero(nullptr),
|
||||
mode(ECastingMode::HERO_CASTING), casterStack(nullptr), selectedStack(nullptr),
|
||||
spellLvl(-1), effectLevel(-1), effectPower(0), enchantPower(0), effectValue(0)
|
||||
{
|
||||
casterStack = dynamic_cast<const CStack *>(caster);
|
||||
casterHero = dynamic_cast<const CGHeroInstance *>(caster);
|
||||
prepare(spell);
|
||||
}
|
||||
|
||||
void BattleSpellCastParameters::aimToHex(const BattleHex& destination)
|
||||
{
|
||||
destinations.push_back(Destination(destination));
|
||||
}
|
||||
|
||||
void BattleSpellCastParameters::aimToStack(const CStack * destination)
|
||||
{
|
||||
destinations.push_back(Destination(destination));
|
||||
}
|
||||
|
||||
|
||||
BattleHex BattleSpellCastParameters::getFirstDestinationHex() const
|
||||
{
|
||||
return destinations.at(0).hexValue;
|
||||
}
|
||||
|
||||
void BattleSpellCastParameters::prepare(const CSpell * spell)
|
||||
{
|
||||
spellLvl = caster->getSpellSchoolLevel(spell);
|
||||
effectLevel = caster->getEffectLevel(spell);
|
||||
effectPower = caster->getEffectPower(spell);
|
||||
effectValue = caster->getEffectValue(spell);
|
||||
enchantPower = caster->getEnchantPower(spell);
|
||||
|
||||
vstd::amax(spellLvl, 0);
|
||||
vstd::amax(effectLevel, 0);
|
||||
vstd::amax(enchantPower, 0);
|
||||
vstd::amax(enchantPower, 0);
|
||||
vstd::amax(effectValue, 0);
|
||||
}
|
||||
|
||||
///ISpellMechanics
|
||||
ISpellMechanics::ISpellMechanics(CSpell * s):
|
||||
owner(s)
|
||||
|
@ -12,8 +12,75 @@
|
||||
|
||||
#include "CSpellHandler.h"
|
||||
#include "../BattleHex.h"
|
||||
#include "../BattleState.h"
|
||||
#include "../NetPacks.h"
|
||||
|
||||
|
||||
///callback to be provided by server
|
||||
class DLL_LINKAGE SpellCastEnvironment
|
||||
{
|
||||
public:
|
||||
virtual ~SpellCastEnvironment(){};
|
||||
virtual void sendAndApply(CPackForClient * info) const = 0;
|
||||
|
||||
virtual CRandomGenerator & getRandomGenerator() const = 0;
|
||||
virtual void complain(const std::string & problem) const = 0;
|
||||
|
||||
virtual const CMap * getMap() const = 0;
|
||||
virtual const CGameInfoCallback * getCb() const = 0;
|
||||
|
||||
virtual bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, PlayerColor asker = PlayerColor::NEUTRAL) const =0; //TODO: remove
|
||||
};
|
||||
|
||||
///all parameters of particular cast event
|
||||
struct DLL_LINKAGE BattleSpellCastParameters
|
||||
{
|
||||
public:
|
||||
///Single spell destination.
|
||||
/// (assumes that anything but battle stack can share same hex)
|
||||
struct DLL_LINKAGE Destination
|
||||
{
|
||||
explicit Destination(const CStack * destination);
|
||||
explicit Destination(const BattleHex & destination);
|
||||
|
||||
const CStack * stackValue;
|
||||
const BattleHex hexValue;
|
||||
};
|
||||
|
||||
BattleSpellCastParameters(const BattleInfo * cb, const ISpellCaster * caster, const CSpell * spell);
|
||||
void aimToHex(const BattleHex & destination);
|
||||
void aimToStack(const CStack * destination);
|
||||
BattleHex getFirstDestinationHex() const;
|
||||
|
||||
const BattleInfo * cb;
|
||||
const ISpellCaster * caster;
|
||||
const PlayerColor casterColor;
|
||||
const ui8 casterSide;
|
||||
|
||||
std::vector<Destination> destinations;
|
||||
|
||||
const CGHeroInstance * casterHero; //deprecated
|
||||
ECastingMode::ECastingMode mode;
|
||||
const CStack * casterStack; //deprecated
|
||||
const CStack * selectedStack;//deprecated
|
||||
|
||||
///spell school level
|
||||
int spellLvl;
|
||||
///spell school level to use for effects
|
||||
int effectLevel;
|
||||
///actual spell-power affecting effect values
|
||||
int effectPower;
|
||||
///actual spell-power affecting effect duration
|
||||
int enchantPower;
|
||||
///for Archangel-like casting
|
||||
int effectValue;
|
||||
private:
|
||||
void prepare(const CSpell * spell);
|
||||
};
|
||||
|
||||
struct DLL_LINKAGE AdventureSpellCastParameters
|
||||
{
|
||||
const CGHeroInstance * caster;
|
||||
int3 pos;
|
||||
};
|
||||
|
||||
class DLL_LINKAGE ISpellMechanics
|
||||
{
|
||||
@ -39,9 +106,9 @@ public:
|
||||
virtual std::vector<BattleHex> rangeInHexes(BattleHex centralHex, ui8 schoolLvl, ui8 side, bool * outDroppedHexes = nullptr) const = 0;
|
||||
virtual std::set<const CStack *> getAffectedStacks(SpellTargetingContext & ctx) const = 0;
|
||||
|
||||
virtual ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const = 0;
|
||||
virtual ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const = 0;
|
||||
|
||||
virtual ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const = 0;
|
||||
virtual ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const = 0;
|
||||
|
||||
virtual void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const = 0;
|
||||
virtual bool adventureCast(const SpellCastEnvironment * env, AdventureSpellCastParameters & parameters) const = 0;
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
class CSpell;
|
||||
class CStack;
|
||||
class PlayerColor;
|
||||
|
||||
class DLL_LINKAGE ISpellCaster
|
||||
{
|
||||
@ -26,7 +27,22 @@ public:
|
||||
/// returns level on which given spell would be cast by this(0 - none, 1 - basic etc);
|
||||
/// caster may not know this spell at all
|
||||
/// optionally returns number of selected school by arg - 0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic
|
||||
virtual ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = nullptr) const = 0;
|
||||
|
||||
virtual ui8 getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool = nullptr) const = 0;
|
||||
|
||||
///applying sorcery secondary skill etc
|
||||
virtual ui32 getSpellBonus(const CSpell * spell, ui32 base, const CStack * affectedStack) const = 0;
|
||||
|
||||
///default spell school level for effect calculation
|
||||
virtual int getEffectLevel(const CSpell * spell) const = 0;
|
||||
|
||||
///default spell-power for damage/heal calculation
|
||||
virtual int getEffectPower(const CSpell * spell) const = 0;
|
||||
|
||||
///default spell-power for timed effects duration
|
||||
virtual int getEnchantPower(const CSpell * spell) const = 0;
|
||||
|
||||
///damage/heal override(ignores spell configuration, effect level and effect power)
|
||||
virtual int getEffectValue(const CSpell * spell) const = 0;
|
||||
|
||||
virtual const PlayerColor getOwner() const = 0;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user