Browse Source

Merge pull request #222 from dydzio0614/HeroBattleWindow

Looks OK to me, thanks! :)
DjWarmonger 9 years ago
parent
commit
e77d408e92

+ 70 - 1
client/battle/CBattleInterfaceClasses.cpp

@@ -177,6 +177,15 @@ void CBattleHero::setPhase(int newPhase)
 	nextPhase = 0;
 }
 
+void CBattleHero::hover(bool on)
+{
+	//TODO: Make lines below work properly
+	if (on)
+		CCS->curh->changeGraphic(ECursor::COMBAT, 5);
+	else
+		CCS->curh->changeGraphic(ECursor::COMBAT, 0);
+}
+
 void CBattleHero::clickLeft(tribool down, bool previousState)
 {
 	if(myOwner->spellDestSelectMode) //we are casting a spell
@@ -196,6 +205,25 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
 	}
 }
 
+void CBattleHero::clickRight(tribool down, bool previousState)
+{
+	Point windowPosition;
+	windowPosition.x = (!flip) ? myOwner->pos.topLeft().x + 1 : myOwner->pos.topRight().x - 79;
+	windowPosition.y = myOwner->pos.y + 135;
+
+	InfoAboutHero targetHero;
+
+	if (down && myOwner->myTurn)
+	{
+		if (myHero != nullptr)
+			targetHero.initFromHero(myHero, InfoAboutHero::EInfoLevel::INBATTLE);
+		else
+			targetHero = myOwner->enemyHero();
+
+		GH.pushInt(new CHeroInfoWindow(targetHero, &windowPosition));
+	}
+}
+
 void CBattleHero::switchToNextPhase()
 {
 	if (phase != nextPhase)
@@ -247,7 +275,7 @@ CBattleHero::CBattleHero(const std::string & defName, bool flipG, PlayerColor pl
 		CSDL_Ext::alphaTransform(elem.bitmap);
 		graphics->blueToPlayersAdv(elem.bitmap, player);
 	}
-	addUsedEvents(LCLICK);
+	addUsedEvents(LCLICK | RCLICK | HOVER);
 
 	switchToNextPhase();
 }
@@ -614,6 +642,47 @@ void CClickableHex::clickRight(tribool down, bool previousState)
 	}
 }
 
+CHeroInfoWindow::CHeroInfoWindow(const InfoAboutHero &hero, Point *position) : CWindowObject(RCLICK_POPUP | SHADOW_DISABLED, "CHRPOP")
+{
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	if (position != nullptr)
+		moveTo(*position);
+	background->colorize(hero.owner); //maybe add this functionality to base class?
+
+	int attack = hero.details->primskills[0];
+	int defense = hero.details->primskills[1];
+	int power = hero.details->primskills[2];
+	int knowledge = hero.details->primskills[3];
+	int morale = hero.details->morale;
+	int luck = hero.details->luck;
+	int currentSpellPoints = hero.details->mana;
+	int maxSpellPoints = hero.details->manaLimit;
+
+	new CAnimImage("PortraitsLarge", hero.portrait, 0, 10, 6);
+
+	//primary stats
+	new CLabel(9, 75, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[380] + ":");
+	new CLabel(9, 87, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[381] + ":");
+	new CLabel(9, 99, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[382] + ":");
+	new CLabel(9, 111, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[383] + ":");
+
+	new CLabel(69, 87, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(attack));
+	new CLabel(69, 99, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(defense));
+	new CLabel(69, 111, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(power));
+	new CLabel(69, 123, EFonts::FONT_TINY, EAlignment::BOTTOMRIGHT, Colors::WHITE, std::to_string(knowledge));
+
+	//morale+luck
+	new CLabel(9, 131, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[384] + ":");
+	new CLabel(9, 143, EFonts::FONT_TINY, EAlignment::TOPLEFT, Colors::WHITE, CGI->generaltexth->allTexts[385] + ":");
+
+	new CAnimImage("IMRL22", morale + 3, 0, 47, 131);
+	new CAnimImage("ILCK22", luck + 3, 0, 47, 143);
+
+	//spell points
+	new CLabel(39, 174, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, CGI->generaltexth->allTexts[387]);
+	new CLabel(39, 186, EFonts::FONT_TINY, EAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints));
+}
+
 void CStackQueue::update()
 {
 	stacksSorted.clear();

+ 9 - 0
client/battle/CBattleInterfaceClasses.h

@@ -2,6 +2,7 @@
 
 #include "../gui/CIntObject.h"
 #include "../../lib/BattleHex.h"
+#include "../windows/CWindowObject.h"
 
 struct SDL_Surface;
 class CDefHandler;
@@ -62,11 +63,19 @@ public:
 	ui8 flagAnim, animCount; //for flag animation
 	void show(SDL_Surface * to) override; //prints next frame of animation to to
 	void setPhase(int newPhase); //sets phase of hero animation
+	void hover(bool on) override;
 	void clickLeft(tribool down, bool previousState) override; //call-in
+	void clickRight(tribool down, bool previousState) override; //call-in
 	CBattleHero(const std::string &defName, bool filpG, PlayerColor player, const CGHeroInstance *hero, const CBattleInterface *owner); //c-tor
 	~CBattleHero(); //d-tor
 };
 
