Browse Source

Merge branch 'develop' into campaignsets

Laserlicht 1 month ago
parent
commit
6521a98077

BIN
Mods/vcmi/Content/Sprites/questDialog.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/bonus-effects.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/button-panel.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/commander-abilities.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/commander-bg.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/info-panel-0.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/info-panel-1.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/info-panel-2.png


BIN
Mods/vcmi/Content/Sprites/stackWindow/spell-effects.png


+ 1 - 1
Mods/vcmi/Content/config/english.json

@@ -965,7 +965,7 @@
 	"creatures.core.rogue.bonus.visionsHeroes" : "{Visions Heroes}\nHero can see detailed informations about enemy heroes",
 	"creatures.core.rogue.bonus.visionsTowns" : "{Visions Towns}\nHero can see detailed informations about enemy towns",
 
-	"core.bonus.ADDITIONAL_ATTACK.description" : "{Additional attacks}\nUnit can attack an additional {$val} times", // TODO: alternative descriptions for melee/ranged effect range
+	"core.bonus.ADDITIONAL_ATTACK.description" : "{Additional attacks}\nUnit can attack an additional ${val} times", // TODO: alternative descriptions for melee/ranged effect range
 	"core.bonus.ADDITIONAL_RETALIATION.description" : "{Additional retaliations}\nUnit can retaliate ${val} extra times",
 	"core.bonus.ATTACKS_ALL_ADJACENT.description" : "{Attack all around}\nAttacks all adjacent enemies in addition to the primary target",
 	"core.bonus.BLOCKS_RANGED_RETALIATION.description" : "{No ranged retaliation}\nThe enemy cannot retaliate when shot by this unit",

+ 1 - 1
Mods/vcmi/Content/config/portuguese.json

@@ -645,7 +645,7 @@
 	"creatures.core.azureDragon.bonus.fearful" : "{Medo}\nUnidades inimigas têm 10% de chance de congelar de medo",
 	"creatures.core.azureDragon.bonus.fearless" : "{Destemido}\nImune à habilidade Medo",
 
-	"core.bonus.ADDITIONAL_ATTACK.description" : "{Ataques Adicionais}\nA unidade pode atacar {$val} vezes adicionais",
+	"core.bonus.ADDITIONAL_ATTACK.description" : "{Ataques Adicionais}\nA unidade pode atacar ${val} vezes adicionais",
 	"core.bonus.ADDITIONAL_RETALIATION.description" : "{Contra-ataques Adicionais}\nA unidade pode contra-atacar ${val} vezes extras",
 	"core.bonus.ATTACKS_ALL_ADJACENT.description" : "{Ataque em Área}\nAtaca todos os inimigos adjacentes além do alvo principal",
 	"core.bonus.BLOCKS_RANGED_RETALIATION.description" : "{Evita Contra-ataques à Distância}\nO inimigo não pode contra-atacar usando um ataque à distância",

+ 1 - 1
Mods/vcmi/Content/config/swedish.json

@@ -953,7 +953,7 @@
 	"creatures.core.azureDragon.bonus.fearful"           : "{Skräckinjagande}\nInjagar skräck/rädsla hos fiendetrupper.",
 	"creatures.core.azureDragon.bonus.fearless"          : "{Orädd}\nImmun mot rädsla/skräck.",
 
-	"core.bonus.ADDITIONAL_ATTACK.description" : "{Ytterligare attacker}\nEnheten kan attackera ytterligare {$val} gång(er).",
+	"core.bonus.ADDITIONAL_ATTACK.description" : "{Ytterligare attacker}\nEnheten kan attackera ytterligare ${val} gång(er).",
 	"core.bonus.ADDITIONAL_RETALIATION.description" : "{Ytterligare motattacker}\nKan slå tillbaka ${val} extra gång(er).",
 	"core.bonus.ATTACKS_ALL_ADJACENT.description" : "{Attackera runtomkring}\nAttackerar alla angränsande fiender.",
 	"core.bonus.BLOCKS_RANGED_RETALIATION.description" : "{Stoppa avståndsretaliering}\nFienden kan inte retaliera på avstånd.",

+ 191 - 0
client/render/AssetGenerator.cpp

@@ -18,6 +18,7 @@
 #include "../render/ColorFilter.h"
 #include "../render/IRenderHandler.h"
 #include "../render/CAnimation.h"
