Browse Source

Merge pull request #2774 from IvanSavenko/beta_bugfixing

(1.3.2) Beta bugfixing
Ivan Savenko 2 years ago
parent
commit
5d67481aaf

+ 2 - 0
client/battle/BattleActionsController.cpp

@@ -24,6 +24,7 @@
 #include "../gui/CIntObject.h"
 #include "../gui/WindowHandler.h"
 #include "../windows/CCreatureWindow.h"
+#include "../windows/InfoWindows.h"
 
 #include "../../CCallback.h"
 #include "../../lib/CConfigHandler.h"
@@ -1003,6 +1004,7 @@ void BattleActionsController::onHexRightClicked(BattleHex clickedHex)
 	if (spellcastingModeActive() || isCurrentStackInSpellcastMode)
 	{
 		endCastingSpell();
+		CRClickPopup::createAndPush(CGI->generaltexth->translate("core.genrltxt.731")); // spell cancelled
 		return;
 	}
 

+ 18 - 3
client/battle/BattleFieldController.cpp

@@ -128,6 +128,9 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
 	attackCursors = std::make_shared<CAnimation>("CRCOMBAT");
 	attackCursors->preload();
 
+	spellCursors = std::make_shared<CAnimation>("CRSPELL");
+	spellCursors->preload();
+
 	initializeHexEdgeMaskToFrameIndex();
 
 	rangedFullDamageLimitImages = std::make_shared<CAnimation>("battle/rangeHighlights/rangeHighlightsGreen.json");
@@ -888,10 +891,22 @@ void BattleFieldController::show(Canvas & to)
 
 	if (isActive() && isGesturing() && getHoveredHex() != BattleHex::INVALID)
 	{
-		auto cursorIndex = CCS->curh->get<Cursor::Combat>();
-		auto imageIndex = static_cast<size_t>(cursorIndex);
+		auto combatCursorIndex = CCS->curh->get<Cursor::Combat>();
+		if (combatCursorIndex)
+		{
+			auto combatImageIndex = static_cast<size_t>(*combatCursorIndex);
+			to.draw(attackCursors->getImage(combatImageIndex), hexPositionAbsolute(getHoveredHex()).center() - CCS->curh->getPivotOffsetCombat(combatImageIndex));
+			return;
+		}
+
+		auto spellCursorIndex = CCS->curh->get<Cursor::Spellcast>();
+		if (spellCursorIndex)
+		{
+			auto spellImageIndex = static_cast<size_t>(*spellCursorIndex);
+			to.draw(spellCursors->getImage(spellImageIndex), hexPositionAbsolute(getHoveredHex()).center() - CCS->curh->getPivotOffsetSpellcast());
+			return;
+		}
 
-		to.draw(attackCursors->getImage(imageIndex), hexPositionAbsolute(getHoveredHex()).center() - CCS->curh->getPivotOffsetCombat(imageIndex));
 	}
 }
 

+ 1 - 0
client/battle/BattleFieldController.h

@@ -37,6 +37,7 @@ class BattleFieldController : public CIntObject
 	std::shared_ptr<CAnimation> shootingRangeLimitImages;
 
 	std::shared_ptr<CAnimation> attackCursors;
+	std::shared_ptr<CAnimation> spellCursors;
 
 	/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
 	std::unique_ptr<Canvas> backgroundWithHexes;

+ 3 - 3
client/gui/CursorHandler.h

@@ -125,7 +125,6 @@ class CursorHandler final
 
 	void changeGraphic(Cursor::Type type, size_t index);
 
-	Point getPivotOffsetSpellcast();
 	Point getPivotOffset();
 
 	void updateSpellcastCursor();
@@ -153,7 +152,7 @@ public:
 
 	/// Returns current index of cursor
 	template<typename Index>
-	Index get()
+	std::optional<Index> get()
 	{
 		bool typeValid = true;
 
@@ -164,9 +163,10 @@ public:
 
 		if (typeValid)
 			return static_cast<Index>(frame);
-		return Index::POINTER;
+		return std::nullopt;
 	}
 
+	Point getPivotOffsetSpellcast();
 	Point getPivotOffsetDefault(size_t index);
 	Point getPivotOffsetMap(size_t index);
 	Point getPivotOffsetCombat(size_t index);

+ 3 - 5
lib/rewardable/Interface.cpp

