瀏覽代碼

Merge pull request #5061 from IvanSavenko/bugfixing_beta

Fixes for issues found in current beta
Ivan Savenko 10 月之前
父節點
當前提交
5560467cc4

+ 2 - 1
client/NetPacksClient.cpp

@@ -430,9 +430,10 @@ void ApplyClientNetPackVisitor::visitPlayerEndsGame(PlayerEndsGame & pack)
 {
 	callAllInterfaces(cl, &IGameEventsReceiver::gameOver, pack.player, pack.victoryLossCheckResult);
 
+	bool localHumanWinsGame = vstd::contains(cl.playerint, pack.player) && cl.getPlayerState(pack.player)->human && pack.victoryLossCheckResult.victory();
 	bool lastHumanEndsGame = CSH->howManyPlayerInterfaces() == 1 && vstd::contains(cl.playerint, pack.player) && cl.getPlayerState(pack.player)->human && !settings["session"]["spectate"].Bool();
 
-	if(lastHumanEndsGame)
+	if(lastHumanEndsGame || localHumanWinsGame)
 	{
 		assert(adventureInt);
 		if(adventureInt)

+ 1 - 1
client/render/IImage.h

@@ -115,7 +115,7 @@ public:
 
 	virtual std::shared_ptr<const ISharedImage> horizontalFlip() const = 0;
 	virtual std::shared_ptr<const ISharedImage> verticalFlip() const = 0;
-	virtual std::shared_ptr<const ISharedImage> scaleInteger(int factor, SDL_Palette * palette) const = 0;
+	virtual std::shared_ptr<const ISharedImage> scaleInteger(int factor, SDL_Palette * palette, EImageBlitMode blitMode) const = 0;
 	virtual std::shared_ptr<const ISharedImage> scaleTo(const Point & size, SDL_Palette * palette) const = 0;
 
 

+ 1 - 1
client/renderSDL/CBitmapFont.cpp

@@ -201,7 +201,7 @@ CBitmapFont::CBitmapFont(const std::string & filename):
 		static const std::map<std::string, EScalingAlgorithm> filterNameToEnum = {
 			{ "nearest", EScalingAlgorithm::NEAREST},
 			{ "bilinear", EScalingAlgorithm::BILINEAR},
-			{ "xbrz", EScalingAlgorithm::XBRZ}
+			{ "xbrz", EScalingAlgorithm::XBRZ_ALPHA}
 		};
 
 		auto filterName = settings["video"]["fontUpscalingFilter"].String();

+ 10 - 4
client/renderSDL/SDLImage.cpp

@@ -278,7 +278,7 @@ void SDLImageShared::optimizeSurface()
 	}
 }
 
