[Scummvm-git-logs] scummvm master -> a3cfd1fabdfdf55fb5c0f6ef99fc975a0c59a0a3

dreammaster noreply at scummvm.org
Sat Jun 10 23:03:12 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
a3cfd1fabd MM: XEEN: add hp and sp bars for QoL


Commit: a3cfd1fabdfdf55fb5c0f6ef99fc975a0c59a0a3
    https://github.com/scummvm/scummvm/commit/a3cfd1fabdfdf55fb5c0f6ef99fc975a0c59a0a3
Author: Alexander Izmailov (yarolig at gmail.com)
Date: 2023-06-10T16:03:08-07:00

Commit Message:
MM: XEEN: add hp and sp bars for QoL

Changed paths:
    engines/mm/detection.h
    engines/mm/detection_tables.h
    engines/mm/metaengine.cpp
    engines/mm/xeen/interface.cpp
    engines/mm/xeen/interface.h
    engines/mm/xeen/xeen.cpp
    engines/mm/xeen/xeen.h


diff --git a/engines/mm/detection.h b/engines/mm/detection.h
index df26fa4dc0f..3034a1568ee 100644
--- a/engines/mm/detection.h
+++ b/engines/mm/detection.h
@@ -49,6 +49,7 @@ struct MightAndMagicGameDescription {
 
 #define GAMEOPTION_SHOW_ITEM_COSTS	GUIO_GAMEOPTIONS1
 #define GAMEOPTION_DURABLE_ARMOR	GUIO_GAMEOPTIONS2
+#define GAMEOPTION_SHOW_HP_SP_BARS	GUIO_GAMEOPTIONS3
 
 } // namespace MM
 
diff --git a/engines/mm/detection_tables.h b/engines/mm/detection_tables.h
index e0e07e0ac8e..e83cdd4ab03 100644
--- a/engines/mm/detection_tables.h
+++ b/engines/mm/detection_tables.h
@@ -19,8 +19,13 @@
  *
  */
 
