mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-10 22:31:40 +02:00
Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
@@ -234,8 +234,10 @@
|
|||||||
"vcmi.adventureOptions.borderScroll.help" : "{Border Scrolling}\n\nScroll adventure map when cursor is adjacent to window edge. Can be disabled by holding down CTRL key.",
|
"vcmi.adventureOptions.borderScroll.help" : "{Border Scrolling}\n\nScroll adventure map when cursor is adjacent to window edge. Can be disabled by holding down CTRL key.",
|
||||||
"vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Info Panel Creature Management",
|
"vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Info Panel Creature Management",
|
||||||
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info Panel Creature Management}\n\nAllows rearranging creatures in info panel instead of cycling between default components.",
|
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info Panel Creature Management}\n\nAllows rearranging creatures in info panel instead of cycling between default components.",
|
||||||
"vcmi.adventureOptions.leftButtonDrag.hover" : "Left Click Drag Map",
|
"vcmi.adventureOptions.leftButtonDrag.hover" : "Left Click Drag",
|
||||||
"vcmi.adventureOptions.leftButtonDrag.help" : "{Left Click Drag Map}\n\nWhen enabled, moving mouse with left button pressed will drag adventure map view.",
|
"vcmi.adventureOptions.leftButtonDrag.help" : "{Left Click Drag}\n\nWhen enabled, moving mouse with left button pressed will drag adventure map view.",
|
||||||
|
"vcmi.adventureOptions.rightButtonDrag.hover" : "Right Click Drag",
|
||||||
|
"vcmi.adventureOptions.rightButtonDrag.help" : "{Right Click Drag}\n\nWhen enabled, moving mouse with right button pressed will drag adventure map view.",
|
||||||
"vcmi.adventureOptions.smoothDragging.hover" : "Smooth Map Dragging",
|
"vcmi.adventureOptions.smoothDragging.hover" : "Smooth Map Dragging",
|
||||||
"vcmi.adventureOptions.smoothDragging.help" : "{Smooth Map Dragging}\n\nWhen enabled, map dragging has a modern run out effect.",
|
"vcmi.adventureOptions.smoothDragging.help" : "{Smooth Map Dragging}\n\nWhen enabled, map dragging has a modern run out effect.",
|
||||||
"vcmi.adventureOptions.skipAdventureMapAnimations.hover" : "Skip fading effects",
|
"vcmi.adventureOptions.skipAdventureMapAnimations.hover" : "Skip fading effects",
|
||||||
|
@@ -234,8 +234,10 @@
|
|||||||
"vcmi.adventureOptions.borderScroll.help" : "{Scrollen am Rand}\n\nScrollt die Abenteuerkarte, wenn sich der Cursor neben dem Fensterrand befindet. Kann mit gedrückter STRG-Taste deaktiviert werden.",
|
"vcmi.adventureOptions.borderScroll.help" : "{Scrollen am Rand}\n\nScrollt die Abenteuerkarte, wenn sich der Cursor neben dem Fensterrand befindet. Kann mit gedrückter STRG-Taste deaktiviert werden.",
|
||||||
"vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Info-Panel Kreaturenmanagement",
|
"vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Info-Panel Kreaturenmanagement",
|
||||||
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info-Panel Kreaturenmanagement}\n\nErmöglicht die Neuanordnung von Kreaturen im Info-Panel, anstatt zwischen den Standardkomponenten zu wechseln",
|
"vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info-Panel Kreaturenmanagement}\n\nErmöglicht die Neuanordnung von Kreaturen im Info-Panel, anstatt zwischen den Standardkomponenten zu wechseln",
|
||||||
"vcmi.adventureOptions.leftButtonDrag.hover" : "Ziehen der Karte mit Links",
|
"vcmi.adventureOptions.leftButtonDrag.hover" : "Ziehen mit Links",
|
||||||
"vcmi.adventureOptions.leftButtonDrag.help" : "{Ziehen der Karte mit Links}\n\nWenn aktiviert, wird die Maus bei gedrückter linker Taste in die Kartenansicht gezogen",
|
"vcmi.adventureOptions.leftButtonDrag.help" : "{Ziehen mit Links}\n\nWenn aktiviert, kann mit gedrückter linker Taste die Kartenansicht gezogen werden",
|
||||||
|
"vcmi.adventureOptions.rightButtonDrag.hover" : "Ziehen mit Rechts",
|
||||||
|
"vcmi.adventureOptions.rightButtonDrag.help" : "{Ziehen mit Rechts}\n\nWenn aktiviert, kann mit gedrückter rechter Taste die Kartenansicht gezogen werden",
|
||||||
"vcmi.adventureOptions.smoothDragging.hover" : "Nahtloses Ziehen der Karte",
|
"vcmi.adventureOptions.smoothDragging.hover" : "Nahtloses Ziehen der Karte",
|
||||||
"vcmi.adventureOptions.smoothDragging.help" : "{Nahtloses Ziehen der Karte}\n\nWenn aktiviert hat das Ziehen der Karte einen sanften Auslaufeffekt.",
|
"vcmi.adventureOptions.smoothDragging.help" : "{Nahtloses Ziehen der Karte}\n\nWenn aktiviert hat das Ziehen der Karte einen sanften Auslaufeffekt.",
|
||||||
"vcmi.adventureOptions.skipAdventureMapAnimations.hover" : "Fading-Effekte überspringen",
|
"vcmi.adventureOptions.skipAdventureMapAnimations.hover" : "Fading-Effekte überspringen",
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "lobby/CLobbyScreen.h"
|
#include "lobby/CLobbyScreen.h"
|
||||||
#include "lobby/CBonusSelection.h"
|
#include "lobby/CBonusSelection.h"
|
||||||
#include "windows/InfoWindows.h"
|
#include "windows/InfoWindows.h"
|
||||||
|
#include "windows/GUIClasses.h"
|
||||||
#include "media/CMusicHandler.h"
|
#include "media/CMusicHandler.h"
|
||||||
#include "media/IVideoPlayer.h"
|
#include "media/IVideoPlayer.h"
|
||||||
|
|
||||||
@@ -661,10 +662,13 @@ void CServerHandler::endGameplay()
|
|||||||
{
|
{
|
||||||
GH.curInt = CMM.get();
|
GH.curInt = CMM.get();
|
||||||
CMM->enable();
|
CMM->enable();
|
||||||
|
CMM->playMusic();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GH.curInt = CMainMenu::create().get();
|
auto mainMenu = CMainMenu::create();
|
||||||
|
GH.curInt = mainMenu.get();
|
||||||
|
mainMenu->playMusic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,10 +712,10 @@ void CServerHandler::startCampaignScenario(HighScoreParameter param, std::shared
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
CMM->openCampaignScreen(ourCampaign->campaignSet);
|
CMM->openCampaignScreen(ourCampaign->campaignSet);
|
||||||
if(!ourCampaign->getOutroVideo().empty() && CCS->videoh->open(ourCampaign->getOutroVideo(), false))
|
if(!ourCampaign->getOutroVideo().empty() && CCS->videoh->open(ourCampaign->getOutroVideo(), 1))
|
||||||
{
|
{
|
||||||
CCS->musich->stopMusic();
|
CCS->musich->stopMusic();
|
||||||
GH.windows().createAndPushWindow<CampaignRimVideo>(ourCampaign->getOutroVideo(), ourCampaign->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : ourCampaign->getVideoRim(), [campaignScoreCalculator, statistic](){
|
GH.windows().createAndPushWindow<VideoWindow>(ourCampaign->getOutroVideo(), ourCampaign->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : ourCampaign->getVideoRim(), false, 1, [campaignScoreCalculator, statistic](bool skipped){
|
||||||
GH.windows().createAndPushWindow<CHighScoreInputScreen>(true, *campaignScoreCalculator, statistic);
|
GH.windows().createAndPushWindow<CHighScoreInputScreen>(true, *campaignScoreCalculator, statistic);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "CGameInfo.h"
|
#include "CGameInfo.h"
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
|
#include "PlayerLocalState.h"
|
||||||
#include "CServerHandler.h"
|
#include "CServerHandler.h"
|
||||||
#include "ClientNetPackVisitors.h"
|
#include "ClientNetPackVisitors.h"
|
||||||
#include "adventureMap/AdventureMapInterface.h"
|
#include "adventureMap/AdventureMapInterface.h"
|
||||||
@@ -495,6 +496,19 @@ void CClient::startPlayerBattleAction(const BattleID & battleID, PlayerColor col
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClient::updatePath(const ObjectInstanceID & id)
|
||||||
|
{
|
||||||
|
invalidatePaths();
|
||||||
|
auto hero = getHero(id);
|
||||||
|
updatePath(hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClient::updatePath(const CGHeroInstance * hero)
|
||||||
|
{
|
||||||
|
if(LOCPLINT && hero)
|
||||||
|
LOCPLINT->localState->verifyPath(hero);
|
||||||
|
}
|
||||||
|
|
||||||
void CClient::invalidatePaths()
|
void CClient::invalidatePaths()
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> pathLock(pathCacheMutex);
|
boost::unique_lock<boost::mutex> pathLock(pathCacheMutex);
|
||||||
|
@@ -150,7 +150,9 @@ public:
|
|||||||
void battleFinished(const BattleID & battleID);
|
void battleFinished(const BattleID & battleID);
|
||||||
void startPlayerBattleAction(const BattleID & battleID, PlayerColor color);
|
void startPlayerBattleAction(const BattleID & battleID, PlayerColor color);
|
||||||
|
|
||||||
void invalidatePaths();
|
void invalidatePaths(); // clears this->pathCache()
|
||||||
|
void updatePath(const ObjectInstanceID & heroID); // invalidatePaths and update displayed hero path
|
||||||
|
void updatePath(const CGHeroInstance * hero);
|
||||||
std::shared_ptr<const CPathsInfo> getPathsInfo(const CGHeroInstance * h);
|
std::shared_ptr<const CPathsInfo> getPathsInfo(const CGHeroInstance * h);
|
||||||
|
|
||||||
friend class CCallback; //handling players actions
|
friend class CCallback; //handling players actions
|
||||||
|
@@ -101,7 +101,7 @@ void callBattleInterfaceIfPresentForBothSides(CClient & cl, const BattleID & bat
|
|||||||
{
|
{
|
||||||
assert(cl.gameState()->getBattle(battleID));
|
assert(cl.gameState()->getBattle(battleID));
|
||||||
|
|
||||||
if (!cl.gameState()->getBattle(battleID))
|
if(!cl.gameState()->getBattle(battleID))
|
||||||
{
|
{
|
||||||
logGlobal->error("Attempt to call battle interface without ongoing battle!");
|
logGlobal->error("Attempt to call battle interface without ongoing battle!");
|
||||||
return;
|
return;
|
||||||
@@ -161,14 +161,14 @@ void ApplyClientNetPackVisitor::visitSetMana(SetMana & pack)
|
|||||||
if(settings["session"]["headless"].Bool())
|
if(settings["session"]["headless"].Bool())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto window : GH.windows().findWindows<BattleWindow>())
|
for(auto window : GH.windows().findWindows<BattleWindow>())
|
||||||
window->heroManaPointsChanged(h);
|
window->heroManaPointsChanged(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitSetMovePoints(SetMovePoints & pack)
|
void ApplyClientNetPackVisitor::visitSetMovePoints(SetMovePoints & pack)
|
||||||
{
|
{
|
||||||
const CGHeroInstance *h = cl.getHero(pack.hid);
|
const CGHeroInstance *h = cl.getHero(pack.hid);
|
||||||
cl.invalidatePaths();
|
cl.updatePath(h);
|
||||||
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroMovePointsChanged, h);
|
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroMovePointsChanged, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ void ApplyClientNetPackVisitor::visitSetStackType(SetStackType & pack)
|
|||||||
void ApplyClientNetPackVisitor::visitEraseStack(EraseStack & pack)
|
void ApplyClientNetPackVisitor::visitEraseStack(EraseStack & pack)
|
||||||
{
|
{
|
||||||
dispatchGarrisonChange(cl, pack.army, ObjectInstanceID());
|
dispatchGarrisonChange(cl, pack.army, ObjectInstanceID());
|
||||||
cl.invalidatePaths(); //it is possible to remove last non-native unit for current terrain and lose movement penalty
|
cl.updatePath(pack.army); //it is possible to remove last non-native unit for current terrain and lose movement penalty
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitSwapStacks(SwapStacks & pack)
|
void ApplyClientNetPackVisitor::visitSwapStacks(SwapStacks & pack)
|
||||||
@@ -237,15 +237,14 @@ void ApplyClientNetPackVisitor::visitSwapStacks(SwapStacks & pack)
|
|||||||
dispatchGarrisonChange(cl, pack.srcArmy, pack.dstArmy);
|
dispatchGarrisonChange(cl, pack.srcArmy, pack.dstArmy);
|
||||||
|
|
||||||
if(pack.srcArmy != pack.dstArmy)
|
if(pack.srcArmy != pack.dstArmy)
|
||||||
cl.invalidatePaths(); // adding/removing units may change terrain type penalty based on creature native terrains
|
cl.updatePath(pack.dstArmy); // adding/removing units may change terrain type penalty based on creature native terrains
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitInsertNewStack(InsertNewStack & pack)
|
void ApplyClientNetPackVisitor::visitInsertNewStack(InsertNewStack & pack)
|
||||||
{
|
{
|
||||||
dispatchGarrisonChange(cl, pack.army, ObjectInstanceID());
|
dispatchGarrisonChange(cl, pack.army, ObjectInstanceID());
|
||||||
|
|
||||||
if(gs.getHero(pack.army))
|
cl.updatePath(pack.army); // adding/removing units may change terrain type penalty based on creature native terrains
|
||||||
cl.invalidatePaths(); // adding/removing units may change terrain type penalty based on creature native terrains
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitRebalanceStacks(RebalanceStacks & pack)
|
void ApplyClientNetPackVisitor::visitRebalanceStacks(RebalanceStacks & pack)
|
||||||
@@ -253,7 +252,10 @@ void ApplyClientNetPackVisitor::visitRebalanceStacks(RebalanceStacks & pack)
|
|||||||
dispatchGarrisonChange(cl, pack.srcArmy, pack.dstArmy);
|
dispatchGarrisonChange(cl, pack.srcArmy, pack.dstArmy);
|
||||||
|
|
||||||
if(pack.srcArmy != pack.dstArmy)
|
if(pack.srcArmy != pack.dstArmy)
|
||||||
cl.invalidatePaths(); // adding/removing units may change terrain type penalty based on creature native terrains
|
{
|
||||||
|
cl.updatePath(pack.srcArmy); // adding/removing units may change terrain type penalty based on creature native terrains
|
||||||
|
cl.updatePath(pack.dstArmy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitBulkRebalanceStacks(BulkRebalanceStacks & pack)
|
void ApplyClientNetPackVisitor::visitBulkRebalanceStacks(BulkRebalanceStacks & pack)
|
||||||
@@ -266,7 +268,10 @@ void ApplyClientNetPackVisitor::visitBulkRebalanceStacks(BulkRebalanceStacks & p
|
|||||||
dispatchGarrisonChange(cl, pack.moves[0].srcArmy, destArmy);
|
dispatchGarrisonChange(cl, pack.moves[0].srcArmy, destArmy);
|
||||||
|
|
||||||
if(pack.moves[0].srcArmy != destArmy)
|
if(pack.moves[0].srcArmy != destArmy)
|
||||||
cl.invalidatePaths(); // adding/removing units may change terrain type penalty based on creature native terrains
|
{
|
||||||
|
cl.updatePath(destArmy); // adding/removing units may change terrain type penalty based on creature native terrains
|
||||||
|
cl.updatePath(pack.moves[0].srcArmy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,6 +297,7 @@ void ApplyClientNetPackVisitor::visitPutArtifact(PutArtifact & pack)
|
|||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitEraseArtifact(BulkEraseArtifacts & pack)
|
void ApplyClientNetPackVisitor::visitEraseArtifact(BulkEraseArtifacts & pack)
|
||||||
{
|
{
|
||||||
|
cl.updatePath(pack.artHolder);
|
||||||
for(const auto & slotErase : pack.posPack)
|
for(const auto & slotErase : pack.posPack)
|
||||||
callInterfaceIfPresent(cl, cl.getOwner(pack.artHolder), &IGameEventsReceiver::artifactRemoved, ArtifactLocation(pack.artHolder, slotErase));
|
callInterfaceIfPresent(cl, cl.getOwner(pack.artHolder), &IGameEventsReceiver::artifactRemoved, ArtifactLocation(pack.artHolder, slotErase));
|
||||||
}
|
}
|
||||||
@@ -312,7 +318,8 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
|
|||||||
if(pack.interfaceOwner != dstOwner)
|
if(pack.interfaceOwner != dstOwner)
|
||||||
callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);
|
callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);
|
||||||
|
|
||||||
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
cl.updatePath(pack.srcArtHolder); // hero might have equipped/unequipped Angel Wings
|
||||||
|
cl.updatePath(pack.dstArtHolder);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -342,14 +349,14 @@ void ApplyClientNetPackVisitor::visitAssembledArtifact(AssembledArtifact & pack)
|
|||||||
{
|
{
|
||||||
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactAssembled, pack.al);
|
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactAssembled, pack.al);
|
||||||
|
|
||||||
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
cl.updatePath(pack.al.artHolder); // hero might have equipped/unequipped Angel Wings
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitDisassembledArtifact(DisassembledArtifact & pack)
|
void ApplyClientNetPackVisitor::visitDisassembledArtifact(DisassembledArtifact & pack)
|
||||||
{
|
{
|
||||||
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactDisassembled, pack.al);
|
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactDisassembled, pack.al);
|
||||||
|
|
||||||
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
cl.updatePath(pack.al.artHolder); // hero might have equipped/unequipped Angel Wings
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitHeroVisit(HeroVisit & pack)
|
void ApplyClientNetPackVisitor::visitHeroVisit(HeroVisit & pack)
|
||||||
@@ -363,7 +370,7 @@ void ApplyClientNetPackVisitor::visitNewTurn(NewTurn & pack)
|
|||||||
{
|
{
|
||||||
cl.invalidatePaths();
|
cl.invalidatePaths();
|
||||||
|
|
||||||
if (pack.newWeekNotification)
|
if(pack.newWeekNotification)
|
||||||
{
|
{
|
||||||
const auto & newWeek = *pack.newWeekNotification;
|
const auto & newWeek = *pack.newWeekNotification;
|
||||||
|
|
||||||
@@ -380,7 +387,7 @@ void ApplyClientNetPackVisitor::visitGiveBonus(GiveBonus & pack)
|
|||||||
case GiveBonus::ETarget::OBJECT:
|
case GiveBonus::ETarget::OBJECT:
|
||||||
{
|
{
|
||||||
const CGHeroInstance *h = gs.getHero(pack.id.as<ObjectInstanceID>());
|
const CGHeroInstance *h = gs.getHero(pack.id.as<ObjectInstanceID>());
|
||||||
if (h)
|
if(h)
|
||||||
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, true);
|
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -419,7 +426,7 @@ void ApplyClientNetPackVisitor::visitPlayerEndsGame(PlayerEndsGame & pack)
|
|||||||
|
|
||||||
bool lastHumanEndsGame = CSH->howManyPlayerInterfaces() == 1 && vstd::contains(cl.playerint, pack.player) && cl.getPlayerState(pack.player)->human && !settings["session"]["spectate"].Bool();
|
bool lastHumanEndsGame = CSH->howManyPlayerInterfaces() == 1 && vstd::contains(cl.playerint, pack.player) && cl.getPlayerState(pack.player)->human && !settings["session"]["spectate"].Bool();
|
||||||
|
|
||||||
if (lastHumanEndsGame)
|
if(lastHumanEndsGame)
|
||||||
{
|
{
|
||||||
assert(adventureInt);
|
assert(adventureInt);
|
||||||
if(adventureInt)
|
if(adventureInt)
|
||||||
@@ -446,9 +453,9 @@ void ApplyClientNetPackVisitor::visitPlayerReinitInterface(PlayerReinitInterface
|
|||||||
{
|
{
|
||||||
cl.initPlayerInterfaces();
|
cl.initPlayerInterfaces();
|
||||||
|
|
||||||
for (PlayerColor player(0); player < PlayerColor::PLAYER_LIMIT; ++player)
|
for(PlayerColor player(0); player < PlayerColor::PLAYER_LIMIT; ++player)
|
||||||
{
|
{
|
||||||
if (cl.gameState()->isPlayerMakingTurn(player))
|
if(cl.gameState()->isPlayerMakingTurn(player))
|
||||||
{
|
{
|
||||||
callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, player);
|
callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, player);
|
||||||
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn, QueryID::NONE);
|
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn, QueryID::NONE);
|
||||||
@@ -482,7 +489,7 @@ void ApplyClientNetPackVisitor::visitRemoveBonus(RemoveBonus & pack)
|
|||||||
case GiveBonus::ETarget::OBJECT:
|
case GiveBonus::ETarget::OBJECT:
|
||||||
{
|
{
|
||||||
const CGHeroInstance *h = gs.getHero(pack.whoID.as<ObjectInstanceID>());
|
const CGHeroInstance *h = gs.getHero(pack.whoID.as<ObjectInstanceID>());
|
||||||
if (h)
|
if(h)
|
||||||
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, false);
|
callInterfaceIfPresent(cl, h->tempOwner, &IGameEventsReceiver::heroBonusChanged, h, pack.bonus, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -701,7 +708,7 @@ void ApplyFirstClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty &
|
|||||||
}
|
}
|
||||||
|
|
||||||
// invalidate section of map view with our object and force an update with new flag color
|
// invalidate section of map view with our object and force an update with new flag color
|
||||||
if (pack.what == ObjProperty::OWNER && CGI->mh)
|
if(pack.what == ObjProperty::OWNER && CGI->mh)
|
||||||
{
|
{
|
||||||
auto object = gs.getObjInstance(pack.id);
|
auto object = gs.getObjInstance(pack.id);
|
||||||
CGI->mh->onObjectInstantRemove(object, object->getOwner());
|
CGI->mh->onObjectInstantRemove(object, object->getOwner());
|
||||||
@@ -718,7 +725,7 @@ void ApplyClientNetPackVisitor::visitSetObjectProperty(SetObjectProperty & pack)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// invalidate section of map view with our object and force an update with new flag color
|
// invalidate section of map view with our object and force an update with new flag color
|
||||||
if (pack.what == ObjProperty::OWNER && CGI->mh)
|
if(pack.what == ObjProperty::OWNER && CGI->mh)
|
||||||
{
|
{
|
||||||
auto object = gs.getObjInstance(pack.id);
|
auto object = gs.getObjInstance(pack.id);
|
||||||
CGI->mh->onObjectInstantAdd(object, object->getOwner());
|
CGI->mh->onObjectInstantAdd(object, object->getOwner());
|
||||||
@@ -807,7 +814,7 @@ void ApplyClientNetPackVisitor::visitBattleSetActiveStack(BattleSetActiveStack &
|
|||||||
|
|
||||||
const CStack *activated = gs.getBattle(pack.battleID)->battleGetStackByID(pack.stack);
|
const CStack *activated = gs.getBattle(pack.battleID)->battleGetStackByID(pack.stack);
|
||||||
PlayerColor playerToCall; //pack.player that will move activated stack
|
PlayerColor playerToCall; //pack.player that will move activated stack
|
||||||
if (activated->hasBonusOfType(BonusType::HYPNOTIZED))
|
if(activated->hasBonusOfType(BonusType::HYPNOTIZED))
|
||||||
{
|
{
|
||||||
playerToCall = gs.getBattle(pack.battleID)->getSide(BattleSide::ATTACKER).color == activated->unitOwner()
|
playerToCall = gs.getBattle(pack.battleID)->getSide(BattleSide::ATTACKER).color == activated->unitOwner()
|
||||||
? gs.getBattle(pack.battleID)->getSide(BattleSide::DEFENDER).color
|
? gs.getBattle(pack.battleID)->getSide(BattleSide::DEFENDER).color
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
#include "widgets/TextControls.h"
|
#include "widgets/TextControls.h"
|
||||||
#include "media/CMusicHandler.h"
|
#include "media/CMusicHandler.h"
|
||||||
#include "media/IVideoPlayer.h"
|
#include "media/IVideoPlayer.h"
|
||||||
|
#include "windows/GUIClasses.h"
|
||||||
|
|
||||||
#include "../lib/CConfigHandler.h"
|
#include "../lib/CConfigHandler.h"
|
||||||
#include "../lib/texts/CGeneralTextHandler.h"
|
#include "../lib/texts/CGeneralTextHandler.h"
|
||||||
@@ -207,10 +208,10 @@ void ApplyOnLobbyScreenNetPackVisitor::visitLobbyUpdateState(LobbyUpdateState &
|
|||||||
{
|
{
|
||||||
auto bonusSel = std::make_shared<CBonusSelection>();
|
auto bonusSel = std::make_shared<CBonusSelection>();
|
||||||
lobby->bonusSel = bonusSel;
|
lobby->bonusSel = bonusSel;
|
||||||
if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty() && CCS->videoh->open(handler.si->campState->getIntroVideo(), false))
|
if(!handler.si->campState->conqueredScenarios().size() && !handler.si->campState->getIntroVideo().empty() && CCS->videoh->open(handler.si->campState->getIntroVideo(), 1))
|
||||||
{
|
{
|
||||||
CCS->musich->stopMusic();
|
CCS->musich->stopMusic();
|
||||||
GH.windows().createAndPushWindow<CampaignRimVideo>(handler.si->campState->getIntroVideo(), handler.si->campState->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getVideoRim(), [bonusSel](){
|
GH.windows().createAndPushWindow<VideoWindow>(handler.si->campState->getIntroVideo(), handler.si->campState->getVideoRim().empty() ? ImagePath::builtin("INTRORIM") : handler.si->campState->getVideoRim(), false, 1, [bonusSel](bool skipped){
|
||||||
if(!CSH->si->campState->getMusic().empty())
|
if(!CSH->si->campState->getMusic().empty())
|
||||||
CCS->musich->playMusic(CSH->si->campState->getMusic(), true, false);
|
CCS->musich->playMusic(CSH->si->campState->getMusic(), true, false);
|
||||||
GH.windows().pushWindow(bonusSel);
|
GH.windows().pushWindow(bonusSel);
|
||||||
|
@@ -34,7 +34,7 @@ InputSourceMouse::InputSourceMouse()
|
|||||||
void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motion)
|
void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motion)
|
||||||
{
|
{
|
||||||
Point newPosition = Point(motion.x, motion.y) / GH.screenHandler().getScalingFactor();
|
Point newPosition = Point(motion.x, motion.y) / GH.screenHandler().getScalingFactor();
|
||||||
Point distance= Point(-motion.xrel, -motion.yrel) / GH.screenHandler().getScalingFactor();
|
Point distance = Point(-motion.xrel, -motion.yrel) / GH.screenHandler().getScalingFactor();
|
||||||
|
|
||||||
mouseButtonsMask = motion.state;
|
mouseButtonsMask = motion.state;
|
||||||
|
|
||||||
@@ -42,6 +42,8 @@ void InputSourceMouse::handleEventMouseMotion(const SDL_MouseMotionEvent & motio
|
|||||||
GH.events().dispatchGesturePanning(middleClickPosition, newPosition, distance);
|
GH.events().dispatchGesturePanning(middleClickPosition, newPosition, distance);
|
||||||
else if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_LEFT))
|
else if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_LEFT))
|
||||||
GH.events().dispatchMouseDragged(newPosition, distance);
|
GH.events().dispatchMouseDragged(newPosition, distance);
|
||||||
|
else if (mouseButtonsMask & SDL_BUTTON(SDL_BUTTON_RIGHT))
|
||||||
|
GH.events().dispatchMouseDraggedPopup(newPosition, distance);
|
||||||
else
|
else
|
||||||
GH.input().setCursorPosition(newPosition);
|
GH.input().setCursorPosition(newPosition);
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,7 @@ void EventDispatcher::processLists(ui16 activityFlag, const Functor & cb)
|
|||||||
processList(AEventsReceiver::HOVER, hoverable);
|
processList(AEventsReceiver::HOVER, hoverable);
|
||||||
processList(AEventsReceiver::MOVE, motioninterested);
|
processList(AEventsReceiver::MOVE, motioninterested);
|
||||||
processList(AEventsReceiver::DRAG, draginterested);
|
processList(AEventsReceiver::DRAG, draginterested);
|
||||||
|
processList(AEventsReceiver::DRAG_POPUP, dragPopupInterested);
|
||||||
processList(AEventsReceiver::KEYBOARD, keyinterested);
|
processList(AEventsReceiver::KEYBOARD, keyinterested);
|
||||||
processList(AEventsReceiver::TIME, timeinterested);
|
processList(AEventsReceiver::TIME, timeinterested);
|
||||||
processList(AEventsReceiver::WHEEL, wheelInterested);
|
processList(AEventsReceiver::WHEEL, wheelInterested);
|
||||||
@@ -433,3 +434,10 @@ void EventDispatcher::dispatchMouseDragged(const Point & currentPosition, const
|
|||||||
elem->mouseDragged(currentPosition, lastUpdateDistance);
|
elem->mouseDragged(currentPosition, lastUpdateDistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventDispatcher::dispatchMouseDraggedPopup(const Point & currentPosition, const Point & lastUpdateDistance)
|
||||||
|
{
|
||||||
|
EventReceiversList diCopy = dragPopupInterested;
|
||||||
|
for(auto & elem : diCopy)
|
||||||
|
elem->mouseDraggedPopup(currentPosition, lastUpdateDistance);
|
||||||
|
}
|
||||||
|
@@ -30,6 +30,7 @@ class EventDispatcher
|
|||||||
EventReceiversList keyinterested;
|
EventReceiversList keyinterested;
|
||||||
EventReceiversList motioninterested;
|
EventReceiversList motioninterested;
|
||||||
EventReceiversList draginterested;
|
EventReceiversList draginterested;
|
||||||
|
EventReceiversList dragPopupInterested;
|
||||||
EventReceiversList timeinterested;
|
EventReceiversList timeinterested;
|
||||||
EventReceiversList wheelInterested;
|
EventReceiversList wheelInterested;
|
||||||
EventReceiversList doubleClickInterested;
|
EventReceiversList doubleClickInterested;
|
||||||
@@ -66,6 +67,7 @@ public:
|
|||||||
void dispatchMouseMoved(const Point & distance, const Point & position);
|
void dispatchMouseMoved(const Point & distance, const Point & position);
|
||||||
|
|
||||||
void dispatchMouseDragged(const Point & currentPosition, const Point & lastUpdateDistance);
|
void dispatchMouseDragged(const Point & currentPosition, const Point & lastUpdateDistance);
|
||||||
|
void dispatchMouseDraggedPopup(const Point & currentPosition, const Point & lastUpdateDistance);
|
||||||
|
|
||||||
void dispatchShowPopup(const Point & position, int tolerance);
|
void dispatchShowPopup(const Point & position, int tolerance);
|
||||||
void dispatchClosePopup(const Point & position);
|
void dispatchClosePopup(const Point & position);
|
||||||
|
@@ -61,6 +61,7 @@ public:
|
|||||||
virtual void wheelScrolled(int distance) {}
|
virtual void wheelScrolled(int distance) {}
|
||||||
virtual void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) {}
|
virtual void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) {}
|
||||||
virtual void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) {}
|
virtual void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) {}
|
||||||
|
virtual void mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance) {}
|
||||||
|
|
||||||
/// Called when UI element hover status changes
|
/// Called when UI element hover status changes
|
||||||
virtual void hover(bool on) {}
|
virtual void hover(bool on) {}
|
||||||
@@ -97,7 +98,8 @@ public:
|
|||||||
TEXTINPUT = 512,
|
TEXTINPUT = 512,
|
||||||
GESTURE = 1024,
|
GESTURE = 1024,
|
||||||
DRAG = 2048,
|
DRAG = 2048,
|
||||||
INPUT_MODE_CHANGE = 4096
|
INPUT_MODE_CHANGE = 4096,
|
||||||
|
DRAG_POPUP = 8192
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns true if element is currently hovered by mouse
|
/// Returns true if element is currently hovered by mouse
|
||||||
|
@@ -58,37 +58,6 @@
|
|||||||
|
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
|
||||||
|
|
||||||
CampaignRimVideo::CampaignRimVideo(VideoPath video, ImagePath rim, std::function<void()> closeCb)
|
|
||||||
: CWindowObject(BORDERED), closeCb(closeCb)
|
|
||||||
{
|
|
||||||
OBJECT_CONSTRUCTION;
|
|
||||||
|
|
||||||
addUsedEvents(LCLICK | KEYBOARD);
|
|
||||||
|
|
||||||
pos = center(Rect(0, 0, 800, 600));
|
|
||||||
|
|
||||||
videoPlayer = std::make_shared<VideoWidgetOnce>(Point(80, 186), video, true, [this](){ exit(); });
|
|
||||||
setBackground(rim);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CampaignRimVideo::exit()
|
|
||||||
{
|
|
||||||
close();
|
|
||||||
if(closeCb)
|
|
||||||
closeCb();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CampaignRimVideo::clickPressed(const Point & cursorPosition)
|
|
||||||
{
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CampaignRimVideo::keyPressed(EShortcut key)
|
|
||||||
{
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CampaignState> CBonusSelection::getCampaign()
|
std::shared_ptr<CampaignState> CBonusSelection::getCampaign()
|
||||||
{
|
{
|
||||||
return CSH->si->campState;
|
return CSH->si->campState;
|
||||||
|
@@ -33,20 +33,6 @@ class VideoWidgetOnce;
|
|||||||
class CBonusSelection;
|
class CBonusSelection;
|
||||||
|
|
||||||
|
|
||||||
class CampaignRimVideo : public CWindowObject
|
|
||||||
{
|
|
||||||
std::shared_ptr<VideoWidgetOnce> videoPlayer;
|
|
||||||
|
|
||||||
std::function<void()> closeCb;
|
|
||||||
|
|
||||||
void exit();
|
|
||||||
public:
|
|
||||||
CampaignRimVideo(VideoPath video, ImagePath rim, std::function<void()> closeCb);
|
|
||||||
|
|
||||||
void clickPressed(const Point & cursorPosition) override;
|
|
||||||
void keyPressed(EShortcut key) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Campaign screen where you can choose one out of three starting bonuses
|
/// Campaign screen where you can choose one out of three starting bonuses
|
||||||
class CBonusSelection : public CWindowObject
|
class CBonusSelection : public CWindowObject
|
||||||
{
|
{
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "CHighScoreScreen.h"
|
#include "CHighScoreScreen.h"
|
||||||
#include "CStatisticScreen.h"
|
#include "CStatisticScreen.h"
|
||||||
|
#include "CMainMenu.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/WindowHandler.h"
|
#include "../gui/WindowHandler.h"
|
||||||
#include "../gui/Shortcut.h"
|
#include "../gui/Shortcut.h"
|
||||||
@@ -170,6 +171,7 @@ void CHighScoreScreen::buttonResetClick()
|
|||||||
void CHighScoreScreen::buttonExitClick()
|
void CHighScoreScreen::buttonExitClick()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
CMM->playMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHighScoreInputScreen::CHighScoreInputScreen(bool won, HighScoreCalculation calc, const StatisticDataSet & statistic)
|
CHighScoreInputScreen::CHighScoreInputScreen(bool won, HighScoreCalculation calc, const StatisticDataSet & statistic)
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "../lobby/CSelectionBase.h"
|
#include "../lobby/CSelectionBase.h"
|
||||||
#include "../lobby/CLobbyScreen.h"
|
#include "../lobby/CLobbyScreen.h"
|
||||||
#include "../media/IMusicPlayer.h"
|
#include "../media/IMusicPlayer.h"
|
||||||
|
#include "../media/IVideoPlayer.h"
|
||||||
#include "../gui/CursorHandler.h"
|
#include "../gui/CursorHandler.h"
|
||||||
#include "../windows/GUIClasses.h"
|
#include "../windows/GUIClasses.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
@@ -117,7 +118,6 @@ void CMenuScreen::show(Canvas & to)
|
|||||||
|
|
||||||
void CMenuScreen::activate()
|
void CMenuScreen::activate()
|
||||||
{
|
{
|
||||||
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
|
|
||||||
CIntObject::activate();
|
CIntObject::activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,6 +300,35 @@ CMainMenu::~CMainMenu()
|
|||||||
GH.curInt = nullptr;
|
GH.curInt = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMainMenu::playIntroVideos()
|
||||||
|
{
|
||||||
|
auto playVideo = [](std::string video, bool rim, float scaleFactor, std::function<void(bool)> cb){
|
||||||
|
if(CCS->videoh->open(VideoPath::builtin(video), scaleFactor))
|
||||||
|
GH.windows().createAndPushWindow<VideoWindow>(VideoPath::builtin(video), rim ? ImagePath::builtin("INTRORIM") : ImagePath::builtin(""), true, scaleFactor, [cb](bool skipped){ cb(skipped); });
|
||||||
|
else
|
||||||
|
cb(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
playVideo("3DOLOGO.SMK", false, 1.25, [playVideo, this](bool skipped){
|
||||||
|
if(!skipped)
|
||||||
|
playVideo("NWCLOGO.SMK", false, 2, [playVideo, this](bool skipped){
|
||||||
|
if(!skipped)
|
||||||
|
playVideo("H3INTRO.SMK", true, 1, [this](bool skipped){
|
||||||
|
playMusic();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
playMusic();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
playMusic();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMainMenu::playMusic()
|
||||||
|
{
|
||||||
|
CCS->musich->playMusic(AudioPath::builtin("Music/MainMenu"), true, true);
|
||||||
|
}
|
||||||
|
|
||||||
void CMainMenu::activate()
|
void CMainMenu::activate()
|
||||||
{
|
{
|
||||||
// check if screen was resized while main menu was inactive - e.g. in gameplay mode
|
// check if screen was resized while main menu was inactive - e.g. in gameplay mode
|
||||||
|
@@ -142,6 +142,8 @@ class CMainMenu : public CIntObject, public IUpdateable, public std::enable_shar
|
|||||||
{
|
{
|
||||||
std::shared_ptr<CFilledTexture> backgroundAroundMenu;
|
std::shared_ptr<CFilledTexture> backgroundAroundMenu;
|
||||||
|
|
||||||
|
std::vector<VideoPath> videoPlayList;
|
||||||
|
|
||||||
CMainMenu(); //Use CMainMenu::create
|
CMainMenu(); //Use CMainMenu::create
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -162,6 +164,8 @@ public:
|
|||||||
|
|
||||||
static std::shared_ptr<CPicture> createPicture(const JsonNode & config);
|
static std::shared_ptr<CPicture> createPicture(const JsonNode & config);
|
||||||
|
|
||||||
|
void playIntroVideos();
|
||||||
|
void playMusic();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Simple window to enter the server's address.
|
/// Simple window to enter the server's address.
|
||||||
|
@@ -34,7 +34,7 @@ MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewMod
|
|||||||
pos.w = model->getPixelsVisibleDimensions().x;
|
pos.w = model->getPixelsVisibleDimensions().x;
|
||||||
pos.h = model->getPixelsVisibleDimensions().y;
|
pos.h = model->getPixelsVisibleDimensions().y;
|
||||||
|
|
||||||
addUsedEvents(LCLICK | SHOW_POPUP | DRAG | GESTURE | HOVER | MOVE | WHEEL);
|
addUsedEvents(LCLICK | SHOW_POPUP | DRAG | DRAG_POPUP | GESTURE | HOVER | MOVE | WHEEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & context)
|
void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & context)
|
||||||
@@ -101,6 +101,11 @@ void MapViewActions::mouseDragged(const Point & cursorPosition, const Point & la
|
|||||||
owner.onMapSwiped(lastUpdateDistance);
|
owner.onMapSwiped(lastUpdateDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapViewActions::mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance)
|
||||||
|
{
|
||||||
|
owner.onMapSwiped(lastUpdateDistance);
|
||||||
|
}
|
||||||
|
|
||||||
void MapViewActions::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
|
void MapViewActions::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
|
||||||
{
|
{
|
||||||
owner.onMapSwiped(lastUpdateDistance);
|
owner.onMapSwiped(lastUpdateDistance);
|
||||||
|
@@ -42,6 +42,7 @@ public:
|
|||||||
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
||||||
void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
||||||
void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
||||||
|
void mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
||||||
void wheelScrolled(int distance) override;
|
void wheelScrolled(int distance) override;
|
||||||
|
|
||||||
bool dragActive;
|
bool dragActive;
|
||||||
|
@@ -14,18 +14,12 @@
|
|||||||
class CEmptyVideoPlayer final : public IVideoPlayer
|
class CEmptyVideoPlayer final : public IVideoPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Plays video on top of the screen, returns only after playback is over
|
|
||||||
bool playIntroVideo(const VideoPath & name) override
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
void playSpellbookAnimation(const VideoPath & name, const Point & position) override
|
void playSpellbookAnimation(const VideoPath & name, const Point & position) override
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load video from specified path
|
/// Load video from specified path
|
||||||
std::unique_ptr<IVideoInstance> open(const VideoPath & name, bool scaleToScreen) override
|
std::unique_ptr<IVideoInstance> open(const VideoPath & name, float scaleFactor) override
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
|
@@ -173,18 +173,10 @@ void CVideoInstance::openVideo()
|
|||||||
openCodec(findVideoStream());
|
openCodec(findVideoStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVideoInstance::prepareOutput(bool scaleToScreenSize, bool useTextureOutput)
|
void CVideoInstance::prepareOutput(float scaleFactor, bool useTextureOutput)
|
||||||
{
|
{
|
||||||
//setup scaling
|
//setup scaling
|
||||||
if(scaleToScreenSize)
|
dimensions = Point(getCodecContext()->width * scaleFactor, getCodecContext()->height * scaleFactor) * GH.screenHandler().getScalingFactor();
|
||||||
{
|
|
||||||
dimensions.x = screen->w;
|
|
||||||
dimensions.y = screen->h;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dimensions = Point(getCodecContext()->width, getCodecContext()->height) * GH.screenHandler().getScalingFactor();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a place to put our YUV image on that screen
|
// Allocate a place to put our YUV image on that screen
|
||||||
if (useTextureOutput)
|
if (useTextureOutput)
|
||||||
@@ -352,10 +344,7 @@ FFMpegStream::~FFMpegStream()
|
|||||||
|
|
||||||
Point CVideoInstance::size()
|
Point CVideoInstance::size()
|
||||||
{
|
{
|
||||||
if(!getCurrentFrame())
|
return dimensions / GH.screenHandler().getScalingFactor();
|
||||||
throw std::runtime_error("Invalid video frame!");
|
|
||||||
|
|
||||||
return Point(getCurrentFrame()->width, getCurrentFrame()->height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVideoInstance::show(const Point & position, Canvas & canvas)
|
void CVideoInstance::show(const Point & position, Canvas & canvas)
|
||||||
@@ -575,7 +564,7 @@ std::pair<std::unique_ptr<ui8 []>, si64> CAudioInstance::extractAudio(const Vide
|
|||||||
return dat;
|
return dat;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool scale, bool stopOnKey)
|
bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool stopOnKey)
|
||||||
{
|
{
|
||||||
CVideoInstance instance;
|
CVideoInstance instance;
|
||||||
CAudioInstance audio;
|
CAudioInstance audio;
|
||||||
@@ -587,7 +576,7 @@ bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & po
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
instance.openVideo();
|
instance.openVideo();
|
||||||
instance.prepareOutput(scale, true);
|
instance.prepareOutput(1, true);
|
||||||
|
|
||||||
auto lastTimePoint = boost::chrono::steady_clock::now();
|
auto lastTimePoint = boost::chrono::steady_clock::now();
|
||||||
|
|
||||||
@@ -633,17 +622,12 @@ bool CVideoPlayer::openAndPlayVideoImpl(const VideoPath & name, const Point & po
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVideoPlayer::playIntroVideo(const VideoPath & name)
|
|
||||||
{
|
|
||||||
return openAndPlayVideoImpl(name, Point(0, 0), true, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVideoPlayer::playSpellbookAnimation(const VideoPath & name, const Point & position)
|
void CVideoPlayer::playSpellbookAnimation(const VideoPath & name, const Point & position)
|
||||||
{
|
{
|
||||||
openAndPlayVideoImpl(name, position * GH.screenHandler().getScalingFactor(), false, false, false);
|
openAndPlayVideoImpl(name, position * GH.screenHandler().getScalingFactor(), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, bool scaleToScreen)
|
std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, float scaleFactor)
|
||||||
{
|
{
|
||||||
auto result = std::make_unique<CVideoInstance>();
|
auto result = std::make_unique<CVideoInstance>();
|
||||||
|
|
||||||
@@ -651,7 +635,7 @@ std::unique_ptr<IVideoInstance> CVideoPlayer::open(const VideoPath & name, bool
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
result->openVideo();
|
result->openVideo();
|
||||||
result->prepareOutput(scaleToScreen, false);
|
result->prepareOutput(scaleFactor, false);
|
||||||
result->loadNextFrame(); // prepare 1st frame
|
result->loadNextFrame(); // prepare 1st frame
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@@ -80,7 +80,7 @@ class CVideoInstance final : public IVideoInstance, public FFMpegStream
|
|||||||
/// video playback current progress, in seconds
|
/// video playback current progress, in seconds
|
||||||
double frameTime = 0.0;
|
double frameTime = 0.0;
|
||||||
|
|
||||||
void prepareOutput(bool scaleToScreenSize, bool useTextureOutput);
|
void prepareOutput(float scaleFactor, bool useTextureOutput);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~CVideoInstance();
|
~CVideoInstance();
|
||||||
@@ -97,13 +97,12 @@ public:
|
|||||||
|
|
||||||
class CVideoPlayer final : public IVideoPlayer
|
class CVideoPlayer final : public IVideoPlayer
|
||||||
{
|
{
|
||||||
bool openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool scale, bool stopOnKey);
|
bool openAndPlayVideoImpl(const VideoPath & name, const Point & position, bool useOverlay, bool stopOnKey);
|
||||||
void openVideoFile(CVideoInstance & state, const VideoPath & fname);
|
void openVideoFile(CVideoInstance & state, const VideoPath & fname);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool playIntroVideo(const VideoPath & name) final;
|
|
||||||
void playSpellbookAnimation(const VideoPath & name, const Point & position) final;
|
void playSpellbookAnimation(const VideoPath & name, const Point & position) final;
|
||||||
std::unique_ptr<IVideoInstance> open(const VideoPath & name, bool scaleToScreen) final;
|
std::unique_ptr<IVideoInstance> open(const VideoPath & name, float scaleFactor) final;
|
||||||
std::pair<std::unique_ptr<ui8[]>, si64> getAudio(const VideoPath & videoToOpen) final;
|
std::pair<std::unique_ptr<ui8[]>, si64> getAudio(const VideoPath & videoToOpen) final;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -38,14 +38,11 @@ public:
|
|||||||
class IVideoPlayer : boost::noncopyable
|
class IVideoPlayer : boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Plays video on top of the screen, returns only after playback is over, aborts on input event
|
|
||||||
virtual bool playIntroVideo(const VideoPath & name) = 0;
|
|
||||||
|
|
||||||
/// Plays video on top of the screen, returns only after playback is over
|
/// Plays video on top of the screen, returns only after playback is over
|
||||||
virtual void playSpellbookAnimation(const VideoPath & name, const Point & position) = 0;
|
virtual void playSpellbookAnimation(const VideoPath & name, const Point & position) = 0;
|
||||||
|
|
||||||
/// Load video from specified path. Returns nullptr on failure
|
/// Load video from specified path. Returns nullptr on failure
|
||||||
virtual std::unique_ptr<IVideoInstance> open(const VideoPath & name, bool scaleToScreen) = 0;
|
virtual std::unique_ptr<IVideoInstance> open(const VideoPath & name, float scaleFactor) = 0;
|
||||||
|
|
||||||
/// Extracts audio data from provided video in wav format
|
/// Extracts audio data from provided video in wav format
|
||||||
virtual std::pair<std::unique_ptr<ui8[]>, si64> getAudio(const VideoPath & videoToOpen) = 0;
|
virtual std::pair<std::unique_ptr<ui8[]>, si64> getAudio(const VideoPath & videoToOpen) = 0;
|
||||||
|
@@ -17,7 +17,12 @@
|
|||||||
#include "../render/Canvas.h"
|
#include "../render/Canvas.h"
|
||||||
|
|
||||||
VideoWidgetBase::VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio)
|
VideoWidgetBase::VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio)
|
||||||
: playAudio(playAudio)
|
: VideoWidgetBase(position, video, playAudio, 1.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoWidgetBase::VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio, float scaleFactor)
|
||||||
|
: playAudio(playAudio), scaleFactor(scaleFactor)
|
||||||
{
|
{
|
||||||
addUsedEvents(TIME);
|
addUsedEvents(TIME);
|
||||||
pos += position;
|
pos += position;
|
||||||
@@ -28,7 +33,7 @@ VideoWidgetBase::~VideoWidgetBase() = default;
|
|||||||
|
|
||||||
void VideoWidgetBase::playVideo(const VideoPath & fileToPlay)
|
void VideoWidgetBase::playVideo(const VideoPath & fileToPlay)
|
||||||
{
|
{
|
||||||
videoInstance = CCS->videoh->open(fileToPlay, false);
|
videoInstance = CCS->videoh->open(fileToPlay, scaleFactor);
|
||||||
if (videoInstance)
|
if (videoInstance)
|
||||||
{
|
{
|
||||||
pos.w = videoInstance->size().x;
|
pos.w = videoInstance->size().x;
|
||||||
@@ -142,6 +147,12 @@ VideoWidgetOnce::VideoWidgetOnce(const Point & position, const VideoPath & video
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VideoWidgetOnce::VideoWidgetOnce(const Point & position, const VideoPath & video, bool playAudio, float scaleFactor, const std::function<void()> & callback)
|
||||||
|
: VideoWidgetBase(position, video, playAudio, scaleFactor)
|
||||||
|
, callback(callback)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void VideoWidgetOnce::onPlaybackFinished()
|
void VideoWidgetOnce::onPlaybackFinished()
|
||||||
{
|
{
|
||||||
callback();
|
callback();
|
||||||
|
@@ -22,6 +22,7 @@ class VideoWidgetBase : public CIntObject
|
|||||||
std::pair<std::unique_ptr<ui8[]>, si64> audioData = {nullptr, 0};
|
std::pair<std::unique_ptr<ui8[]>, si64> audioData = {nullptr, 0};
|
||||||
int audioHandle = -1;
|
int audioHandle = -1;
|
||||||
bool playAudio = false;
|
bool playAudio = false;
|
||||||
|
float scaleFactor = 1.0;
|
||||||
|
|
||||||
void loadAudio(const VideoPath & file);
|
void loadAudio(const VideoPath & file);
|
||||||
void startAudio();
|
void startAudio();
|
||||||
@@ -29,6 +30,7 @@ class VideoWidgetBase : public CIntObject
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio);
|
VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio);
|
||||||
|
VideoWidgetBase(const Point & position, const VideoPath & video, bool playAudio, float scaleFactor);
|
||||||
|
|
||||||
virtual void onPlaybackFinished() = 0;
|
virtual void onPlaybackFinished() = 0;
|
||||||
void playVideo(const VideoPath & video);
|
void playVideo(const VideoPath & video);
|
||||||
@@ -62,4 +64,5 @@ class VideoWidgetOnce final: public VideoWidgetBase
|
|||||||
void onPlaybackFinished() final;
|
void onPlaybackFinished() final;
|
||||||
public:
|
public:
|
||||||
VideoWidgetOnce(const Point & position, const VideoPath & video, bool playAudio, const std::function<void()> & callback);
|
VideoWidgetOnce(const Point & position, const VideoPath & video, bool playAudio, const std::function<void()> & callback);
|
||||||
|
VideoWidgetOnce(const Point & position, const VideoPath & video, bool playAudio, float scaleFactor, const std::function<void()> & callback);
|
||||||
};
|
};
|
||||||
|
@@ -1608,3 +1608,50 @@ void CObjectListWindow::keyPressed(EShortcut key)
|
|||||||
list->scrollTo(sel);
|
list->scrollTo(sel);
|
||||||
changeSelection(sel);
|
changeSelection(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VideoWindow::VideoWindow(VideoPath video, ImagePath rim, bool showBackground, float scaleFactor, std::function<void(bool skipped)> closeCb)
|
||||||
|
: CWindowObject(BORDERED | SHADOW_DISABLED | NEEDS_ANIMATED_BACKGROUND), closeCb(closeCb)
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION;
|
||||||
|
|
||||||
|
addUsedEvents(LCLICK | KEYBOARD);
|
||||||
|
|
||||||
|
if(!rim.empty())
|
||||||
|
{
|
||||||
|
videoPlayer = std::make_shared<VideoWidgetOnce>(Point(80, 186), video, true, [this](){ exit(false); });
|
||||||
|
pos = center(Rect(0, 0, 800, 600));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
videoPlayer = std::make_shared<VideoWidgetOnce>(Point(0, 0), video, true, scaleFactor, [this](){ exit(false); });
|
||||||
|
pos = center(Rect(0, 0, videoPlayer->pos.w, videoPlayer->pos.h));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(showBackground)
|
||||||
|
backgroundAroundWindow = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), Rect(-pos.x, -pos.y, GH.screenDimensions().x, GH.screenDimensions().y));
|
||||||
|
|
||||||
|
if(!rim.empty())
|
||||||
|
setBackground(rim);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoWindow::exit(bool skipped)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
if(closeCb)
|
||||||
|
closeCb(skipped);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoWindow::clickPressed(const Point & cursorPosition)
|
||||||
|
{
|
||||||
|
exit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoWindow::keyPressed(EShortcut key)
|
||||||
|
{
|
||||||
|
exit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoWindow::receiveEvent(const Point & position, int eventType) const
|
||||||
|
{
|
||||||
|
return true; // capture click also outside of window
|
||||||
|
}
|
||||||
|
@@ -43,6 +43,7 @@ class CAnimImage;
|
|||||||
class CFilledTexture;
|
class CFilledTexture;
|
||||||
class IImage;
|
class IImage;
|
||||||
class VideoWidget;
|
class VideoWidget;
|
||||||
|
class VideoWidgetOnce;
|
||||||
|
|
||||||
enum class EUserEvent;
|
enum class EUserEvent;
|
||||||
|
|
||||||
@@ -501,3 +502,18 @@ public:
|
|||||||
CThievesGuildWindow(const CGObjectInstance * _owner);
|
CThievesGuildWindow(const CGObjectInstance * _owner);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VideoWindow : public CWindowObject
|
||||||
|
{
|
||||||
|
std::shared_ptr<VideoWidgetOnce> videoPlayer;
|
||||||
|
std::shared_ptr<CFilledTexture> backgroundAroundWindow;
|
||||||
|
|
||||||
|
std::function<void(bool)> closeCb;
|
||||||
|
|
||||||
|
void exit(bool skipped);
|
||||||
|
public:
|
||||||
|
VideoWindow(VideoPath video, ImagePath rim, bool showBackground, float scaleFactor, std::function<void(bool)> closeCb);
|
||||||
|
|
||||||
|
void clickPressed(const Point & cursorPosition) override;
|
||||||
|
void keyPressed(EShortcut key) override;
|
||||||
|
bool receiveEvent(const Point & position, int eventType) const override;
|
||||||
|
};
|
||||||
|
@@ -245,8 +245,11 @@ void CRClickPopup::createAndPush(const CGObjectInstance * obj, const Point & p,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CRClickPopupInt::CRClickPopupInt(const std::shared_ptr<CIntObject> & our)
|
CRClickPopupInt::CRClickPopupInt(const std::shared_ptr<CIntObject> & our) :
|
||||||
|
dragDistance(Point(0, 0))
|
||||||
{
|
{
|
||||||
|
addUsedEvents(DRAG_POPUP);
|
||||||
|
|
||||||
CCS->curh->hide();
|
CCS->curh->hide();
|
||||||
inner = our;
|
inner = our;
|
||||||
addChild(our.get(), false);
|
addChild(our.get(), false);
|
||||||
@@ -257,6 +260,17 @@ CRClickPopupInt::~CRClickPopupInt()
|
|||||||
CCS->curh->show();
|
CCS->curh->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRClickPopupInt::mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance)
|
||||||
|
{
|
||||||
|
if(!settings["adventure"]["rightButtonDrag"].Bool())
|
||||||
|
return;
|
||||||
|
|
||||||
|
dragDistance += lastUpdateDistance;
|
||||||
|
|
||||||
|
if(dragDistance.length() > 16)
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
Point CInfoBoxPopup::toScreen(Point p)
|
Point CInfoBoxPopup::toScreen(Point p)
|
||||||
{
|
{
|
||||||
auto bounds = adventureInt->terrainAreaPixels();
|
auto bounds = adventureInt->terrainAreaPixels();
|
||||||
@@ -267,6 +281,18 @@ Point CInfoBoxPopup::toScreen(Point p)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInfoBoxPopup::mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance)
|
||||||
|
{
|
||||||
|
if(!settings["adventure"]["rightButtonDrag"].Bool())
|
||||||
|
return;
|
||||||
|
|
||||||
|
dragDistance += lastUpdateDistance;
|
||||||
|
|
||||||
|
if(dragDistance.length() > 16)
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
|
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
|
||||||
: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, ImagePath::builtin("TOWNQVBK"), toScreen(position))
|
: CWindowObject(RCLICK_POPUP | PLAYER_COLORED, ImagePath::builtin("TOWNQVBK"), toScreen(position))
|
||||||
{
|
{
|
||||||
@@ -275,6 +301,8 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGTownInstance * town)
|
|||||||
|
|
||||||
OBJECT_CONSTRUCTION;
|
OBJECT_CONSTRUCTION;
|
||||||
tooltip = std::make_shared<CTownTooltip>(Point(9, 10), iah);
|
tooltip = std::make_shared<CTownTooltip>(Point(9, 10), iah);
|
||||||
|
|
||||||
|
addUsedEvents(DRAG_POPUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
|
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
|
||||||
@@ -285,6 +313,8 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGHeroInstance * hero)
|
|||||||
|
|
||||||
OBJECT_CONSTRUCTION;
|
OBJECT_CONSTRUCTION;
|
||||||
tooltip = std::make_shared<CHeroTooltip>(Point(9, 10), iah);
|
tooltip = std::make_shared<CHeroTooltip>(Point(9, 10), iah);
|
||||||
|
|
||||||
|
addUsedEvents(DRAG_POPUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
|
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
|
||||||
@@ -295,6 +325,8 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGGarrison * garr)
|
|||||||
|
|
||||||
OBJECT_CONSTRUCTION;
|
OBJECT_CONSTRUCTION;
|
||||||
tooltip = std::make_shared<CArmyTooltip>(Point(9, 10), iah);
|
tooltip = std::make_shared<CArmyTooltip>(Point(9, 10), iah);
|
||||||
|
|
||||||
|
addUsedEvents(DRAG_POPUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGCreature * creature)
|
CInfoBoxPopup::CInfoBoxPopup(Point position, const CGCreature * creature)
|
||||||
@@ -302,6 +334,8 @@ CInfoBoxPopup::CInfoBoxPopup(Point position, const CGCreature * creature)
|
|||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION;
|
OBJECT_CONSTRUCTION;
|
||||||
tooltip = std::make_shared<CreatureTooltip>(Point(9, 10), creature);
|
tooltip = std::make_shared<CreatureTooltip>(Point(9, 10), creature);
|
||||||
|
|
||||||
|
addUsedEvents(DRAG_POPUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<WindowBase>
|
std::shared_ptr<WindowBase>
|
||||||
|
@@ -78,9 +78,13 @@ class CRClickPopupInt : public CRClickPopup
|
|||||||
{
|
{
|
||||||
std::shared_ptr<CIntObject> inner;
|
std::shared_ptr<CIntObject> inner;
|
||||||
|
|
||||||
|
Point dragDistance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CRClickPopupInt(const std::shared_ptr<CIntObject> & our);
|
CRClickPopupInt(const std::shared_ptr<CIntObject> & our);
|
||||||
~CRClickPopupInt();
|
~CRClickPopupInt();
|
||||||
|
|
||||||
|
void mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// popup on adventure map for town\hero and other objects with customized popup content
|
/// popup on adventure map for town\hero and other objects with customized popup content
|
||||||
@@ -89,11 +93,15 @@ class CInfoBoxPopup : public CWindowObject
|
|||||||
std::shared_ptr<CIntObject> tooltip;
|
std::shared_ptr<CIntObject> tooltip;
|
||||||
Point toScreen(Point pos);
|
Point toScreen(Point pos);
|
||||||
|
|
||||||
|
Point dragDistance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CInfoBoxPopup(Point position, const CGTownInstance * town);
|
CInfoBoxPopup(Point position, const CGTownInstance * town);
|
||||||
CInfoBoxPopup(Point position, const CGHeroInstance * hero);
|
CInfoBoxPopup(Point position, const CGHeroInstance * hero);
|
||||||
CInfoBoxPopup(Point position, const CGGarrison * garr);
|
CInfoBoxPopup(Point position, const CGGarrison * garr);
|
||||||
CInfoBoxPopup(Point position, const CGCreature * creature);
|
CInfoBoxPopup(Point position, const CGCreature * creature);
|
||||||
|
|
||||||
|
void mouseDraggedPopup(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// component selection window
|
/// component selection window
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "AdventureOptionsTab.h"
|
#include "AdventureOptionsTab.h"
|
||||||
|
|
||||||
|
#include "../../eventsSDL/InputHandler.h"
|
||||||
#include "../../../lib/filesystem/ResourcePath.h"
|
#include "../../../lib/filesystem/ResourcePath.h"
|
||||||
#include "../../gui/CGuiHandler.h"
|
#include "../../gui/CGuiHandler.h"
|
||||||
#include "../../widgets/Buttons.h"
|
#include "../../widgets/Buttons.h"
|
||||||
@@ -36,6 +37,9 @@ AdventureOptionsTab::AdventureOptionsTab()
|
|||||||
OBJECT_CONSTRUCTION;
|
OBJECT_CONSTRUCTION;
|
||||||
setRedrawParent(true);
|
setRedrawParent(true);
|
||||||
|
|
||||||
|
addConditional("touchscreen", GH.input().getCurrentInputMode() == InputMode::TOUCH);
|
||||||
|
addConditional("keyboardMouse", GH.input().getCurrentInputMode() == InputMode::KEYBOARD_AND_MOUSE);
|
||||||
|
addConditional("controller", GH.input().getCurrentInputMode() == InputMode::CONTROLLER);
|
||||||
#ifdef VCMI_MOBILE
|
#ifdef VCMI_MOBILE
|
||||||
addConditional("mobile", true);
|
addConditional("mobile", true);
|
||||||
addConditional("desktop", false);
|
addConditional("desktop", false);
|
||||||
@@ -126,6 +130,10 @@ AdventureOptionsTab::AdventureOptionsTab()
|
|||||||
{
|
{
|
||||||
return setBoolSetting("adventure", "leftButtonDrag", value);
|
return setBoolSetting("adventure", "leftButtonDrag", value);
|
||||||
});
|
});
|
||||||
|
addCallback("rightButtonDragChanged", [](bool value)
|
||||||
|
{
|
||||||
|
return setBoolSetting("adventure", "rightButtonDrag", value);
|
||||||
|
});
|
||||||
addCallback("smoothDraggingChanged", [](bool value)
|
addCallback("smoothDraggingChanged", [](bool value)
|
||||||
{
|
{
|
||||||
return setBoolSetting("adventure", "smoothDragging", value);
|
return setBoolSetting("adventure", "smoothDragging", value);
|
||||||
@@ -177,6 +185,10 @@ AdventureOptionsTab::AdventureOptionsTab()
|
|||||||
if (leftButtonDragCheckbox)
|
if (leftButtonDragCheckbox)
|
||||||
leftButtonDragCheckbox->setSelected(settings["adventure"]["leftButtonDrag"].Bool());
|
leftButtonDragCheckbox->setSelected(settings["adventure"]["leftButtonDrag"].Bool());
|
||||||
|
|
||||||
|
std::shared_ptr<CToggleButton> rightButtonDragCheckbox = widget<CToggleButton>("rightButtonDragCheckbox");
|
||||||
|
if (rightButtonDragCheckbox)
|
||||||
|
rightButtonDragCheckbox->setSelected(settings["adventure"]["rightButtonDrag"].Bool());
|
||||||
|
|
||||||
std::shared_ptr<CToggleButton> smoothDraggingCheckbox = widget<CToggleButton>("smoothDraggingCheckbox");
|
std::shared_ptr<CToggleButton> smoothDraggingCheckbox = widget<CToggleButton>("smoothDraggingCheckbox");
|
||||||
if (smoothDraggingCheckbox)
|
if (smoothDraggingCheckbox)
|
||||||
smoothDraggingCheckbox->setSelected(settings["adventure"]["smoothDragging"].Bool());
|
smoothDraggingCheckbox->setSelected(settings["adventure"]["smoothDragging"].Bool());
|
||||||
|
@@ -97,7 +97,9 @@ GeneralOptionsTab::GeneralOptionsTab()
|
|||||||
OBJECT_CONSTRUCTION;
|
OBJECT_CONSTRUCTION;
|
||||||
setRedrawParent(true);
|
setRedrawParent(true);
|
||||||
|
|
||||||
addConditional("touchscreen", GH.input().hasTouchInputDevice());
|
addConditional("touchscreen", GH.input().getCurrentInputMode() == InputMode::TOUCH);
|
||||||
|
addConditional("keyboardMouse", GH.input().getCurrentInputMode() == InputMode::KEYBOARD_AND_MOUSE);
|
||||||
|
addConditional("controller", GH.input().getCurrentInputMode() == InputMode::CONTROLLER);
|
||||||
#ifdef VCMI_MOBILE
|
#ifdef VCMI_MOBILE
|
||||||
addConditional("mobile", true);
|
addConditional("mobile", true);
|
||||||
addConditional("desktop", false);
|
addConditional("desktop", false);
|
||||||
|
@@ -45,6 +45,8 @@ SettingsMainWindow::SettingsMainWindow(BattleInterface * parentBattleUi) : Inter
|
|||||||
addCallback("closeWindow", [this](int) { backButtonCallback(); });
|
addCallback("closeWindow", [this](int) { backButtonCallback(); });
|
||||||
build(config);
|
build(config);
|
||||||
|
|
||||||
|
addUsedEvents(INPUT_MODE_CHANGE);
|
||||||
|
|
||||||
std::shared_ptr<CIntObject> background = widget<CIntObject>("background");
|
std::shared_ptr<CIntObject> background = widget<CIntObject>("background");
|
||||||
pos.w = background->pos.w;
|
pos.w = background->pos.w;
|
||||||
pos.h = background->pos.h;
|
pos.h = background->pos.h;
|
||||||
@@ -196,3 +198,8 @@ void SettingsMainWindow::onScreenResize()
|
|||||||
if (tab)
|
if (tab)
|
||||||
tab->updateResolutionSelector();
|
tab->updateResolutionSelector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsMainWindow::inputModeChanged(InputMode mode)
|
||||||
|
{
|
||||||
|
tabContentArea->reset();
|
||||||
|
}
|
||||||
|
@@ -42,5 +42,6 @@ public:
|
|||||||
|
|
||||||
void showAll(Canvas & to) override;
|
void showAll(Canvas & to) override;
|
||||||
void onScreenResize() override;
|
void onScreenResize() override;
|
||||||
|
void inputModeChanged(InputMode mode) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "../client/render/Graphics.h"
|
#include "../client/render/Graphics.h"
|
||||||
#include "../client/render/IRenderHandler.h"
|
#include "../client/render/IRenderHandler.h"
|
||||||
#include "../client/render/IScreenHandler.h"
|
#include "../client/render/IScreenHandler.h"
|
||||||
|
#include "../client/lobby/CBonusSelection.h"
|
||||||
#include "../client/windows/CMessage.h"
|
#include "../client/windows/CMessage.h"
|
||||||
#include "../client/windows/InfoWindows.h"
|
#include "../client/windows/InfoWindows.h"
|
||||||
|
|
||||||
@@ -65,7 +66,6 @@ static std::optional<std::string> criticalInitializationError;
|
|||||||
#ifndef VCMI_IOS
|
#ifndef VCMI_IOS
|
||||||
void processCommand(const std::string &message);
|
void processCommand(const std::string &message);
|
||||||
#endif
|
#endif
|
||||||
void playIntro();
|
|
||||||
[[noreturn]] static void quitApplication();
|
[[noreturn]] static void quitApplication();
|
||||||
static void mainLoop();
|
static void mainLoop();
|
||||||
|
|
||||||
@@ -319,13 +319,6 @@ int main(int argc, char * argv[])
|
|||||||
init();
|
init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!settings["session"]["headless"].Bool())
|
|
||||||
{
|
|
||||||
if(!vm.count("battle") && !vm.count("nointro") && settings["video"]["showIntro"].Bool())
|
|
||||||
playIntro();
|
|
||||||
GH.screenHandler().clearScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef VCMI_NO_THREADED_LOAD
|
#ifndef VCMI_NO_THREADED_LOAD
|
||||||
#ifdef VCMI_ANDROID // android loads the data quite slowly so we display native progressbar to prevent having only black screen for few seconds
|
#ifdef VCMI_ANDROID // android loads the data quite slowly so we display native progressbar to prevent having only black screen for few seconds
|
||||||
{
|
{
|
||||||
@@ -381,6 +374,12 @@ int main(int argc, char * argv[])
|
|||||||
{
|
{
|
||||||
auto mmenu = CMainMenu::create();
|
auto mmenu = CMainMenu::create();
|
||||||
GH.curInt = mmenu.get();
|
GH.curInt = mmenu.get();
|
||||||
|
|
||||||
|
bool playIntroVideo = !settings["session"]["headless"].Bool() && !vm.count("battle") && !vm.count("nointro") && settings["video"]["showIntro"].Bool();
|
||||||
|
if(playIntroVideo)
|
||||||
|
mmenu->playIntroVideos();
|
||||||
|
else
|
||||||
|
mmenu->playMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
@@ -402,18 +401,6 @@ int main(int argc, char * argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//plays intro, ends when intro is over or button has been pressed (handles events)
|
|
||||||
void playIntro()
|
|
||||||
{
|
|
||||||
if(!CCS->videoh->playIntroVideo(VideoPath::builtin("3DOLOGO.SMK")))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!CCS->videoh->playIntroVideo(VideoPath::builtin("NWCLOGO.SMK")))
|
|
||||||
return;
|
|
||||||
|
|
||||||
CCS->videoh->playIntroVideo(VideoPath::builtin("H3INTRO.SMK"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mainLoop()
|
static void mainLoop()
|
||||||
{
|
{
|
||||||
#ifndef VCMI_UNIX
|
#ifndef VCMI_UNIX
|
||||||
|
@@ -322,7 +322,7 @@
|
|||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
"default" : {},
|
"default" : {},
|
||||||
"required" : [ "heroMoveTime", "enemyMoveTime", "scrollSpeedPixels", "heroReminder", "quickCombat", "objectAnimation", "terrainAnimation", "forceQuickCombat", "borderScroll", "leftButtonDrag", "smoothDragging", "backgroundDimLevel", "hideBackground", "backgroundDimSmallWindows" ],
|
"required" : [ "heroMoveTime", "enemyMoveTime", "scrollSpeedPixels", "heroReminder", "quickCombat", "objectAnimation", "terrainAnimation", "forceQuickCombat", "borderScroll", "leftButtonDrag", "rightButtonDrag", "smoothDragging", "backgroundDimLevel", "hideBackground", "backgroundDimSmallWindows" ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"heroMoveTime" : {
|
"heroMoveTime" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
|
@@ -171,6 +171,10 @@
|
|||||||
"type" : "boolean",
|
"type" : "boolean",
|
||||||
"description" : "If used as creature spell, unit can cast this spell on itself"
|
"description" : "If used as creature spell, unit can cast this spell on itself"
|
||||||
},
|
},
|
||||||
|
"canCastWithoutSkip" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "If used the creature will not skip the turn after casting a spell."
|
||||||
|
},
|
||||||
"gainChance" : {
|
"gainChance" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"description" : "Chance for this spell to appear in Mage Guild of a specific faction",
|
"description" : "Chance for this spell to appear in Mage Guild of a specific faction",
|
||||||
|
@@ -364,13 +364,25 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "vcmi.adventureOptions.leftButtonDrag.hover",
|
"text": "vcmi.adventureOptions.leftButtonDrag.hover",
|
||||||
"created" : "desktop"
|
"created" : "keyboardMouse"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"text": "vcmi.adventureOptions.smoothDragging.hover"
|
"text": "vcmi.adventureOptions.smoothDragging.hover"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "verticalLayout",
|
||||||
|
"customType": "labelDescription",
|
||||||
|
"position": {"x": 225, "y": 415},
|
||||||
|
"items":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"text": "vcmi.adventureOptions.rightButtonDrag.hover",
|
||||||
|
"created" : "keyboardMouse"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "verticalLayout",
|
"type": "verticalLayout",
|
||||||
"customType": "checkbox",
|
"customType": "checkbox",
|
||||||
@@ -411,7 +423,7 @@
|
|||||||
"name": "leftButtonDragCheckbox",
|
"name": "leftButtonDragCheckbox",
|
||||||
"help": "vcmi.adventureOptions.leftButtonDrag",
|
"help": "vcmi.adventureOptions.leftButtonDrag",
|
||||||
"callback": "leftButtonDragChanged",
|
"callback": "leftButtonDragChanged",
|
||||||
"created" : "desktop"
|
"created" : "keyboardMouse"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "smoothDraggingCheckbox",
|
"name": "smoothDraggingCheckbox",
|
||||||
@@ -419,6 +431,20 @@
|
|||||||
"callback": "smoothDraggingChanged"
|
"callback": "smoothDraggingChanged"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "verticalLayout",
|
||||||
|
"customType": "checkbox",
|
||||||
|
"position": {"x": 190, "y": 413},
|
||||||
|
"items":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "rightButtonDragCheckbox",
|
||||||
|
"help": "vcmi.adventureOptions.rightButtonDrag",
|
||||||
|
"callback": "rightButtonDragChanged",
|
||||||
|
"created" : "keyboardMouse"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -65,6 +65,9 @@
|
|||||||
// If false, then creature can only cast this spell on other units
|
// If false, then creature can only cast this spell on other units
|
||||||
"canCastOnSelf" : false,
|
"canCastOnSelf" : false,
|
||||||
|
|
||||||
|
// If true the creature will not skip the turn after casting a spell
|
||||||
|
"canCastWithoutSkip": false,
|
||||||
|
|
||||||
// If true, spell won't be available on a map without water
|
// If true, spell won't be available on a map without water
|
||||||
"onlyOnWaterMap" : true,
|
"onlyOnWaterMap" : true,
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ public:
|
|||||||
|
|
||||||
virtual bool hasSchool(SpellSchool school) const = 0;
|
virtual bool hasSchool(SpellSchool school) const = 0;
|
||||||
virtual bool canCastOnSelf() const = 0;
|
virtual bool canCastOnSelf() const = 0;
|
||||||
|
virtual bool canCastWithoutSkip() const = 0;
|
||||||
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
|
virtual void forEachSchool(const SchoolCallback & cb) const = 0;
|
||||||
virtual int32_t getCost(const int32_t skillLevel) const = 0;
|
virtual int32_t getCost(const int32_t skillLevel) const = 0;
|
||||||
|
|
||||||
|
@@ -330,6 +330,7 @@ CUnitState::CUnitState():
|
|||||||
drainedMana(false),
|
drainedMana(false),
|
||||||
fear(false),
|
fear(false),
|
||||||
hadMorale(false),
|
hadMorale(false),
|
||||||
|
castSpellThisTurn(false),
|
||||||
ghost(false),
|
ghost(false),
|
||||||
ghostPending(false),
|
ghostPending(false),
|
||||||
movedThisRound(false),
|
movedThisRound(false),
|
||||||
@@ -362,6 +363,7 @@ CUnitState & CUnitState::operator=(const CUnitState & other)
|
|||||||
drainedMana = other.drainedMana;
|
drainedMana = other.drainedMana;
|
||||||
fear = other.fear;
|
fear = other.fear;
|
||||||
hadMorale = other.hadMorale;
|
hadMorale = other.hadMorale;
|
||||||
|
castSpellThisTurn = other.castSpellThisTurn;
|
||||||
ghost = other.ghost;
|
ghost = other.ghost;
|
||||||
ghostPending = other.ghostPending;
|
ghostPending = other.ghostPending;
|
||||||
movedThisRound = other.movedThisRound;
|
movedThisRound = other.movedThisRound;
|
||||||
@@ -532,7 +534,7 @@ bool CUnitState::hasClone() const
|
|||||||
|
|
||||||
bool CUnitState::canCast() const
|
bool CUnitState::canCast() const
|
||||||
{
|
{
|
||||||
return casts.canUse(1);//do not check specific cast abilities here
|
return casts.canUse(1) && !castSpellThisTurn;//do not check specific cast abilities here
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CUnitState::isCaster() const
|
bool CUnitState::isCaster() const
|
||||||
@@ -748,6 +750,7 @@ void CUnitState::serializeJson(JsonSerializeFormat & handler)
|
|||||||
handler.serializeBool("drainedMana", drainedMana);
|
handler.serializeBool("drainedMana", drainedMana);
|
||||||
handler.serializeBool("fear", fear);
|
handler.serializeBool("fear", fear);
|
||||||
handler.serializeBool("hadMorale", hadMorale);
|
handler.serializeBool("hadMorale", hadMorale);
|
||||||
|
handler.serializeBool("castSpellThisTurn", castSpellThisTurn);
|
||||||
handler.serializeBool("ghost", ghost);
|
handler.serializeBool("ghost", ghost);
|
||||||
handler.serializeBool("ghostPending", ghostPending);
|
handler.serializeBool("ghostPending", ghostPending);
|
||||||
handler.serializeBool("moved", movedThisRound);
|
handler.serializeBool("moved", movedThisRound);
|
||||||
@@ -782,6 +785,7 @@ void CUnitState::reset()
|
|||||||
drainedMana = false;
|
drainedMana = false;
|
||||||
fear = false;
|
fear = false;
|
||||||
hadMorale = false;
|
hadMorale = false;
|
||||||
|
castSpellThisTurn = false;
|
||||||
ghost = false;
|
ghost = false;
|
||||||
ghostPending = false;
|
ghostPending = false;
|
||||||
movedThisRound = false;
|
movedThisRound = false;
|
||||||
@@ -864,6 +868,7 @@ void CUnitState::afterNewRound()
|
|||||||
waitedThisTurn = false;
|
waitedThisTurn = false;
|
||||||
movedThisRound = false;
|
movedThisRound = false;
|
||||||
hadMorale = false;
|
hadMorale = false;
|
||||||
|
castSpellThisTurn = false;
|
||||||
fear = false;
|
fear = false;
|
||||||
drainedMana = false;
|
drainedMana = false;
|
||||||
counterAttacks.reset();
|
counterAttacks.reset();
|
||||||
|
@@ -141,6 +141,7 @@ public:
|
|||||||
bool drainedMana;
|
bool drainedMana;
|
||||||
bool fear;
|
bool fear;
|
||||||
bool hadMorale;
|
bool hadMorale;
|
||||||
|
bool castSpellThisTurn;
|
||||||
bool ghost;
|
bool ghost;
|
||||||
bool ghostPending;
|
bool ghostPending;
|
||||||
bool movedThisRound;
|
bool movedThisRound;
|
||||||
|
@@ -625,13 +625,6 @@ void CBonusSystemNode::limitBonuses(const BonusList &allBonuses, BonusList &out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TBonusListPtr CBonusSystemNode::limitBonuses(const BonusList &allBonuses) const
|
|
||||||
{
|
|
||||||
auto ret = std::make_shared<BonusList>();
|
|
||||||
limitBonuses(allBonuses, *ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBonusSystemNode::treeHasChanged()
|
void CBonusSystemNode::treeHasChanged()
|
||||||
{
|
{
|
||||||
treeChanged++;
|
treeChanged++;
|
||||||
|
@@ -55,6 +55,7 @@ private:
|
|||||||
void getAllBonusesRec(BonusList &out, const CSelector & selector) const;
|
void getAllBonusesRec(BonusList &out, const CSelector & selector) const;
|
||||||
TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit) const;
|
TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit) const;
|
||||||
std::shared_ptr<Bonus> getUpdatedBonus(const std::shared_ptr<Bonus> & b, const TUpdaterPtr & updater) const;
|
std::shared_ptr<Bonus> getUpdatedBonus(const std::shared_ptr<Bonus> & b, const TUpdaterPtr & updater) const;
|
||||||
|
void limitBonuses(const BonusList &allBonuses, BonusList &out) const; //out will bo populed with bonuses that are not limited here
|
||||||
|
|
||||||
void getRedParents(TCNodes &out) const; //retrieves list of red parent nodes (nodes bonuses propagate from)
|
void getRedParents(TCNodes &out) const; //retrieves list of red parent nodes (nodes bonuses propagate from)
|
||||||
void getRedAncestors(TCNodes &out) const;
|
void getRedAncestors(TCNodes &out) const;
|
||||||
@@ -84,8 +85,6 @@ public:
|
|||||||
explicit CBonusSystemNode(ENodeTypes NodeType);
|
explicit CBonusSystemNode(ENodeTypes NodeType);
|
||||||
virtual ~CBonusSystemNode();
|
virtual ~CBonusSystemNode();
|
||||||
|
|
||||||
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 convenience
|
|
||||||
TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const override;
|
TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const override;
|
||||||
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
|
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
|
||||||
|
|
||||||
|
@@ -17,9 +17,7 @@ class DLL_LINKAGE IBonusBearer
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//new bonusing node interface
|
//new bonusing node interface
|
||||||
// * selector is predicate that tests if HeroBonus matches our criteria
|
// * selector is predicate that tests if Bonus matches our criteria
|
||||||
// * root is node on which call was made (nullptr will be replaced with this)
|
|
||||||
//interface
|
|
||||||
IBonusBearer() = default;
|
IBonusBearer() = default;
|
||||||
virtual ~IBonusBearer() = default;
|
virtual ~IBonusBearer() = default;
|
||||||
virtual TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const = 0;
|
virtual TConstBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const = 0;
|
||||||
|
@@ -2209,6 +2209,7 @@ void StartAction::applyGs(CGameState *gs)
|
|||||||
st->waiting = false;
|
st->waiting = false;
|
||||||
st->defendingAnim = false;
|
st->defendingAnim = false;
|
||||||
st->movedThisRound = true;
|
st->movedThisRound = true;
|
||||||
|
st->castSpellThisTurn = ba.actionType == EActionType::MONSTER_SPELL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -298,6 +298,11 @@ bool CSpell::canCastOnSelf() const
|
|||||||
return castOnSelf;
|
return castOnSelf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSpell::canCastWithoutSkip() const
|
||||||
|
{
|
||||||
|
return castWithoutSkip;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string & CSpell::getIconImmune() const
|
const std::string & CSpell::getIconImmune() const
|
||||||
{
|
{
|
||||||
return iconImmune;
|
return iconImmune;
|
||||||
@@ -779,6 +784,7 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
spell->castOnSelf = json["canCastOnSelf"].Bool();
|
spell->castOnSelf = json["canCastOnSelf"].Bool();
|
||||||
|
spell->castWithoutSkip = json["canCastWithoutSkip"].Bool();
|
||||||
spell->level = static_cast<si32>(json["level"].Integer());
|
spell->level = static_cast<si32>(json["level"].Integer());
|
||||||
spell->power = static_cast<si32>(json["power"].Integer());
|
spell->power = static_cast<si32>(json["power"].Integer());
|
||||||
|
|
||||||
|
@@ -167,6 +167,7 @@ public:
|
|||||||
|
|
||||||
bool hasSchool(SpellSchool school) const override;
|
bool hasSchool(SpellSchool school) const override;
|
||||||
bool canCastOnSelf() const override;
|
bool canCastOnSelf() const override;
|
||||||
|
bool canCastWithoutSkip() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls cb for each school this spell belongs to
|
* Calls cb for each school this spell belongs to
|
||||||
@@ -296,6 +297,7 @@ private:
|
|||||||
bool combat; //is this spell combat (true) or adventure (false)
|
bool combat; //is this spell combat (true) or adventure (false)
|
||||||
bool creatureAbility; //if true, only creatures can use this spell
|
bool creatureAbility; //if true, only creatures can use this spell
|
||||||
bool castOnSelf; // if set, creature caster can cast this spell on itself
|
bool castOnSelf; // if set, creature caster can cast this spell on itself
|
||||||
|
bool castWithoutSkip; // if set the creature will not skip the turn after casting a spell
|
||||||
si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
|
si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
|
||||||
|
|
||||||
std::unique_ptr<spells::ISpellMechanicsFactory> mechanics;//(!) do not serialize
|
std::unique_ptr<spells::ISpellMechanicsFactory> mechanics;//(!) do not serialize
|
||||||
|
@@ -565,6 +565,19 @@ void BattleFlowProcessor::onActionMade(const CBattleInfoCallback & battle, const
|
|||||||
if(battle.battleGetTacticDist() != 0)
|
if(battle.battleGetTacticDist() != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// creature will not skip the turn after casting a spell if spell uses canCastWithoutSkip
|
||||||
|
if(ba.actionType == EActionType::MONSTER_SPELL)
|
||||||
|
{
|
||||||
|
assert(activeStack != nullptr);
|
||||||
|
assert(actedStack != nullptr);
|
||||||
|
|
||||||
|
if(actedStack->castSpellThisTurn && SpellID(ba.spell).toSpell()->canCastWithoutSkip())
|
||||||
|
{
|
||||||
|
setActiveStack(battle, actedStack);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ba.isUnitAction())
|
if (ba.isUnitAction())
|
||||||
{
|
{
|
||||||
assert(activeStack != nullptr);
|
assert(activeStack != nullptr);
|
||||||
|
@@ -47,6 +47,7 @@ public:
|
|||||||
MOCK_CONST_METHOD0(isSpecial, bool());
|
MOCK_CONST_METHOD0(isSpecial, bool());
|
||||||
MOCK_CONST_METHOD0(isMagical, bool());
|
MOCK_CONST_METHOD0(isMagical, bool());
|
||||||
MOCK_CONST_METHOD0(canCastOnSelf, bool());
|
MOCK_CONST_METHOD0(canCastOnSelf, bool());
|
||||||
|
MOCK_CONST_METHOD0(canCastWithoutSkip, bool());
|
||||||
MOCK_CONST_METHOD1(hasSchool, bool(SpellSchool));
|
MOCK_CONST_METHOD1(hasSchool, bool(SpellSchool));
|
||||||
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
|
MOCK_CONST_METHOD1(forEachSchool, void(const SchoolCallback &));
|
||||||
MOCK_CONST_METHOD0(getCastSound, const std::string &());
|
MOCK_CONST_METHOD0(getCastSound, const std::string &());
|
||||||
|
Reference in New Issue
Block a user