-std::shared_ptr<const ISharedImage> SDLImageShared::scaleInteger(int factor, SDL_Palette * palette) const
+std::shared_ptr<const ISharedImage> SDLImageShared::scaleInteger(int factor, SDL_Palette * palette, EImageBlitMode mode) const
 {
 	if (factor <= 0)
 		throw std::runtime_error("Unable to scale by integer value of " + std::to_string(factor));
@@ -293,7 +293,13 @@ std::shared_ptr<const ISharedImage> SDLImageShared::scaleInteger(int factor, SDL
 	if(preScaleFactor == factor)
 		return shared_from_this();
 	else if(preScaleFactor == 1)
-		scaled = CSDL_Ext::scaleSurfaceIntegerFactor(surf, factor, EScalingAlgorithm::XBRZ);
+	{
+		// dump heuristics to differentiate tileable UI elements from map object / combat assets
+		if (mode == EImageBlitMode::OPAQUE || mode == EImageBlitMode::COLORKEY || mode == EImageBlitMode::SIMPLE)
+			scaled = CSDL_Ext::scaleSurfaceIntegerFactor(surf, factor, EScalingAlgorithm::XBRZ_OPAQUE);
+		else
+			scaled = CSDL_Ext::scaleSurfaceIntegerFactor(surf, factor, EScalingAlgorithm::XBRZ_ALPHA);
+	}
 	else
 		scaled = CSDL_Ext::scaleSurface(surf, (surf->w / preScaleFactor) * factor, (surf->h / preScaleFactor) * factor);
 
@@ -589,12 +595,12 @@ void SDLImageRGB::scaleTo(const Point & size)
 
 void SDLImageIndexed::scaleInteger(int factor)
 {
-	image = image->scaleInteger(factor, currentPalette);
+	image = image->scaleInteger(factor, currentPalette, blitMode);
 }
 
 void SDLImageRGB::scaleInteger(int factor)
 {
-	image = image->scaleInteger(factor, nullptr);
+	image = image->scaleInteger(factor, nullptr, blitMode);
 }
 
 void SDLImageRGB::exportBitmap(const boost::filesystem::path & path) const

+ 1 - 1
client/renderSDL/SDLImage.h

@@ -60,7 +60,7 @@ public:
 	std::shared_ptr<IImage> createImageReference(EImageBlitMode mode) const override;
 	std::shared_ptr<const ISharedImage> horizontalFlip() const override;
 	std::shared_ptr<const ISharedImage> verticalFlip() const override;
-	std::shared_ptr<const ISharedImage> scaleInteger(int factor, SDL_Palette * palette) const override;
+	std::shared_ptr<const ISharedImage> scaleInteger(int factor, SDL_Palette * palette, EImageBlitMode blitMode) const override;
 	std::shared_ptr<const ISharedImage> scaleTo(const Point & size, SDL_Palette * palette) const override;
 
 	friend class SDLImageLoader;

+ 8 - 3
client/renderSDL/SDL_Extensions.cpp

@@ -683,12 +683,17 @@ SDL_Surface * CSDL_Ext::scaleSurfaceIntegerFactor(SDL_Surface * surf, int factor
 		case EScalingAlgorithm::BILINEAR:
 			xbrz::bilinearScale(srcPixels, intermediate->w, intermediate->h, dstPixels, ret->w, ret->h);
 			break;
-		case EScalingAlgorithm::XBRZ:
-			tbb::parallel_for(tbb::blocked_range<size_t>(0, intermediate->h, granulation), [factor, srcPixels, dstPixels, intermediate](const tbb::blocked_range<size_t> & r)
+		case EScalingAlgorithm::XBRZ_ALPHA:
+		case EScalingAlgorithm::XBRZ_OPAQUE:
+		{
+			auto format = algorithm == EScalingAlgorithm::XBRZ_OPAQUE ? xbrz::ColorFormat::ARGB_CLAMPED : xbrz::ColorFormat::ARGB;
+			tbb::parallel_for(tbb::blocked_range<size_t>(0, intermediate->h, granulation), [factor, srcPixels, dstPixels, intermediate, format](const tbb::blocked_range<size_t> & r)
 			{
-				xbrz::scale(factor, srcPixels, dstPixels, intermediate->w, intermediate->h, xbrz::ColorFormat::ARGB, {}, r.begin(), r.end());
+
+				xbrz::scale(factor, srcPixels, dstPixels, intermediate->w, intermediate->h, format, {}, r.begin(), r.end());
 			});
 			break;
+		}
 		default:
 			throw std::runtime_error("invalid scaling algorithm!");
 	}

+ 2 - 1
client/renderSDL/SDL_Extensions.h

@@ -31,7 +31,8 @@ enum class EScalingAlgorithm : int8_t
 {
 	NEAREST,
 	BILINEAR,
-	XBRZ
+	XBRZ_OPAQUE, // xbrz, image edges are considered to have same color as pixel inside image
+	XBRZ_ALPHA // xbrz, image edges are considered to be transparent
 };
 
 namespace CSDL_Ext

+ 0 - 5
client/windows/settings/SettingsMainWindow.cpp

@@ -198,8 +198,3 @@ void SettingsMainWindow::onScreenResize()
 	if (tab)
 		tab->updateResolutionSelector();
 }
-
-void SettingsMainWindow::inputModeChanged(InputMode mode)
-{
-	tabContentArea->reset();
-}

+ 0 - 1
client/windows/settings/SettingsMainWindow.h

@@ -42,6 +42,5 @@ public:
 
 	void showAll(Canvas & to) override;
 	void onScreenResize() override;
-	void inputModeChanged(InputMode mode) override;
 };
 

+ 17 - 0
client/xBRZ/xbrz.cpp

@@ -1195,6 +1195,22 @@ void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth
             }
             break;
 