+#include "engines/advancedDetector.h"
+#include "engines/mm/detection.h"
+
 namespace MM {
 
+#define GUIO_XEEN GUIO3(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR, GAMEOPTION_SHOW_HP_SP_BARS)
+
 static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 #ifdef ENABLE_MM1
 	{
@@ -82,7 +87,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_WorldOfXeen,
 		0
@@ -98,7 +103,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_WorldOfXeen,
 		0
@@ -118,7 +123,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::DE_DEU,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_WorldOfXeen,
 		0
@@ -134,7 +139,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::DE_DEU,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_WorldOfXeen,
 		0
@@ -150,7 +155,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_CD,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_WorldOfXeen,
 		0
@@ -167,7 +172,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::FR_FRA,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_WorldOfXeen,
 		0
@@ -182,7 +187,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_Clouds,
 		0
@@ -197,7 +202,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::DE_DEU,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_Clouds,
 		0
@@ -212,7 +217,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::RU_RUS,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_Clouds,
 		0
@@ -227,7 +232,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::ZH_TWN,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_Clouds,
 		0
@@ -243,7 +248,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::FR_FRA,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_Clouds,
 		0
@@ -258,7 +263,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_DarkSide,
 		0
@@ -273,7 +278,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::DE_DEU,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_DarkSide,
 		0
@@ -289,7 +294,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::DE_DEU,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_DarkSide,
 		0
@@ -304,7 +309,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::ZH_TWN,
 			Common::kPlatformDOS,
 			ADGF_UNSTABLE,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_DarkSide,
 		0
@@ -320,7 +325,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::FR_FRA,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_DarkSide,
 		0
@@ -335,7 +340,7 @@ static const MightAndMagicGameDescription GAME_DESCRIPTIONS[] = {
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
-			GUIO2(GAMEOPTION_SHOW_ITEM_COSTS, GAMEOPTION_DURABLE_ARMOR)
+			GUIO_XEEN
 		},
 		GType_Swords,
 		0
diff --git a/engines/mm/metaengine.cpp b/engines/mm/metaengine.cpp
index 85a62110f25..cca674bcd96 100644
--- a/engines/mm/metaengine.cpp
+++ b/engines/mm/metaengine.cpp
@@ -39,6 +39,43 @@
 #include "mm/xeen/swordsofxeen/swordsofxeen.h"
 #endif
 
+static const ADExtraGuiOptionsMap optionsList[] = {
+	{
+		GAMEOPTION_SHOW_ITEM_COSTS,
+		{
+			_s("Show item costs in standard inventory mode"),
+			_s("Shows item costs in standard inventory mode, allowing the value of items to be compared"),
+			"ShowItemCosts",
+			false,
+			0,
+			0
+		}
+	},
+	{
+		GAMEOPTION_DURABLE_ARMOR,
+		{
+			_s("More durable armor"),
+			_s("Armor won't break until character is at -80HP, rather than merely -10HP"),
+			"DurableArmor",
+			false,
+			0,
+			0
+		}
+	},
+	{
+		GAMEOPTION_SHOW_HP_SP_BARS,
+		{
+			_s("Hitpoint bars"),
+			_s("Replace a colored gem with bars for hit points and spell points."),
+			"ShowHpSpBars",
+			false,
+			0,
+			0
+		}
+	},
+	AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
+
 class MMMetaEngine : public AdvancedMetaEngine {
 private:
 	/**
@@ -60,6 +97,10 @@ public:
 	SaveStateList listSaves(const char *target) const override;
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
 	Common::KeymapArray initKeymaps(const char *target) const override;
+
+	const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
+		return optionsList;
+	}
 };
 
 bool MMMetaEngine::hasFeature(MetaEngineFeature f) const {
diff --git a/engines/mm/xeen/interface.cpp b/engines/mm/xeen/interface.cpp
index ca9827128a0..7ea8bc2e3c9 100644
--- a/engines/mm/xeen/interface.cpp
+++ b/engines/mm/xeen/interface.cpp
@@ -51,12 +51,124 @@ PartyDrawer::PartyDrawer(XeenEngine *vm): _vm(vm) {
 	_hiliteChar = HILIGHT_CHAR_NONE;
 }
 
+static inline int clipToFaceWidth(int i) {
+	const int faceWidth = 32;
+	return CLIP(i, 0, faceWidth);
+}
+
+static inline int unzero(int i) {
+	if (i) return i;
+	return 1;
+}
+
+void PartyDrawer::drawHitPoints(int charIndex) {
+	Combat &combat = *_vm->_combat;
+	Party &party = *_vm->_party;
+	Windows &windows = *_vm->_windows;
+	bool inCombat = _vm->_mode == MODE_COMBAT;
+	Window &win = windows[0];
+	Character &c = inCombat ? *combat._combatParty[charIndex] : party._activeParty[charIndex];
+
+	enum {
+		BLACK = 0,
+		STONE = 20,
+
+		BRIGHT_GREEN = 80,
+		GREEN = 85,
+		YELLOW = 55,
+		RED = 185,
+		DARK_BLUE = 78,
+
+		BRIGHT_BLUE = 70,
+		BLUE = 75
+	};
+
+	int hp = c._currentHp;
+	int sp = c._currentSp;
+
+	int maxHp = c.getMaxHP();
+	int maxSp =  c.getMaxSP();
+
+	int gemFrame;
+	int hpColor = GREEN;
+
+	if (hp < 1) {
+		gemFrame = 4;
+	} else if (hp > maxHp) {
+		gemFrame = 3;
+	} else if (hp == maxHp) {
+		gemFrame = 0;
+	} else if (hp < (maxHp / 4)) {
+		gemFrame = 2;
+		hpColor = RED;
+	} else{
+		hpColor = YELLOW;
+		gemFrame = 1;
+	}
+	if (!g_vm->_extOptions._showHpSpBars) {
+		_hpSprites.draw(0, gemFrame, Common::Point(Res.HP_BARS_X[charIndex], 182));
+	} else {
+		const int faceWidth = 32;
+
+		const int barLeft = Res.CHAR_FACES_X[charIndex];
+		const int barRight = Res.CHAR_FACES_X[charIndex] + 32;
+		const int barHeight = 3;
+
+		const int frameTop = 183;
+		const int frameBottom = 190;
+		const int frameColor = STONE;
+		const int hpBarTop = 184;
+		const int hpBarBottom = hpBarTop + barHeight;
+
+		const int spBarTop = 188;
+		const int spBarBottom = spBarTop + barHeight;
+
+		int hpPart = clipToFaceWidth( (hp * faceWidth) / unzero(maxHp) );
+		int boostedHpPart = 0;
+		if (hp > maxHp) {
+			boostedHpPart = clipToFaceWidth(faceWidth * (hp - maxHp) / unzero(hp + maxHp) );
+		}
+
+		int spPart = clipToFaceWidth( (sp * faceWidth) / unzero(maxSp) );
+		int boostedSpPart = 0;
+		if (sp > maxSp) {
+			boostedSpPart = clipToFaceWidth( faceWidth * (sp - maxSp) / unzero(sp + maxSp) );
+		}
+
+		int negativeHpPart = 32;
+		if (hp < 0) {
+			negativeHpPart = faceWidth - clipToFaceWidth((-hp * faceWidth) / unzero(maxHp));
+		}
+
+		win.fillRect(Common::Rect(barLeft, frameTop, barRight, frameBottom), frameColor);
+
+		win.fillRect(Common::Rect(barLeft, hpBarTop, barRight, hpBarBottom), BLACK);
+		win.fillRect(Common::Rect(barLeft, hpBarTop, barLeft + hpPart, hpBarBottom), hpColor);
+		if (boostedHpPart != 0) {
+			win.fillRect(Common::Rect(barLeft, hpBarTop, barLeft + boostedHpPart, hpBarBottom), BRIGHT_GREEN);
+		}
+
+		if (negativeHpPart != 32) {
+			win.fillRect(Common::Rect(barLeft + negativeHpPart, hpBarTop, barLeft + faceWidth, hpBarBottom), DARK_BLUE);
+		}
+
+		if (maxSp != 0) {
+			win.fillRect(Common::Rect(barLeft, spBarTop, barRight, spBarBottom), BLACK);
+			win.fillRect(Common::Rect(barLeft, spBarTop, barLeft + spPart, spBarBottom), BLUE);
+			if (boostedSpPart) {
+				win.fillRect(Common::Rect(barLeft, spBarTop, barLeft + boostedSpPart, spBarBottom), BRIGHT_BLUE);
+			}
+		}
+	}
+}
+
 void PartyDrawer::drawParty(bool updateFlag) {
 	Combat &combat = *_vm->_combat;
 	Party &party = *_vm->_party;
 	Resources &res = *_vm->_resources;
 	Windows &windows = *_vm->_windows;
 	bool inCombat = _vm->_mode == MODE_COMBAT;
+
 	_restoreSprites.draw(0, 0, Common::Point(8, 149));
 
 	// Handle drawing the party faces
@@ -75,23 +187,7 @@ void PartyDrawer::drawParty(bool updateFlag) {
 	}
 
 	for (uint idx = 0; idx < partyCount; ++idx) {
-		Character &c = inCombat ? *combat._combatParty[idx] : party._activeParty[idx];
-
-		// Draw the Hp bar
-		int maxHp = c.getMaxHP();
-		int frame;
-		if (c._currentHp < 1)
-			frame = 4;
-		else if (c._currentHp > maxHp)
-			frame = 3;
-		else if (c._currentHp == maxHp)
-			frame = 0;
-		else if (c._currentHp < (maxHp / 4))
-			frame = 2;
-		else
-			frame = 1;
-
-		_hpSprites.draw(0, frame, Common::Point(Res.HP_BARS_X[idx], 182));
+		drawHitPoints(idx);
 	}
 
 	if (_hiliteChar != HILIGHT_CHAR_NONE)
@@ -533,6 +629,10 @@ void Interface::perform() {
 		if (CastSpell::show(_vm) != -1) {
 			chargeStep();
 			doStepCode();
+			// update spell point bar
+			if (g_vm->_extOptions._showHpSpBars) {
+				drawParty(true);
+			}
 		}
 		break;
 
@@ -1601,6 +1701,10 @@ void Interface::doCombat() {
 				// Cast spell
 				if (CastSpell::show(_vm) != -1) {
 					nextChar();
+					// update spell point bar
+					if (g_vm->_extOptions._showHpSpBars) {
+						drawParty(true);
+					}
 				} else {
 					highlightChar(combat._whosTurn);
 				}
diff --git a/engines/mm/xeen/interface.h b/engines/mm/xeen/interface.h
index ff3dd6bba8e..eda151c6a08 100644
--- a/engines/mm/xeen/interface.h
+++ b/engines/mm/xeen/interface.h
@@ -86,6 +86,9 @@ public:
 	void unhighlightChar();
 
 	void resetHighlight();
+
+private:
+	void drawHitPoints(int charIndex);
 };
 
 /**
diff --git a/engines/mm/xeen/xeen.cpp b/engines/mm/xeen/xeen.cpp
index c63c5c66c13..1799a4195e3 100644
--- a/engines/mm/xeen/xeen.cpp
+++ b/engines/mm/xeen/xeen.cpp
@@ -125,6 +125,7 @@ void XeenEngine::loadSettings() {
 
 	_extOptions._showItemCosts = ConfMan.hasKey("ShowItemCosts") && ConfMan.getBool("ShowItemCosts");
 	_extOptions._durableArmor = ConfMan.hasKey("DurableArmor") && ConfMan.getBool("DurableArmor");
+	_extOptions._showHpSpBars = ConfMan.hasKey("ShowHpSpBars") && ConfMan.getBool("ShowHpSpBars");
 
 	// If requested, load a savegame instead of showing the intro
 	if (ConfMan.hasKey("save_slot")) {
diff --git a/engines/mm/xeen/xeen.h b/engines/mm/xeen/xeen.h
index e3ed79f2ef0..b86f047cf5d 100644
--- a/engines/mm/xeen/xeen.h
+++ b/engines/mm/xeen/xeen.h
@@ -97,9 +97,13 @@ class XeenEngine : public MMEngine {
 	struct ExtendedOptions {
 		bool _showItemCosts;
 		bool _durableArmor;
+		bool _showHpSpBars;
 
-		ExtendedOptions() : _showItemCosts(false), _durableArmor(false) {
-		}
+		ExtendedOptions() :
+			_showItemCosts(false),
+			_durableArmor(false),
+			_showHpSpBars(false)
+		{}
 	};
 private:
 	/**




More information about the Scummvm-git-logs mailing list