+#include "../render/Colors.h"
 
 #include "../lib/filesystem/Filesystem.h"
 #include "../lib/GameSettings.h"
@@ -51,6 +52,16 @@ void AssetGenerator::initialize()
 
 	imageFiles[ImagePath::builtin("SpelTabNone.png")] = [this](){ return createSpellTabNone();};
 
+	imageFiles[ImagePath::builtin("stackWindow/info-panel-0.png")] = [this](){ return createCreatureInfoPanel(2);};
+	imageFiles[ImagePath::builtin("stackWindow/info-panel-1.png")] = [this](){ return createCreatureInfoPanel(3);};
+	imageFiles[ImagePath::builtin("stackWindow/info-panel-2.png")] = [this](){ return createCreatureInfoPanel(4);};
+	imageFiles[ImagePath::builtin("stackWindow/bonus-effects.png")] = [this](){ return createCreatureInfoPanelElement(BONUS_EFFECTS);};
+	imageFiles[ImagePath::builtin("stackWindow/spell-effects.png")] = [this](){ return createCreatureInfoPanelElement(SPELL_EFFECTS);};
+	imageFiles[ImagePath::builtin("stackWindow/button-panel.png")] = [this](){ return createCreatureInfoPanelElement(BUTTON_PANEL);};
+	imageFiles[ImagePath::builtin("stackWindow/commander-bg.png")] = [this](){ return createCreatureInfoPanelElement(COMMANDER_BACKGROUND);};
+	imageFiles[ImagePath::builtin("stackWindow/commander-abilities.png")] = [this](){ return createCreatureInfoPanelElement(COMMANDER_ABILITIES);};
+	imageFiles[ImagePath::builtin("questDialog.png")] = [this](){ return createQuestWindow();};
+
 	for (PlayerColor color(0); color < PlayerColor::PLAYER_LIMIT; ++color)
 		imageFiles[ImagePath::builtin("DialogBoxBackground_" + color.toString())] = [this, color](){ return createPlayerColoredBackground(color);};
 
@@ -538,6 +549,186 @@ AssetGenerator::AnimationLayoutMap AssetGenerator::createAdventureMapButton(cons
 	return layout;
 }
 
