mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-02 00:10:22 +02:00
Merge remote-tracking branch 'vcmi/beta' into develop
This commit is contained in:
commit
695a51d8c8
@ -60,6 +60,12 @@ void CBattleAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::share
|
||||
movesSkippedByDefense = 0;
|
||||
}
|
||||
|
||||
void CBattleAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB, AutocombatPreferences autocombatPreferences)
|
||||
{
|
||||
initBattleInterface(ENV, CB);
|
||||
autobattlePreferences = autocombatPreferences;
|
||||
}
|
||||
|
||||
BattleAction CBattleAI::useHealingTent(const CStack *stack)
|
||||
{
|
||||
auto healingTargets = cb->battleGetStacks(CBattleInfoEssentials::ONLY_MINE);
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
~CBattleAI();
|
||||
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) override;
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB, AutocombatPreferences autocombatPreferences) override;
|
||||
|
||||
void activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
void yourTacticPhase(int distance) override;
|
||||
@ -94,4 +95,5 @@ public:
|
||||
//void battleTriggerEffect(const BattleTriggerEffect & bte) override;
|
||||
//void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
//void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
AutocombatPreferences autobattlePreferences = AutocombatPreferences();
|
||||
};
|
||||
|
@ -48,6 +48,11 @@ void CStupidAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::share
|
||||
CB->unlockGsWhenWaiting = false;
|
||||
}
|
||||
|
||||
void CStupidAI::initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB, AutocombatPreferences autocombatPreferences)
|
||||
{
|
||||
initBattleInterface(ENV, CB);
|
||||
}
|
||||
|
||||
void CStupidAI::actionFinished(const BattleAction &action)
|
||||
{
|
||||
print("actionFinished called");
|
||||
|
@ -29,6 +29,7 @@ public:
|
||||
~CStupidAI();
|
||||
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) override;
|
||||
void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB, AutocombatPreferences autocombatPreferences) override;
|
||||
void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero
|
||||
void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero
|
||||
void activeStack(const CStack * stack) override; //called when it's turn of that stack
|
||||
|
8
Mods/vcmi/Sprites/buttons/backpack.json
Normal file
8
Mods/vcmi/Sprites/buttons/backpack.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"basepath" : "buttons/",
|
||||
"images" :
|
||||
[
|
||||
{ "frame" : 0, "file" : "backpackNormal.png"},
|
||||
{ "frame" : 1, "file" : "backpackPressed.png"}
|
||||
]
|
||||
}
|
BIN
Mods/vcmi/Sprites/buttons/backpackNormal.png
Normal file
BIN
Mods/vcmi/Sprites/buttons/backpackNormal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
BIN
Mods/vcmi/Sprites/buttons/backpackPressed.png
Normal file
BIN
Mods/vcmi/Sprites/buttons/backpackPressed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
BIN
Mods/vcmi/Sprites/heroWindow/artifactSlotEmpty.png
Normal file
BIN
Mods/vcmi/Sprites/heroWindow/artifactSlotEmpty.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 133 B |
@ -172,6 +172,8 @@
|
||||
|
||||
"vcmi.heroWindow.openCommander.hover" : "Open commander info window",
|
||||
"vcmi.heroWindow.openCommander.help" : "Shows details about the commander of this hero",
|
||||
"vcmi.heroWindow.openBackpack.hover" : "Open artifact backpack window",
|
||||
"vcmi.heroWindow.openBackpack.help" : "Opens window that allows easier artifact backpack management",
|
||||
|
||||
"vcmi.commanderWindow.artifactMessage" : "Do you want to return this artifact to the hero?",
|
||||
|
||||
|
@ -172,6 +172,8 @@
|
||||
|
||||
"vcmi.heroWindow.openCommander.hover" : "Otwórz okno dowódcy",
|
||||
"vcmi.heroWindow.openCommander.help" : "Wyświetla informacje o dowódcy przynależącym do tego bohatera",
|
||||
"vcmi.heroWindow.openBackpack.hover" : "Otwórz okno sakwy",
|
||||
"vcmi.heroWindow.openBackpack.help" : "Otwiera okno pozwalające łatwiej zarządzać artefaktami w sakwie",
|
||||
|
||||
"vcmi.commanderWindow.artifactMessage" : "Czy chcesz zwrócić ten artefakt bohaterowi?",
|
||||
|
||||
|
@ -3,13 +3,13 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk 31
|
||||
compileSdk 33
|
||||
ndkVersion '25.2.9519653'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "is.xyz.vcmi"
|
||||
minSdk 19
|
||||
targetSdk 31
|
||||
targetSdk 33
|
||||
versionCode 1400
|
||||
versionName "1.4.0"
|
||||
setProperty("archivesBaseName", "vcmi")
|
||||
|
@ -493,9 +493,6 @@ void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero)
|
||||
adventureInt->onHeroChanged(hero);
|
||||
if (makingTurn && hero->tempOwner == playerID)
|
||||
adventureInt->onHeroChanged(hero);
|
||||
|
||||
for (auto window : GH.windows().findWindows<BattleWindow>())
|
||||
window->heroManaPointsChanged(hero);
|
||||
}
|
||||
void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
|
||||
{
|
||||
@ -684,7 +681,11 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
|
||||
if ((replayAllowed && useQuickCombat) || forceQuickCombat)
|
||||
{
|
||||
autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String());
|
||||
autofightingAI->initBattleInterface(env, cb);
|
||||
|
||||
AutocombatPreferences autocombatPreferences = AutocombatPreferences();
|
||||
autocombatPreferences.enableSpellsUsage = settings["battle"]["enableAutocombatSpells"].Bool();
|
||||
|
||||
autofightingAI->initBattleInterface(env, cb, autocombatPreferences);
|
||||
autofightingAI->battleStart(army1, army2, tile, hero1, hero2, side, false);
|
||||
isAutoFightOn = true;
|
||||
cb->registerBattleInterface(autofightingAI);
|
||||
@ -916,6 +917,12 @@ void CPlayerInterface::battleTriggerEffect (const BattleTriggerEffect & bte)
|
||||
|
||||
RETURN_IF_QUICK_COMBAT;
|
||||
battleInt->effectsController->battleTriggerEffect(bte);
|
||||
|
||||
if(bte.effect == vstd::to_underlying(BonusType::MANA_DRAIN))
|
||||
{
|
||||
const CGHeroInstance * manaDrainedHero = LOCPLINT->cb->getHero(ObjectInstanceID(bte.additionalInfo));
|
||||
battleInt->windowObject->heroManaPointsChanged(manaDrainedHero);
|
||||
}
|
||||
}
|
||||
void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged)
|
||||
{
|
||||
|
@ -17,7 +17,9 @@
|
||||
#include "mapView/mapHandler.h"
|
||||
#include "adventureMap/CInGameConsole.h"
|
||||
#include "battle/BattleInterface.h"
|
||||
#include "battle/BattleWindow.h"
|
||||
#include "gui/CGuiHandler.h"
|
||||
#include "gui/WindowHandler.h"
|
||||
#include "widgets/MiscWidgets.h"
|
||||
#include "CMT.h"
|
||||
#include "CServerHandler.h"
|
||||
@ -153,6 +155,9 @@ void ApplyClientNetPackVisitor::visitSetMana(SetMana & pack)
|
||||
{
|
||||
const CGHeroInstance *h = cl.getHero(pack.hid);
|
||||
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroManaPointsChanged, h);
|
||||
|
||||
for (auto window : GH.windows().findWindows<BattleWindow>())
|
||||
window->heroManaPointsChanged(h);
|
||||
}
|
||||
|
||||
void ApplyClientNetPackVisitor::visitSetMovePoints(SetMovePoints & pack)
|
||||
|
@ -215,7 +215,7 @@ std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActi
|
||||
return std::vector<PossiblePlayerBattleAction>(allActions);
|
||||
}
|
||||
|
||||
void BattleActionsController::reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context)
|
||||
void BattleActionsController::reorderPossibleActionsPriority(const CStack * stack, const CStack * targetStack)
|
||||
{
|
||||
if(owner.tacticsMode || possibleActions.empty()) return; //this function is not supposed to be called in tactics mode or before getPossibleActionsForStack
|
||||
|
||||
@ -229,10 +229,17 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
|
||||
case PossiblePlayerBattleAction::NO_LOCATION:
|
||||
case PossiblePlayerBattleAction::FREE_LOCATION:
|
||||
case PossiblePlayerBattleAction::OBSTACLE:
|
||||
if(!stack->hasBonusOfType(BonusType::NO_SPELLCAST_BY_DEFAULT) && context == MouseHoveredHexContext::OCCUPIED_HEX)
|
||||
if(!stack->hasBonusOfType(BonusType::NO_SPELLCAST_BY_DEFAULT) && targetStack != nullptr)
|
||||
{
|
||||
PlayerColor stackOwner = owner.curInt->cb->battleGetOwner(targetStack);
|
||||
bool enemyTargetingPositiveSpellcast = item.spell().toSpell()->isPositive() && stackOwner != LOCPLINT->playerID;
|
||||
bool friendTargetingNegativeSpellcast = item.spell().toSpell()->isNegative() && stackOwner == LOCPLINT->playerID;
|
||||
|
||||
if(!enemyTargetingPositiveSpellcast && !friendTargetingNegativeSpellcast)
|
||||
return 1;
|
||||
else
|
||||
}
|
||||
return 100; //bottom priority
|
||||
|
||||
break;
|
||||
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
|
||||
return 2;
|
||||
@ -788,7 +795,7 @@ PossiblePlayerBattleAction BattleActionsController::selectAction(BattleHex targe
|
||||
|
||||
const CStack * targetStack = getStackForHex(targetHex);
|
||||
|
||||
reorderPossibleActionsPriority(owner.stacksController->getActiveStack(), targetStack ? MouseHoveredHexContext::OCCUPIED_HEX : MouseHoveredHexContext::UNOCCUPIED_HEX);
|
||||
reorderPossibleActionsPriority(owner.stacksController->getActiveStack(), targetStack);
|
||||
|
||||
for (PossiblePlayerBattleAction action : possibleActions)
|
||||
{
|
||||
@ -972,6 +979,11 @@ void BattleActionsController::activateStack()
|
||||
|
||||
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
|
||||
actionsToSelect.push_back(possibleActions.front());
|
||||
actionsToSelect.push_back(PossiblePlayerBattleAction::ATTACK);
|
||||
break;
|
||||
case PossiblePlayerBattleAction::ANY_LOCATION:
|
||||
actionsToSelect.push_back(possibleActions.front());
|
||||
actionsToSelect.push_back(PossiblePlayerBattleAction::ATTACK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -981,8 +993,18 @@ void BattleActionsController::activateStack()
|
||||
|
||||
void BattleActionsController::onHexRightClicked(BattleHex clickedHex)
|
||||
{
|
||||
if (spellcastingModeActive())
|
||||
auto spellcastActionPredicate = [](PossiblePlayerBattleAction & action)
|
||||
{
|
||||
return action.spellcast();
|
||||
};
|
||||
|
||||
bool isCurrentStackInSpellcastMode = std::all_of(possibleActions.begin(), possibleActions.end(), spellcastActionPredicate);
|
||||
|
||||
if (spellcastingModeActive() || isCurrentStackInSpellcastMode)
|
||||
{
|
||||
endCastingSpell();
|
||||
return;
|
||||
}
|
||||
|
||||
auto selectedStack = owner.curInt->cb->battleGetStackByPos(clickedHex, true);
|
||||
|
||||
@ -998,7 +1020,7 @@ void BattleActionsController::onHexRightClicked(BattleHex clickedHex)
|
||||
|
||||
bool BattleActionsController::spellcastingModeActive() const
|
||||
{
|
||||
return heroSpellToCast != nullptr;;
|
||||
return heroSpellToCast != nullptr;
|
||||
}
|
||||
|
||||
bool BattleActionsController::currentActionSpellcasting(BattleHex hoveredHex)
|
||||
|
@ -23,12 +23,6 @@ VCMI_LIB_NAMESPACE_END
|
||||
|
||||
class BattleInterface;
|
||||
|
||||
enum class MouseHoveredHexContext
|
||||
{
|
||||
UNOCCUPIED_HEX,
|
||||
OCCUPIED_HEX
|
||||
};
|
||||
|
||||
/// Class that controls actions that can be performed by player, e.g. moving stacks, attacking, etc
|
||||
/// As well as all relevant feedback for these actions in user interface
|
||||
class BattleActionsController
|
||||
@ -53,7 +47,7 @@ class BattleActionsController
|
||||
bool isCastingPossibleHere (const CSpell * spell, const CStack *shere, BattleHex myNumber);
|
||||
bool canStackMoveHere (const CStack *sactive, BattleHex MyNumber) const; //TODO: move to BattleState / callback
|
||||
std::vector<PossiblePlayerBattleAction> getPossibleActionsForStack (const CStack *stack) const; //called when stack gets its turn
|
||||
void reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context);
|
||||
void reorderPossibleActionsPriority(const CStack * stack, const CStack * targetStack);
|
||||
|
||||
bool actionIsLegal(PossiblePlayerBattleAction action, BattleHex hoveredHex);
|
||||
|
||||
|
@ -451,6 +451,10 @@ void BattleWindow::showAlternativeActionIcon(PossiblePlayerBattleAction action)
|
||||
iconName = variables["actionIconSpell"].String();
|
||||
break;
|
||||
|
||||
case PossiblePlayerBattleAction::ANY_LOCATION:
|
||||
iconName = variables["actionIconSpell"].String();
|
||||
break;
|
||||
|
||||
//TODO: figure out purpose of this icon
|
||||
//case PossiblePlayerBattleAction::???:
|
||||
//iconName = variables["actionIconWalk"].String();
|
||||
@ -500,7 +504,11 @@ void BattleWindow::bAutofightf()
|
||||
blockUI(true);
|
||||
|
||||
auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String());
|
||||
ai->initBattleInterface(owner.curInt->env, owner.curInt->cb);
|
||||
|
||||
AutocombatPreferences autocombatPreferences = AutocombatPreferences();
|
||||
autocombatPreferences.enableSpellsUsage = settings["battle"]["enableAutocombatSpells"].Bool();
|
||||
|
||||
ai->initBattleInterface(owner.curInt->env, owner.curInt->cb, autocombatPreferences);
|
||||
ai->battleStart(owner.army1, owner.army2, int3(0,0,0), owner.attackingHeroInstance, owner.defendingHeroInstance, owner.curInt->cb->battleGetMySide(), false);
|
||||
owner.curInt->autofightingAI = ai;
|
||||
owner.curInt->cb->registerBattleInterface(ai);
|
||||
|
@ -120,7 +120,7 @@ std::vector<EShortcut> ShortcutHandler::translateKeycode(SDL_Keycode key) const
|
||||
{SDLK_KP_MINUS, EShortcut::ADVENTURE_ZOOM_OUT },
|
||||
{SDLK_BACKSPACE, EShortcut::ADVENTURE_ZOOM_RESET },
|
||||
{SDLK_q, EShortcut::BATTLE_TOGGLE_QUEUE },
|
||||
{SDLK_c, EShortcut::BATTLE_USE_CREATURE_SPELL },
|
||||
{SDLK_f, EShortcut::BATTLE_USE_CREATURE_SPELL },
|
||||
{SDLK_s, EShortcut::BATTLE_SURRENDER },
|
||||
{SDLK_r, EShortcut::BATTLE_RETREAT },
|
||||
{SDLK_a, EShortcut::BATTLE_AUTOCOMBAT },
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "../gui/Shortcut.h"
|
||||
|
||||
#include "Buttons.h"
|
||||
#include "Images.h"
|
||||
#include "GameSettings.h"
|
||||
#include "IHandlerBase.h"
|
||||
#include "ObjectLists.h"
|
||||
@ -27,25 +28,37 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
||||
pos += position;
|
||||
setRedrawParent(true);
|
||||
|
||||
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
|
||||
auto visibleCapasityMax = HERO_BACKPACK_WINDOW_SLOT_LINES * HERO_BACKPACK_WINDOW_SLOT_COLUMNS;
|
||||
auto visibleCapacityMax = HERO_BACKPACK_WINDOW_SLOT_ROWS * HERO_BACKPACK_WINDOW_SLOT_COLUMNS;
|
||||
if(backpackCap >= 0)
|
||||
visibleCapasityMax = visibleCapasityMax > backpackCap ? backpackCap : visibleCapasityMax;
|
||||
visibleCapacityMax = visibleCapacityMax > backpackCap ? backpackCap : visibleCapacityMax;
|
||||
|
||||
backpack.resize(visibleCapasityMax);
|
||||
backpack.resize(visibleCapacityMax);
|
||||
size_t artPlaceIdx = 0;
|
||||
|
||||
const int slotSizeWithMargin = 46;
|
||||
|
||||
for(int i = 0; i < visibleCapacityMax; i++)
|
||||
{
|
||||
auto artifactSlotBackground = std::make_shared<CPicture>("heroWindow/artifactSlotEmpty",
|
||||
Point(slotSizeWithMargin * (i % HERO_BACKPACK_WINDOW_SLOT_COLUMNS), slotSizeWithMargin * (i / HERO_BACKPACK_WINDOW_SLOT_COLUMNS)));
|
||||
|
||||
backpackSlotsBackgrounds.emplace_back(artifactSlotBackground);
|
||||
}
|
||||
|
||||
for(auto & artPlace : backpack)
|
||||
{
|
||||
artPlace = std::make_shared<CHeroArtPlace>(
|
||||
Point(46 * (artPlaceIdx % HERO_BACKPACK_WINDOW_SLOT_COLUMNS), 46 * (artPlaceIdx / HERO_BACKPACK_WINDOW_SLOT_COLUMNS)));
|
||||
Point(slotSizeWithMargin * (artPlaceIdx % HERO_BACKPACK_WINDOW_SLOT_COLUMNS), slotSizeWithMargin * (artPlaceIdx / HERO_BACKPACK_WINDOW_SLOT_COLUMNS)));
|
||||
artPlace->setArtifact(nullptr);
|
||||
artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
|
||||
artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
|
||||
artPlaceIdx++;
|
||||
}
|
||||
|
||||
if(backpackCap < 0 || visibleCapasityMax < backpackCap)
|
||||
if(backpackCap < 0 || visibleCapacityMax < backpackCap)
|
||||
{
|
||||
auto onCreate = [](size_t index) -> std::shared_ptr<CIntObject>
|
||||
{
|
||||
@ -56,8 +69,8 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position)
|
||||
scrollBackpack(static_cast<int>(pos) * HERO_BACKPACK_WINDOW_SLOT_COLUMNS - backpackPos);
|
||||
};
|
||||
backpackListBox = std::make_shared<CListBoxWithCallback>(
|
||||
posMoved, onCreate, Point(0, 0), Point(0, 0), HERO_BACKPACK_WINDOW_SLOT_LINES, 0, 0, 1,
|
||||
Rect(HERO_BACKPACK_WINDOW_SLOT_COLUMNS * 46 + 10, 0, HERO_BACKPACK_WINDOW_SLOT_LINES * 46 - 5, 0));
|
||||
posMoved, onCreate, Point(0, 0), Point(0, 0), HERO_BACKPACK_WINDOW_SLOT_ROWS, 0, 0, 1,
|
||||
Rect(HERO_BACKPACK_WINDOW_SLOT_COLUMNS * slotSizeWithMargin + 10, 0, HERO_BACKPACK_WINDOW_SLOT_ROWS * slotSizeWithMargin - 5, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<CListBoxWithCallback> backpackListBox;
|
||||
std::vector<std::shared_ptr<CPicture>> backpackSlotsBackgrounds;
|
||||
const size_t HERO_BACKPACK_WINDOW_SLOT_COLUMNS = 8;
|
||||
const size_t HERO_BACKPACK_WINDOW_SLOT_LINES = 8;
|
||||
const size_t HERO_BACKPACK_WINDOW_SLOT_ROWS = 8;
|
||||
};
|
||||
|
@ -165,7 +165,7 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst
|
||||
|
||||
if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroBackpack>>)
|
||||
{
|
||||
if(!isTransferAllowed)
|
||||
if(!isTransferAllowed && artPlace.getArt())
|
||||
{
|
||||
if(closeCallback)
|
||||
closeCallback();
|
||||
|
@ -14,17 +14,33 @@
|
||||
#include "../gui/Shortcut.h"
|
||||
|
||||
#include "../widgets/Buttons.h"
|
||||
#include "../widgets/Images.h"
|
||||
#include "CMessage.h"
|
||||
#include "render/Canvas.h"
|
||||
#include "CPlayerInterface.h"
|
||||
|
||||
CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero)
|
||||
: CWindowObject(PLAYER_COLORED)
|
||||
: CWindowObject((EOptions)0)
|
||||
{
|
||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||
|
||||
arts = std::make_shared<CArtifactsOfHeroBackpack>(Point(-100, -170));
|
||||
stretchedBackground = std::make_shared<CFilledTexture>("DIBOXBCK", Rect(0, 0, 410, 425));
|
||||
pos.w = stretchedBackground->pos.w;
|
||||
pos.h = stretchedBackground->pos.h;
|
||||
center();
|
||||
|
||||
|
||||
arts = std::make_shared<CArtifactsOfHeroBackpack>(/*Point(-100, -170)*/Point(10, 10));
|
||||
arts->setHero(hero);
|
||||
addSet(arts);
|
||||
|
||||
addCloseCallback(std::bind(&CHeroBackpackWindow::close, this));
|
||||
|
||||
quitButton = std::make_shared<CButton>(Point(242, 200), "hsbtns.def", CButton::tooltip(""), [this]() { close(); }, EShortcut::GLOBAL_RETURN);
|
||||
quitButton = std::make_shared<CButton>(Point(173, 385), "IOKAY32.def", CButton::tooltip(""), [this]() { close(); }, EShortcut::GLOBAL_RETURN);
|
||||
}
|
||||
|
||||
void CHeroBackpackWindow::showAll(Canvas &to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
CMessage::drawBorder(PlayerColor(LOCPLINT->playerID), to.getInternalSurface(), pos.w+28, pos.h+29, pos.x-14, pos.y-15);
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "../widgets/CWindowWithArtifacts.h"
|
||||
#include "CWindowObject.h"
|
||||
|
||||
class CFilledTexture;
|
||||
|
||||
class CHeroBackpackWindow : public CWindowObject, public CWindowWithArtifacts
|
||||
{
|
||||
public:
|
||||
@ -20,4 +22,7 @@ public:
|
||||
private:
|
||||
std::shared_ptr<CArtifactsOfHeroBackpack> arts;
|
||||
std::shared_ptr<CButton> quitButton;
|
||||
std::shared_ptr<CFilledTexture> stretchedBackground;
|
||||
|
||||
void showAll(Canvas &to) override;
|
||||
};
|
||||
|
@ -84,11 +84,19 @@ CHeroWindow::CHeroWindow(const CGHeroInstance * hero)
|
||||
|
||||
quitButton = std::make_shared<CButton>(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [=](){ close(); }, EShortcut::GLOBAL_RETURN);
|
||||
|
||||
dismissLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[8], Rect(370, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||
dismissButton = std::make_shared<CButton>(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [=](){ dismissCurrent(); }, EShortcut::HERO_DISMISS);
|
||||
|
||||
questlogLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||
if(settings["general"]["enableUiEnhancements"].Bool())
|
||||
{
|
||||
questlogButton = std::make_shared<CButton>(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, EShortcut::ADVENTURE_QUEST_LOG);
|
||||
backpackButton = std::make_shared<CButton>(Point(424, 429), "buttons/backpack", CButton::tooltipLocalized("vcmi.heroWindow.Backpack"), [=](){ createBackpackWindow(); }, EShortcut::HERO_BACKPACK);
|
||||
dismissButton = std::make_shared<CButton>(Point(534, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [=](){ dismissCurrent(); }, EShortcut::HERO_DISMISS);
|
||||
}
|
||||
else
|
||||
{
|
||||
dismissLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[8], Rect(370, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||
questlogLabel = std::make_shared<CTextBox>(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE);
|
||||
dismissButton = std::make_shared<CButton>(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [=](){ dismissCurrent(); }, EShortcut::HERO_DISMISS);
|
||||
questlogButton = std::make_shared<CButton>(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, EShortcut::ADVENTURE_QUEST_LOG);
|
||||
}
|
||||
|
||||
formations = std::make_shared<CToggleGroup>(0);
|
||||
formations->addToggle(0, std::make_shared<CToggleButton>(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, EShortcut::HERO_TIGHT_FORMATION));
|
||||
|
@ -554,7 +554,7 @@ std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index)
|
||||
void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstance *> & ownedObjects)
|
||||
{
|
||||
ui32 footerPos = OVERVIEW_SIZE * 116;
|
||||
TResources minesCount(GameConstants::RESOURCE_QUANTITY, 0);
|
||||
ResourceSet minesCount = ResourceSet();
|
||||
int totalIncome=0;
|
||||
|
||||
for(const CGObjectInstance * object : ownedObjects)
|
||||
|
@ -64,6 +64,10 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
|
||||
{
|
||||
showStickyHeroWindowsChangedCallback(value, owner);
|
||||
});
|
||||
addCallback("enableAutocombatSpellsChanged", [this](bool value)
|
||||
{
|
||||
enableAutocombatSpellsChangedCallback(value);
|
||||
});
|
||||
build(config);
|
||||
|
||||
std::shared_ptr<CToggleGroup> animationSpeedToggle = widget<CToggleGroup>("animationSpeedPicker");
|
||||
@ -92,6 +96,9 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
|
||||
|
||||
std::shared_ptr<CToggleButton> skipBattleIntroMusicCheckbox = widget<CToggleButton>("skipBattleIntroMusicCheckbox");
|
||||
skipBattleIntroMusicCheckbox->setSelected(settings["gameTweaks"]["skipBattleIntroMusic"].Bool());
|
||||
|
||||
std::shared_ptr<CToggleButton> enableAutocombatSpellsCheckbox = widget<CToggleButton>("enableAutocombatSpellsCheckbox");
|
||||
enableAutocombatSpellsCheckbox->setSelected(settings["battle"]["enableAutocombatSpells"].Bool());
|
||||
}
|
||||
|
||||
int BattleOptionsTab::getAnimSpeed() const
|
||||
@ -235,3 +242,9 @@ void BattleOptionsTab::skipBattleIntroMusicChangedCallback(bool value)
|
||||
musicSkipSettingValue->Bool() = value;
|
||||
}
|
||||
|
||||
void BattleOptionsTab::enableAutocombatSpellsChangedCallback(bool value)
|
||||
{
|
||||
Settings enableAutocombatSpells = settings.write["battle"]["enableAutocombatSpells"];
|
||||
enableAutocombatSpells->Bool() = value;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ private:
|
||||
void queueSizeChangedCallback(int value, BattleInterface * parentBattleInterface);
|
||||
void skipBattleIntroMusicChangedCallback(bool value);
|
||||
void showStickyHeroWindowsChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||
void enableAutocombatSpellsChangedCallback(bool value);
|
||||
public:
|
||||
BattleOptionsTab(BattleInterface * owner = nullptr);
|
||||
};
|
||||
|
@ -330,6 +330,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
||||
${MAIN_LIB_DIR}/../include/vcmi/Team.h
|
||||
|
||||
${MAIN_LIB_DIR}/battle/AccessibilityInfo.h
|
||||
${MAIN_LIB_DIR}/battle/AutocombatPreferences.h
|
||||
${MAIN_LIB_DIR}/battle/BattleAction.h
|
||||
${MAIN_LIB_DIR}/battle/BattleAttackInfo.h
|
||||
${MAIN_LIB_DIR}/battle/BattleHex.h
|
||||
|
@ -38,7 +38,8 @@
|
||||
"autosaveCountLimit",
|
||||
"useSavePrefix",
|
||||
"savePrefix",
|
||||
"startTurnAutosave"
|
||||
"startTurnAutosave",
|
||||
"enableUiEnhancements"
|
||||
],
|
||||
"properties" : {
|
||||
"playerName" : {
|
||||
@ -126,6 +127,10 @@
|
||||
"startTurnAutosave" : {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"enableUiEnhancements" : {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -276,7 +281,7 @@
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"default" : {},
|
||||
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "rangeLimitHighlightOnHover", "showQueue", "swipeAttackDistance", "queueSize", "stickyHeroInfoWindows" ],
|
||||
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "rangeLimitHighlightOnHover", "showQueue", "swipeAttackDistance", "queueSize", "stickyHeroInfoWindows", "enableAutocombatSpells" ],
|
||||
"properties" : {
|
||||
"speedFactor" : {
|
||||
"type" : "number",
|
||||
@ -318,6 +323,10 @@
|
||||
"stickyHeroInfoWindows" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"enableAutocombatSpells" : {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -51,14 +51,37 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "autoCombatCheckboxes",
|
||||
"name": "autoCombatFakeCheckboxes",
|
||||
"type" : "verticalLayout",
|
||||
"customType" : "checkboxFake",
|
||||
"position": {"x": 380, "y": 83},
|
||||
"items":
|
||||
[
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"type" : "verticalLayout",
|
||||
"customType" : "checkbox",
|
||||
"position": {"x": 380, "y": 113},
|
||||
"items":
|
||||
[
|
||||
{
|
||||
"name": "enableAutocombatSpellsCheckbox",
|
||||
"help": "vcmi.battleOptions.enableAutocombatSpells",
|
||||
"callback": "enableAutocombatSpellsChanged"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name": "autoCombatFakeCheckboxes2",
|
||||
"type" : "verticalLayout",
|
||||
"customType" : "checkboxFake",
|
||||
"position": {"x": 380, "y": 143},
|
||||
"items":
|
||||
[
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "battle/AutocombatPreferences.h"
|
||||
#include "IGameEventsReceiver.h"
|
||||
|
||||
#include "spells/ViewSpellInt.h"
|
||||
@ -76,6 +77,7 @@ public:
|
||||
|
||||
virtual ~CBattleGameInterface() {};
|
||||
virtual void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB){};
|
||||
virtual void initBattleInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB, AutocombatPreferences autocombatPreferences){};
|
||||
|
||||
//battle call-ins
|
||||
virtual void activeStack(const CStack * stack)=0; //called when it's turn of that stack
|
||||
|
21
lib/battle/AutocombatPreferences.h
Normal file
21
lib/battle/AutocombatPreferences.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* AutocombatPreferences.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
struct AutocombatPreferences
|
||||
{
|
||||
bool enableSpellsUsage = true;
|
||||
//TODO: below options exist in original H3, consider usefulness of mixed human-AI combat when enabling autocombat inside battle
|
||||
// bool enableUnitsUsage = true;
|
||||
// bool enableCatapultUsage = true;
|
||||
// bool enableBallistaUsage = true;
|
||||
// bool enableFirstAidTendUsage = true;
|
||||
};
|
||||
|
@ -1617,52 +1617,69 @@ void CGHeroInstance::serializeCommonOptions(JsonSerializeFormat & handler)
|
||||
//in json default skills means no field/null
|
||||
if(!defaultSkills)
|
||||
{
|
||||
//enter structure here as handler initialize it
|
||||
auto secondarySkills = handler.enterStruct("secondarySkills");
|
||||
//enter array here as handler initialize it
|
||||
auto secondarySkills = handler.enterArray("secondarySkills");
|
||||
secondarySkills.syncSize(secSkills, JsonNode::JsonType::DATA_VECTOR);
|
||||
|
||||
for(auto & p : secSkills)
|
||||
for(size_t skillIndex = 0; skillIndex < secondarySkills.size(); ++skillIndex)
|
||||
{
|
||||
const si32 rawId = p.first.num;
|
||||
JsonArraySerializer inner = secondarySkills.enterArray(skillIndex);
|
||||
const si32 rawId = secSkills.at(skillIndex).first;
|
||||
|
||||
if(rawId < 0 || rawId >= VLC->skillh->size())
|
||||
logGlobal->error("Invalid secondary skill %d", rawId);
|
||||
|
||||
handler.serializeEnum((*VLC->skillh)[SecondarySkill(rawId)]->getJsonKey(), p.second, 0, NSecondarySkill::levels);
|
||||
auto value = (*VLC->skillh)[SecondarySkill(rawId)]->getJsonKey();
|
||||
handler.serializeString("skill", value);
|
||||
value = NSecondarySkill::levels.at(secSkills.at(skillIndex).second);
|
||||
handler.serializeString("level", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto secondarySkills = handler.enterStruct("secondarySkills");
|
||||
const JsonNode & skillMap = handler.getCurrent();
|
||||
auto secondarySkills = handler.getCurrent()["secondarySkills"];
|
||||
|
||||
secSkills.clear();
|
||||
if(skillMap.getType() == JsonNode::JsonType::DATA_NULL)
|
||||
if(secondarySkills.getType() == JsonNode::JsonType::DATA_NULL)
|
||||
{
|
||||
secSkills.emplace_back(SecondarySkill::DEFAULT, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const auto & p : skillMap.Struct())
|
||||
auto addSkill = [this](const std::string & skillId, const std::string & levelId)
|
||||
{
|
||||
const std::string skillId = p.first;
|
||||
const std::string levelId = p.second.String();
|
||||
|
||||
const int rawId = CSkillHandler::decodeSkill(skillId);
|
||||
if(rawId < 0)
|
||||
{
|
||||
logGlobal->error("Invalid secondary skill %s", skillId);
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
const int level = vstd::find_pos(NSecondarySkill::levels, levelId);
|
||||
if(level < 0)
|
||||
{
|
||||
logGlobal->error("Invalid secondary skill level%s", levelId);
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
secSkills.emplace_back(SecondarySkill(rawId), level);
|
||||
};
|
||||
|
||||
if(secondarySkills.getType() == JsonNode::JsonType::DATA_VECTOR)
|
||||
{
|
||||
for(const auto & p : secondarySkills.Vector())
|
||||
{
|
||||
auto skillMap = p.Struct();
|
||||
addSkill(skillMap["skill"].String(), skillMap["level"].String());
|
||||
}
|
||||
}
|
||||
else if(secondarySkills.getType() == JsonNode::JsonType::DATA_STRUCT)
|
||||
{
|
||||
for(const auto & p : secondarySkills.Struct())
|
||||
{
|
||||
addSkill(p.first, p.second.String());
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user