+class CHeroInfoWindow : public CWindowObject
+{
+public:
+	CHeroInfoWindow(const InfoAboutHero &hero, Point *position);
+};
+
 /// Class which manages the battle options window
 class CBattleOptionsWindow : public CIntObject
 {

+ 2 - 2
client/widgets/MiscWidgets.cpp

@@ -294,9 +294,9 @@ CHeroTooltip::CHeroTooltip(Point pos, const InfoAboutHero &hero):
 }
 
 CHeroTooltip::CHeroTooltip(Point pos, const CGHeroInstance * hero):
-	CArmyTooltip(pos, InfoAboutHero(hero, true))
+	CArmyTooltip(pos, InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED))
 {
-	init(InfoAboutHero(hero, true));
+	init(InfoAboutHero(hero, InfoAboutHero::EInfoLevel::DETAILED));
 }
 
 void CTownTooltip::init(const InfoAboutTown &town)

+ 14 - 1
lib/CBattleCallback.cpp

@@ -332,7 +332,8 @@ InfoAboutHero CBattleInfoEssentials::battleGetHeroInfo( ui8 side ) const
 		return InfoAboutHero();
 	}
 
-	return InfoAboutHero(hero, battleDoWeKnowAbout(side));
+	InfoAboutHero::EInfoLevel infoLevel = battleDoWeKnowAbout(side) ? InfoAboutHero::EInfoLevel::DETAILED : InfoAboutHero::EInfoLevel::BASIC;
+	return InfoAboutHero(hero, infoLevel);
 }
 
 int CBattleInfoEssentials::battleCastSpells(ui8 side) const
@@ -424,6 +425,18 @@ ui8 CBattleInfoEssentials::playerToSide(PlayerColor player) const
 	return ret;
 }
 
+bool CBattleInfoEssentials::playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const
+{
+	RETURN_IF_NOT_BATTLE(false);
+	ui8 playerSide = playerToSide(player);
+	if (playerSide >= 0)
+	{
+		if (getBattle()->sides[!playerSide].hero == h)
+			return true;
+	}
+	return false;
+}
+
 ui8 CBattleInfoEssentials::battleGetSiegeLevel() const
 {
 	RETURN_IF_NOT_BATTLE(0);

+ 1 - 0
lib/CBattleCallback.h

@@ -190,6 +190,7 @@ public:
 	bool battleCanFlee(PlayerColor player) const;
 	bool battleCanSurrender(PlayerColor player) const;
 	ui8 playerToSide(PlayerColor player) const;
+	bool playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const;
 	ui8 battleGetSiegeLevel() const; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
 	bool battleHasHero(ui8 side) const;
 	int battleCastSpells(ui8 side) const; //how many spells has given side cast

+ 17 - 5
lib/CGameInfoCallback.cpp

@@ -271,19 +271,31 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 	ERROR_RET_VAL_IF(!h, "That's not a hero!", false);
 	ERROR_RET_VAL_IF(!isVisible(h->getPosition(false)), "That hero is not visible!", false);
 
-	bool accessFlag = hasAccess(h->tempOwner);
+	InfoAboutHero::EInfoLevel infoLevel = InfoAboutHero::EInfoLevel::BASIC;
 
-	if(!accessFlag && nullptr != selectedObject)
+	if(hasAccess(h->tempOwner))
+		infoLevel = InfoAboutHero::EInfoLevel::DETAILED;
+
+	if ( (infoLevel == InfoAboutHero::EInfoLevel::BASIC) && gs->curB) //if it's battle we can get enemy hero full data
+	{
+		if(gs->curB->playerHasAccessToHeroInfo(*player, h))
+			infoLevel = InfoAboutHero::EInfoLevel::INBATTLE;
+	}
+
+	if( (infoLevel == InfoAboutHero::EInfoLevel::BASIC) && nullptr != selectedObject)
 	{
 		const CGHeroInstance * selectedHero = dynamic_cast<const CGHeroInstance *>(selectedObject);
 		if(nullptr != selectedHero)
-			accessFlag = selectedHero->hasVisions(hero, 1);
+			if(selectedHero->hasVisions(hero, 1))
+				infoLevel = InfoAboutHero::EInfoLevel::DETAILED;
 	}
 
-	dest.initFromHero(h, accessFlag);
+	dest.initFromHero(h, infoLevel);
 
 	//DISGUISED bonus implementation
 
+	bool disguiseFlag = (infoLevel == InfoAboutHero::EInfoLevel::DETAILED);
+
 	if(getPlayerRelations(getLocalPlayer(), hero->tempOwner) == PlayerRelations::ENEMIES)
 	{
 		//todo: bonus cashing
@@ -312,7 +324,7 @@ bool CGameInfoCallback::getHeroInfo(const CGObjectInstance * hero, InfoAboutHero
 				}
 		};
 
-		auto doAdvancedDisguise = [accessFlag, &doBasicDisguise](InfoAboutHero & info)
+		auto doAdvancedDisguise = [disguiseFlag, &doBasicDisguise](InfoAboutHero & info)
 		{
 			doBasicDisguise(info);
 

+ 10 - 4
lib/CGameState.cpp

@@ -2619,7 +2619,7 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
 				continue;
 			const CGHeroInstance * best = statsHLP::findBestHero(this, g->second.color);
 			InfoAboutHero iah;
-			iah.initFromHero(best, level >= 2);
+			iah.initFromHero(best, (level >= 2) ? InfoAboutHero::EInfoLevel::DETAILED : InfoAboutHero::EInfoLevel::BASIC);
 			iah.army.clear();
 			tgi.colorToBestHero[g->second.color] = iah;
 		}
@@ -3007,12 +3007,12 @@ InfoAboutHero::InfoAboutHero(const InfoAboutHero & iah):
 	assign(iah);
 }
 