+        case ColorFormat::ARGB_CLAMPED:
+            switch (factor)
+            {
+                case 2:
+                    return scaleImage<Scaler2x<ColorGradientARGB>, ColorDistanceARGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+                case 3:
+                    return scaleImage<Scaler3x<ColorGradientARGB>, ColorDistanceARGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+                case 4:
+                    return scaleImage<Scaler4x<ColorGradientARGB>, ColorDistanceARGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+                case 5:
+                    return scaleImage<Scaler5x<ColorGradientARGB>, ColorDistanceARGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+                case 6:
+                    return scaleImage<Scaler6x<ColorGradientARGB>, ColorDistanceARGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast);
+            }
+            break;
+
         case ColorFormat::ARGB:
             switch (factor)
             {
@@ -1238,6 +1254,7 @@ bool xbrz::equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, doub
         case ColorFormat::RGB:
             return ColorDistanceRGB::dist(col1, col2, luminanceWeight) < equalColorTolerance;
         case ColorFormat::ARGB:
+        case ColorFormat::ARGB_CLAMPED:
             return ColorDistanceARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance;
         case ColorFormat::ARGB_UNBUFFERED:
             return ColorDistanceUnbufferedARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance;

+ 1 - 0
client/xBRZ/xbrz.h

@@ -44,6 +44,7 @@ enum class ColorFormat //from high bits -> low bits, 8 bit per channel
 {
     RGB,  //8 bit for each red, green, blue, upper 8 bits unused
     ARGB, //including alpha channel, BGRA byte order on little-endian machines
+    ARGB_CLAMPED, // like ARGB, but edges are treated as opaque, with same color as edge
     ARGB_UNBUFFERED, //like ARGB, but without the one-time buffer creation overhead (ca. 100 - 300 ms) at the expense of a slightly slower scaling time
 };
 

+ 30 - 21
launcher/modManager/cmodlistview_moc.cpp

@@ -441,9 +441,10 @@ void CModListView::selectMod(const QModelIndex & index)
 		Helper::enableScrollBySwiping(ui->modInfoBrowser);
 		Helper::enableScrollBySwiping(ui->changelogBrowser);
 
-		QStringList notInstalledDependencies = this->getModsToInstall(modName);
-		QStringList unavailableDependencies = this->findUnavailableMods(notInstalledDependencies);
+		QStringList notInstalledDependencies = getModsToInstall(modName);
+		QStringList unavailableDependencies = findUnavailableMods(notInstalledDependencies);
 		bool translationMismatch = 	mod.isTranslation() && CGeneralTextHandler::getPreferredLanguage() != mod.getBaseLanguage().toStdString();
+		bool modIsBeingDownloaded = enqueuedModDownloads.contains(mod.getID());
 
 		ui->disableButton->setVisible(modStateModel->isModInstalled(mod.getID()) && modStateModel->isModEnabled(mod.getID()));
 		ui->enableButton->setVisible(modStateModel->isModInstalled(mod.getID()) && !modStateModel->isModEnabled(mod.getID()));
@@ -454,9 +455,9 @@ void CModListView::selectMod(const QModelIndex & index)
 		// Block buttons if action is not allowed at this time
 		ui->disableButton->setEnabled(true);
 		ui->enableButton->setEnabled(notInstalledDependencies.empty() && !translationMismatch);
-		ui->installButton->setEnabled(unavailableDependencies.empty());
+		ui->installButton->setEnabled(unavailableDependencies.empty() && !modIsBeingDownloaded);
 		ui->uninstallButton->setEnabled(true);
-		ui->updateButton->setEnabled(unavailableDependencies.empty());
+		ui->updateButton->setEnabled(unavailableDependencies.empty() && !modIsBeingDownloaded);
 
 		loadScreenshots();
 	}