+AssetGenerator::CanvasPtr AssetGenerator::createCreatureInfoPanel(int boxesAmount) const
+{
+	Point size(438, 187);
+
+	auto image = ENGINE->renderHandler().createImage(size, CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
+
+	Rect r(4, 40, 102, 132);
+	canvas.drawColor(r, Colors::BLACK);
+	canvas.drawBorder(r, Colors::YELLOW);
+
+    const ColorRGBA rectangleColor = ColorRGBA(0, 0, 0, 75);
+    const ColorRGBA rectangleColorRed = ColorRGBA(32, 0, 0, 150);
+    const ColorRGBA borderColor = ColorRGBA(128, 100, 75);
+
+	r = Rect(60, 3, 315, 21);
+	canvas.drawColorBlended(r, rectangleColor);
+	canvas.drawBorder(r, borderColor);
+
+	for(int i = 0; i < 8; i++)
+	{
+		Rect r(114, 30 + i * 19, 24, 20);
+		canvas.drawColorBlended(r, rectangleColor);
+		canvas.drawBorder(r, borderColor);
+		r.x += 23;
+		r.w = 173;
+		canvas.drawColorBlended(r, rectangleColor);
+		canvas.drawBorder(r, borderColor);
+	}
+
+	std::vector<Rect> redRects = {
+		Rect(319, 30, 45, 45),
+		Rect(373, 30, 45, 45)
+	};
+	std::vector<Rect> darkRects = {};
+
+	if(boxesAmount == 3)
+	{
+		redRects.push_back(Rect(347, 109, 45, 45));
+		darkRects.push_back(Rect(347, 156, 45, 19));
+	}
+	else if(boxesAmount == 4)
+	{
+		redRects.push_back(Rect(319, 109, 45, 45));
+		redRects.push_back(Rect(373, 109, 45, 45));
+		darkRects.push_back(Rect(319, 156, 45, 19));
+		darkRects.push_back(Rect(373, 156, 45, 19));
+	}
+	
+	for(auto & rect : darkRects)
+	{
+		canvas.drawColorBlended(rect, rectangleColor);
+		canvas.drawBorder(rect, borderColor);
+	}
+	for(auto & rect : redRects)
+	{
+		canvas.drawColorBlended(rect, rectangleColorRed);
+		canvas.drawBorder(rect, borderColor);
+	}
+
+	return image;
+}
+
+AssetGenerator::CanvasPtr AssetGenerator::createCreatureInfoPanelElement(CreatureInfoPanelElement element) const
+{
+	std::map<CreatureInfoPanelElement, Point> size {
+		{BONUS_EFFECTS, Point(438, 59)},
+		{SPELL_EFFECTS, Point(438, 42)},
+		{BUTTON_PANEL, Point(438, 43)},
+		{COMMANDER_BACKGROUND, Point(438, 177)},
+		{COMMANDER_ABILITIES, Point(438, 59)}
+	};
+
+	auto image = ENGINE->renderHandler().createImage(size[element], CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
+	
+    const ColorRGBA rectangleColor = ColorRGBA(0, 0, 0, 75);
+    const ColorRGBA rectangleColorRed = ColorRGBA(32, 0, 0, 150);
+    const ColorRGBA borderColor = ColorRGBA(128, 100, 75);
+
+	switch (element)
+	{
+	case BONUS_EFFECTS:
+		for(int i = 0; i < 2; i++)
+		{
+			Rect r(4 + i * 208, 0, 54, 54);
+			canvas.drawColorBlended(r, rectangleColorRed);
+			canvas.drawBorder(r, borderColor);
+			r = Rect(61 + i * 208, 0, 144, 54);
+			canvas.drawColorBlended(r, rectangleColor);
+			canvas.drawBorder(r, borderColor);
+		}
+		break;
+	case SPELL_EFFECTS:
+		for(int i = 0; i < 8; i++)
+		{
+			Rect r(6 + i * 54, 2, 48, 36);
+			canvas.drawColorBlended(r, rectangleColor);
+			canvas.drawBorder(r, borderColor);
+		}
+		break;
+	case BUTTON_PANEL:
+		canvas.drawColorBlended(Rect(382, 5, 52, 36), Colors::BLACK);
+		break;
+	case COMMANDER_BACKGROUND:
+		for(int x = 0; x < 3; x++)
+		{
+			for(int y = 0; y < 3; y++)
+			{
+				Rect r(269 + x * 52, 21 + y * 52, 44, 44);
+				canvas.drawColorBlended(r, rectangleColorRed);
+				canvas.drawBorder(r, borderColor);
+			}
+		}
+		for(int x = 0; x < 3; x++)
+		{
+			for(int y = 0; y < 2; y++)
+			{
+				Rect r(10 + x * 80, 20 + y * 80, 70, 70);
+				canvas.drawColor(r, Colors::BLACK);
+			}
+		}
+		break;
+	case COMMANDER_ABILITIES:
+		for(int i = 0; i < 6; i++)
+		{
+			Rect r(37 + i * 63, 2, 54, 54);
+			canvas.drawColorBlended(r, rectangleColorRed);
+			canvas.drawBorder(r, borderColor);
+		}
+		for(int i = 0; i < 2; i++)
+		{
+			Rect r(10 + i * 401, 6, 22, 46);
+			canvas.drawColor(r, Colors::BLACK);
+		}
+		break;
+	}
+
+	return image;
+}
+
+AssetGenerator::CanvasPtr AssetGenerator::createQuestWindow() const
+{
+	auto locator = ImageLocator(ImagePath::builtin("DiBoxBck"), EImageBlitMode::OPAQUE);
+	std::shared_ptr<IImage> img = ENGINE->renderHandler().loadImage(locator);
+
+	Point size(612, 438);
+
+	auto image = ENGINE->renderHandler().createImage(size, CanvasScalingPolicy::IGNORE);
+	Canvas canvas = image->getCanvas();
+
+	for (int y = 0; y < size.y; y += img->height())
+		for (int x = 0; x < size.x; x += img->width())
+			canvas.draw(img, Point(x, y), Rect(0, 0, std::min(img->width(), size.x - x), std::min(img->height(), size.y - y)));
+
+	Rect r(11, 11, 171, 171);
+	canvas.drawColor(r, Colors::BLACK);
+	canvas.drawBorder(r, Colors::YELLOW);
+
+    const ColorRGBA rectangleColor = ColorRGBA(0, 0, 0, 75);
+    const ColorRGBA borderColor = ColorRGBA(128, 100, 75);
+
+	for(int i = 0; i < 6; i++)
+	{
+		Rect r(11, 194 + i * 32, 155, 33);
+		canvas.drawColorBlended(r, rectangleColor);
+		canvas.drawBorder(r, borderColor);
+	}
+	
+	r = Rect(165, 194, 18, 193);
+	canvas.drawColor(r, Colors::BLACK);
+	canvas.drawBorder(r, borderColor);
+
+	r = Rect(193, 11, 408, 376);
+	canvas.drawColorBlended(r, rectangleColor);
+	canvas.drawBorder(r, borderColor);
+
+	return image;
+}
+
 AssetGenerator::AnimationLayoutMap AssetGenerator::createGSPButtonClear()
 {
 	auto baseImg = ENGINE->renderHandler().loadAnimation(AnimationPath::builtin("GSPBUTT"), EImageBlitMode::OPAQUE);

+ 4 - 0
client/render/AssetGenerator.h

@@ -54,6 +54,10 @@ private:
 	CanvasPtr createChroniclesCampaignImages(int chronicle) const;
 	CanvasPtr createPaletteShiftedImage(const AnimationPath & source, const std::vector<PaletteAnimation> & animation, int frameIndex, int paletteShiftCounter) const;
 	CanvasPtr createAdventureMapButtonClear(const PlayerColor & player) const;
+	CanvasPtr createCreatureInfoPanel(int boxesAmount) const;
+	enum CreatureInfoPanelElement{ BONUS_EFFECTS, SPELL_EFFECTS, BUTTON_PANEL, COMMANDER_BACKGROUND, COMMANDER_ABILITIES };
+	CanvasPtr createCreatureInfoPanelElement(CreatureInfoPanelElement element) const;
+	CanvasPtr createQuestWindow() const;
 	AnimationLayoutMap createAdventureMapButton(const ImagePath & overlay);
 	AnimationLayoutMap createGSPButtonClear();
 

+ 5 - 0
client/windows/CCreatureWindow.cpp

@@ -18,6 +18,7 @@
 #include "../widgets/Buttons.h"
 #include "../widgets/CComponent.h"
 #include "../widgets/CComponentHolder.h"
+#include "../widgets/GraphicalPrimitiveCanvas.h"
 #include "../widgets/Images.h"
 #include "../widgets/TextControls.h"
 #include "../widgets/ObjectLists.h"
@@ -831,6 +832,8 @@ void CStackWindow::init()
 {
 	OBJECT_CONSTRUCTION;
 
+	background = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), pos);
+
 	if(!info->stackNode)
 	{
 		fakeNode = std::make_unique<CStackInstance>(nullptr, info->creature->getId(), 1, true);
@@ -846,6 +849,8 @@ void CStackWindow::init()
 
 	initBonusesList();
 	initSections();
+
+	background->pos = pos;
 }
 
 void CStackWindow::initBonusesList()

+ 3 - 0
client/windows/CCreatureWindow.h

@@ -32,6 +32,7 @@ class CArtPlace;
 class CCommanderArtPlace;
 class LRClickableArea;
 class GraphicalPrimitiveCanvas;
+class CFilledTexture;
 
 class CCommanderSkillIcon : public LRClickableAreaWText //TODO: maybe bring commander skill button initialization logic inside?
 {
@@ -159,6 +160,8 @@ class CStackWindow : public CWindowObject
 		MainSection(CStackWindow * owner, int yOffset, bool showExp, bool showArt);
 	};
 
+	std::shared_ptr<CFilledTexture> background;
+
 	std::shared_ptr<CArtPlace> stackArtifact;
 	std::shared_ptr<CButton> stackArtifactButton;
 

+ 1 - 1
lib/callback/CGameInfoCallback.cpp

@@ -394,7 +394,7 @@ bool CGameInfoCallback::isVisibleFor(int3 pos, PlayerColor player) const
 bool CGameInfoCallback::isVisible(int3 pos) const
 {
 	if (!getPlayerID().has_value())
-		return true; // weird, but we do have such calls
+		return gameState().getMap().isInTheMap(pos); // weird, but we do have such calls
 	return gameState().isVisibleFor(pos, *getPlayerID());
 }