-InfoAboutHero::InfoAboutHero(const CGHeroInstance *h, bool detailed)
+InfoAboutHero::InfoAboutHero(const CGHeroInstance *h, InfoAboutHero::EInfoLevel infoLevel)
 	: details(nullptr),
 	hclass(nullptr),
 	portrait(-1)
 {
-	initFromHero(h, detailed);
+	initFromHero(h, infoLevel);
 }
 
 InfoAboutHero::~InfoAboutHero()
@@ -3026,11 +3026,13 @@ InfoAboutHero & InfoAboutHero::operator=(const InfoAboutHero & iah)
 	return *this;
 }
 
-void InfoAboutHero::initFromHero(const CGHeroInstance *h, bool detailed)
+void InfoAboutHero::initFromHero(const CGHeroInstance *h, InfoAboutHero::EInfoLevel infoLevel)
 {
 	if(!h)
 		return;
 
+	bool detailed = ( (infoLevel == EInfoLevel::DETAILED) || (infoLevel == EInfoLevel::INBATTLE) );
+
 	initFromArmy(h, detailed);
 
 	hclass = h->type->heroClass;
@@ -3050,6 +3052,10 @@ void InfoAboutHero::initFromHero(const CGHeroInstance *h, bool detailed)
 		{
 			details->primskills[i] = h->getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(i));
 		}
+		if (infoLevel == EInfoLevel::INBATTLE)
+			details->manaLimit = h->manaLimit();
+		else
+			details->manaLimit = -1; //we do not want to leak max mana info outside battle so set to meaningless value
 	}
 }
 

+ 11 - 3
lib/CGameStateFwd.h

@@ -44,24 +44,32 @@ struct DLL_LINKAGE InfoAboutHero : public InfoAboutArmy
 {
 private:
 	void assign(const InfoAboutHero & iah);
+
 public:
 	struct DLL_LINKAGE Details
 	{
 		std::vector<si32> primskills;
-		si32 mana, luck, morale;
+		si32 mana, manaLimit, luck, morale;
 	} *details;
 
 	const CHeroClass *hclass;
 	int portrait;
 
+	enum EInfoLevel
+	{
+		BASIC,
+		DETAILED,
+		INBATTLE
+	};
+
 	InfoAboutHero();
 	InfoAboutHero(const InfoAboutHero & iah);
-	InfoAboutHero(const CGHeroInstance *h, bool detailed);
+	InfoAboutHero(const CGHeroInstance *h, EInfoLevel infoLevel);
 	~InfoAboutHero();
 
 	InfoAboutHero & operator=(const InfoAboutHero & iah);
 
-	void initFromHero(const CGHeroInstance *h, bool detailed);
+	void initFromHero(const CGHeroInstance *h, EInfoLevel infoLevel);
 };
 
 /// Struct which holds a int information about a town