@@ -544,9 +545,6 @@ QStringList CModListView::getModsToInstall(QString mod)
 		candidates.pop_back();
 		processed.push_back(potentialToInstall);
 
-		if (modStateModel->isModExists(potentialToInstall) && modStateModel->isModInstalled(potentialToInstall))
-			continue;
-
 		if (modStateModel->isSubmod(potentialToInstall))
 		{
 			QString topParent = modStateModel->getTopParent(potentialToInstall);
@@ -560,7 +558,8 @@ QStringList CModListView::getModsToInstall(QString mod)
 				potentialToInstall = modStateModel->getTopParent(potentialToInstall);
 		}
 
-		result.push_back(potentialToInstall);
+		if (modStateModel->isModExists(potentialToInstall) && !modStateModel->isModInstalled(potentialToInstall))
+			result.push_back(potentialToInstall);
 
 		if (modStateModel->isModExists(potentialToInstall))
 		{
@@ -580,6 +579,8 @@ void CModListView::on_updateButton_clicked()
 {
 	QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
 	doUpdateMod(modName);
+
+	ui->updateButton->setEnabled(false);
 }
 
 void CModListView::doUpdateMod(const QString & modName)
@@ -587,14 +588,14 @@ void CModListView::doUpdateMod(const QString & modName)
 	auto targetMod = modStateModel->getMod(modName);
 
 	if(targetMod.isUpdateAvailable())
-		downloadFile(modName + ".zip", targetMod.getDownloadUrl(), modName, targetMod.getDownloadSizeBytes());
+		downloadMod(targetMod);
 
 	for(const auto & name : getModsToInstall(modName))
 	{
 		auto mod = modStateModel->getMod(name);
 		// update required mod, install missing (can be new dependency)
 		if(mod.isUpdateAvailable() || !mod.isInstalled())
-			downloadFile(name + ".zip", mod.getDownloadUrl(), name, mod.getDownloadSizeBytes());
+			downloadMod(mod);
 	}
 }
 
@@ -617,14 +618,18 @@ void CModListView::on_installButton_clicked()
 {
 	QString modName = ui->allModsView->currentIndex().data(ModRoles::ModNameRole).toString();
 
-	for(const auto & name : getModsToInstall(modName))
-	{
-		auto mod = modStateModel->getMod(name);
-		if(mod.isAvailable())
-			downloadFile(name + ".zip", mod.getDownloadUrl(), name, mod.getDownloadSizeBytes());
-		else if(!modStateModel->isModEnabled(name))
-			enableModByName(name);
-	}
+	doInstallMod(modName);
+
+	ui->installButton->setEnabled(false);
+}
+
+void CModListView::downloadMod(const ModState & mod)
+{
+	if (enqueuedModDownloads.contains(mod.getID()))
+		return;
+
+	enqueuedModDownloads.push_back(mod.getID());
+	downloadFile(mod.getID() + ".zip", mod.getDownloadUrl(), mod.getName(), mod.getDownloadSizeBytes());
 }
 
 void CModListView::downloadFile(QString file, QUrl url, QString description, qint64 sizeBytes)
@@ -697,6 +702,7 @@ void CModListView::downloadFinished(QStringList savedFiles, QStringList failedFi
 		doInstallFiles = true;
 	}
 
+	enqueuedModDownloads.clear();
 	dlManager->deleteLater();
 	dlManager = nullptr;
 	
@@ -796,6 +802,7 @@ void CModListView::installFiles(QStringList files)
 		{
 			ChroniclesExtractor ce(this, [&prog](float progress) { prog = progress; });
 			ce.installChronicles(exe);
+			enableModByName("chronicles");
 			return true;
 		});
 		