@@ -140,13 +140,11 @@ void Rewardable::Interface::grantRewardAfterLevelup(IGameCallback * cb, const Re
 		caster.setActualCaster(hero);
 		caster.setSpellSchoolLevel(info.reward.spellCast.second);
 		cb->castSpell(&caster, info.reward.spellCast.first, int3{-1, -1, -1});
-		
-		if(info.reward.removeObject)
-			logMod->warn("Removal of object with spell casts is not supported!");
 	}
-	else if(info.reward.removeObject) //FIXME: object can't track spell cancel or finish, so removeObject leads to crash
+
+	if(info.reward.removeObject)
 		if(auto * instance = dynamic_cast<const CGObjectInstance*>(this))
-			cb->removeObject(instance);
+			cb->removeAfterVisit(instance);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 6 - 0
server/CGameHandler.cpp

@@ -6120,6 +6120,12 @@ void CGameHandler::runBattle()
 					sendAndApply(&pack);
 				}
 			}
+
+			// send empty event to client
+			// temporary(?) workaround to force animations to trigger
+			StacksInjured fakeEvent;
+			sendAndApply(&fakeEvent);
+
 		}
 
 		stackEnchantedTrigger(stack);

+ 17 - 5
server/PlayerMessageProcessor.cpp

@@ -211,15 +211,27 @@ void PlayerMessageProcessor::cheatGiveMachines(PlayerColor player, const CGHeroI
 		gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::FIRST_AID_TENT], ArtifactPosition::MACH3);
 }
 
-void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHeroInstance * hero)
+void PlayerMessageProcessor::cheatGiveArtifacts(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words)
 {
 	if (!hero)
 		return;
 
-	for(int g = 7; g < VLC->arth->objects.size(); ++g) //including artifacts from mods
+	if (!words.empty())
 	{
-		if(VLC->arth->objects[g]->canBePutAt(hero))
-			gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[g], ArtifactPosition::FIRST_AVAILABLE);
+		for (auto const & word : words)
+		{
+			auto artID = VLC->modh->identifiers.getIdentifier(CModHandler::scopeGame(), "artifact", word, false);
+			if(artID &&  VLC->arth->objects[*artID])
+				gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[*artID], ArtifactPosition::FIRST_AVAILABLE);
+		}
+	}
+	else
+	{
+		for(int g = 7; g < VLC->arth->objects.size(); ++g) //including artifacts from mods
+		{
+			if(VLC->arth->objects[g]->canBePutAt(hero))
+				gameHandler->giveHeroNewArtifact(hero, VLC->arth->objects[g], ArtifactPosition::FIRST_AVAILABLE);
+		}
 	}
 }
 
@@ -432,7 +444,7 @@ void PlayerMessageProcessor::executeCheatCode(const std::string & cheatName, Pla
 	const auto & doCheatGiveArmyCustom = [&]() { cheatGiveArmy(player, hero, words); };
 	const auto & doCheatGiveArmyFixed = [&](std::vector<std::string> customWords) { cheatGiveArmy(player, hero, customWords); };
 	const auto & doCheatGiveMachines = [&]() { cheatGiveMachines(player, hero); };
-	const auto & doCheatGiveArtifacts = [&]() { cheatGiveArtifacts(player, hero); };
+	const auto & doCheatGiveArtifacts = [&]() { cheatGiveArtifacts(player, hero, words); };
 	const auto & doCheatLevelup = [&]() { cheatLevelup(player, hero, words); };
 	const auto & doCheatExperience = [&]() { cheatExperience(player, hero, words); };
 	const auto & doCheatMovement = [&]() { cheatMovement(player, hero, words); };

+ 1 - 1
server/PlayerMessageProcessor.h

@@ -31,7 +31,7 @@ class PlayerMessageProcessor
 	void cheatBuildTown(PlayerColor player, const CGTownInstance * town);
 	void cheatGiveArmy(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);
 	void cheatGiveMachines(PlayerColor player, const CGHeroInstance * hero);
-	void cheatGiveArtifacts(PlayerColor player, const CGHeroInstance * hero);
+	void cheatGiveArtifacts(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);
 	void cheatLevelup(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);
 	void cheatExperience(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);
 	void cheatMovement(PlayerColor player, const CGHeroInstance * hero, std::vector<std::string> words);