@@ -959,11 +966,13 @@ void CModListView::on_screenshotsList_clicked(const QModelIndex & index)
 
 void CModListView::doInstallMod(const QString & modName)
 {
-	for(const auto & name : modStateModel->getMod(modName).getDependencies())
+	for(const auto & name : getModsToInstall(modName))
 	{
 		auto mod = modStateModel->getMod(name);
-		if(!mod.isInstalled())
-			downloadFile(name + ".zip", mod.getDownloadUrl(), name, mod.getDownloadSizeBytes());
+		if(mod.isAvailable())
+			downloadMod(mod);
+		else if(!modStateModel->isModEnabled(name))
+			enableModByName(name);
 	}
 }
 

+ 3 - 0
launcher/modManager/cmodlistview_moc.h

@@ -37,6 +37,8 @@ class CModListView : public QWidget
 	CModFilterModel * filterModel;
 	CDownloadManager * dlManager;
 
+	QStringList enqueuedModDownloads;
+
 	void setupModModel();
 	void setupFilterModel();
 	void setupModsView();
@@ -111,6 +113,7 @@ public:
 	/// returns true if mod is currently installed
 	bool isModInstalled(const QString & modName);
 
+	void downloadMod(const ModState & mod);
 	void downloadFile(QString file, QUrl url, QString description, qint64 sizeBytes = 0);
 	void installFiles(QStringList mods);
 

+ 1 - 1
launcher/startGame/StartGameTab.cpp

@@ -102,7 +102,7 @@ void StartGameTab::refreshGameData()
 	};
 
 	bool missingSoundtrack = !CResourceHandler::get()->existsResource(AudioPath::builtin("Music/MainMenu"));
-	bool missingVideoFiles = !CResourceHandler::get()->existsResource(VideoPath::builtin("Video/H3Intro"));
+	bool missingVideoFiles = !CResourceHandler::get()->existsResource(VideoPath::builtin("Video/H3Intro")) && !CResourceHandler::get()->existsResource(ResourcePath("Video/H3Intro", EResType::VIDEO_LOW_QUALITY));
 	bool missingGameFiles = false;
 	bool missingCampaings = false;
 

+ 7 - 2
lib/gameState/CGameState.cpp

@@ -1400,8 +1400,10 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
 		case EventCondition::TRANSPORT:
 		{
 			const auto * t = getTown(condition.objectID);
-			return (t->visitingHero && t->visitingHero->getOwner() == player && t->visitingHero->hasArt(condition.objectType.as<ArtifactID>())) ||
-				   (t->garrisonHero && t->garrisonHero->getOwner() == player && t->garrisonHero->hasArt(condition.objectType.as<ArtifactID>()));
+			bool garrisonedWon = t->garrisonHero && t->garrisonHero->getOwner() == player && t->garrisonHero->hasArt(condition.objectType.as<ArtifactID>());
+			bool visitingWon = t->visitingHero && t->visitingHero->getOwner() == player && t->visitingHero->hasArt(condition.objectType.as<ArtifactID>());
+
+			return garrisonedWon || visitingWon;
 		}
 		case EventCondition::DAYS_PASSED:
 		{
@@ -1436,6 +1438,9 @@ PlayerColor CGameState::checkForStandardWin() const
 	TeamID winnerTeam = TeamID::NO_TEAM;
 	for(const auto & elem : players)
 	{
+		if(elem.second.status == EPlayerStatus::WINNER)
+			return elem.second.color;
+
 		if(elem.second.status == EPlayerStatus::INGAME && elem.first.isValidPlayer())
 		{
 			if(supposedWinner == PlayerColor::NEUTRAL)

+ 1 - 2
lib/modding/ModDescription.cpp

@@ -120,8 +120,7 @@ const JsonNode & ModDescription::getLocalizedValue(const std::string & keyName)
 
 const JsonNode & ModDescription::getValue(const std::string & keyName) const
 {
-	const JsonNode & localValue = getLocalValue(keyName);
-	if (localValue.isNull())
+	if (!isInstalled() || isUpdateAvailable())
 		return getRepositoryValue(keyName);
 	else
 		return getLocalValue(keyName);