Bläddra i källkod

New creature window works in general, covering old functionalities and displaying new info. It's far from finished though.

DjWarmonger 14 år sedan
förälder
incheckning
dc0eb37da6

+ 3 - 1
client/CBattleInterface.cpp

@@ -24,6 +24,7 @@
 #include "../lib/CondSh.h"
 #include "../lib/NetPacks.h"
 #include "CPlayerInterface.h"
+#include "CCreatureWindow.h"
 #include "CVideoHandler.h"
 #include "../lib/CTownHandler.h"
 #include <boost/assign/list_of.hpp>
@@ -3770,7 +3771,8 @@ void CBattleHex::clickRight(tribool down, bool previousState)
 		if(!myst->alive()) return;
 		if(down)
 		{
-			GH.pushInt(new CCreInfoWindow(*myst));
+			//GH.pushInt(new CCreInfoWindow(*myst));
+			GH.pushInt(new CCreatureWindow(*myst, CCreatureWindow::BATTLE));
 		}
 	}
 }

+ 243 - 0
client/CCreatureWindow.cpp

@@ -0,0 +1,243 @@
+#include "CCreatureWindow.h"
+#include "../lib/CCreatureSet.h"
+#include "CGameInfo.h"
+#include "../lib/CGeneralTextHandler.h"
+#include "../lib/BattleState.h"
+#include "../CCallback.h"
+
+#include <SDL.h>
+#include "SDL_Extensions.h"
+#include "CBitmapHandler.h"
+#include "CDefHandler.h"
+#include "Graphics.h"
+#include "AdventureMapButton.h"
+#include "CPlayerInterface.h"
+#include "CMessage.h"
+
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/assign/std/vector.hpp> 
+#include <boost/assign/list_of.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/format.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+
+using namespace CSDL_Ext;
+
+/*
+ * CCreatureWindow.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+CCreatureWindow::CCreatureWindow (const CStack &stack, int Type)
+	: type(Type)
+{
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+
+	init(stack.base, &stack, dynamic_cast<const CGHeroInstance*>(stack.base->armyObj));
+}
+
+CCreatureWindow::CCreatureWindow (const CStackInstance &stack, int Type)
+	: type(Type)
+{
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+
+	init(&stack, &stack, dynamic_cast<const CGHeroInstance*>(stack.armyObj));
+}
+
+void CCreatureWindow::init(const CStackInstance *stack, const CBonusSystemNode *stackNode, const CGHeroInstance *heroOwner)
+{
+	c = stack->type;
+	if(!stackNode) stackNode = c;
+
+	//Basic graphics
+	std::pair<int,int> winSize;
+	winSize.first = 560 + 30;
+	winSize.second = 448 + 60;
+
+	bitmap = new CPicture(CMessage::drawBox1 (winSize.first, winSize.second, LOCPLINT->playerID), winSize.first, winSize.second, true);
+	//bitmap = new CPicture("CreWin3.pcx");
+	//graphics->blueToPlayersAdv(bitmap->bg, LOCPLINT->playerID);
+	//bitmap->colorizeAndConvert(LOCPLINT->playerID);
+	pos = bitmap->center();
+
+	//Buttons
+	ok = new AdventureMapButton("",CGI->generaltexth->zelp[445].second, boost::bind(&CCreatureWindow::close,this), 489, 148, "IOKAY32.DEF", SDLK_RETURN);
+
+	if (type <= BATTLE) //in battle or info window
+	{
+		upgrade = NULL;
+		dismiss = NULL;
+	}
+	anim = new CCreaturePic(20, 46, c);
+	printAtMiddle(c->namePl, 180, 30, FONT_SMALL, tytulowy,*bitmap); //creature name
+
+	//Stats
+	morale = new MoraleLuckBox(true, genRect(42, 42, 333, 98));
+	morale->set(stack);
+	luck = new MoraleLuckBox(false, genRect(42, 42, 385, 98));
+	luck->set(stack);
+
+	printLine(0, CGI->generaltexth->primarySkillNames[0], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK));
+	printLine(1, CGI->generaltexth->primarySkillNames[1], c->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE), stackNode->valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE));
+	if(c->shots)
+		printLine(2, CGI->generaltexth->allTexts[198], c->shots);
+
+	//TODO
+	int dmgMultiply = 1;
+	if(heroOwner && stackNode->hasBonusOfType(Bonus::SIEGE_WEAPON))
+		dmgMultiply += heroOwner->Attack(); 
+
+	printLine(3, CGI->generaltexth->allTexts[199], stackNode->getMinDamage() * dmgMultiply, stackNode->getMaxDamage() * dmgMultiply, true);
+	printLine(4, CGI->generaltexth->allTexts[388], c->valOfBonuses(Bonus::STACK_HEALTH), stackNode->valOfBonuses(Bonus::STACK_HEALTH));
+	printLine(6, CGI->generaltexth->zelp[441].first, c->valOfBonuses(Bonus::STACKS_SPEED), stackNode->valOfBonuses(Bonus::STACKS_SPEED));
+
+	if (stack)
+	{
+		if (STACK_EXP)
+		{
+			printAtMiddle("Rank " + boost::lexical_cast<std::string>(stack->getExpRank()), 425, 60, FONT_MEDIUM, tytulowy,*bitmap);
+			printAtMiddle(boost::lexical_cast<std::string>(stack->experience), 425, 80, FONT_SMALL, zwykly,*bitmap);
+		}
+
+		if (STACK_ARTIFACT && type > BATTLE)
+		{
+			//SDL_Rect rect = genRect(44,44,465,98);
+			//creatureArtifact = new CArtPlace(NULL);
+			//creatureArtifact->pos = rect;
+			//creatureArtifact->ourOwner = NULL; //hmm?
+			leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::scrollArt, this, -1), 437, 98, "hsbtns3.def", SDLK_LEFT);
+			rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind (&CCreatureWindow::scrollArt, this, +1), 516, 98, "hsbtns5.def", SDLK_RIGHT);
+		}
+		else
+			creatureArtifact = NULL;
+	}
+
+	if(const CStack *battleStack = dynamic_cast<const CStack*>(stackNode)) //only during battle
+	{
+		//spell effects
+		int printed=0; //how many effect pics have been printed
+		std::vector<si32> spells = battleStack->activeSpells();
+		BOOST_FOREACH(si32 effect, spells)
+		{
+			blitAt(graphics->spellEffectsPics->ourImages[effect + 1].bitmap, 21 + 52 * printed, 186, *bitmap); 
+			if (++printed >= 10) //we can fit only 10 effects
+				break;
+		}
+		//print current health
+		printLine (5, CGI->generaltexth->allTexts[200], battleStack->firstHPleft);
+	}
+
+	//All bonuses - abilities
+
+	BonusList bl = stackNode->getBonuses(Selector::durationType(Bonus::PERMANENT));
+	//BonusList bl = stackNode->getBonuses(Selector::sourceTypeSel(Bonus::CREATURE_ABILITY));
+	int bonusRows = bl.size() / 3;
+	int bonusHeight = bonusRows * 60;
+	//TODO: Scroll them
+	std::string text;
+	int i = 0, j = 0;
+
+	BOOST_FOREACH(Bonus* b, bl)
+	{
+		int offsetx = 60*i;
+		int offsety = 170*j;
+
+		text = stack->bonusToString(b, false);
+		if (text.size())
+		{
+			printAt(text, 80 + offsety, 242 + offsetx, FONT_SMALL, tytulowy, *bitmap);
+			//graphics (21 + offsetx, 233 + offsetty)
+			if (++j > 2) //next line
+			{
+				++i;
+				j = 0;
+			}
+		}
+
+			//text = stack->bonusToString(*it, true);
+			//if (text.size())
+			//	printAt(text, 80 + offsety, 262 + offsetx, FONT_SMALL, zwykly, *bitmap);
+	}
+
+	//AUIDAT.DEF
+}
+CCreatureWindow::CCreatureWindow(const CStackInstance &st, int Type, boost::function<void()> Upg, boost::function<void()> Dsm, UpgradeInfo *ui)
+	: type(Type), dsm(Dsm), dismiss(0), upgrade(0), ok(0)
+{
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+	init(&st, &st,dynamic_cast<const CGHeroInstance*>(st.armyObj));
+
+	//print abilities text - if r-click popup
+	if(type)
+	{
+		if(Upg && ui)
+		{
+			bool enough = true;
+			for(std::set<std::pair<int,int> >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost
+			{
+				BLOCK_CAPTURING;
+				if(LOCPLINT->cb->getResourceAmount(i->first) < i->second*st.count)
+					enough = false;
+				upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*st.count)); 
+			}
+
+			if(enough)
+			{
+				CFunctionList<void()> fs;
+				fs += Upg;
+				fs += boost::bind(&CCreatureWindow::close,this);
+				CFunctionList<void()> cfl;
+				cfl = boost::bind(&CPlayerInterface::showYesNoDialog, LOCPLINT, CGI->generaltexth->allTexts[207], boost::ref(upgResCost), fs, 0, false);
+				upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,cfl,385, 148,"IVIEWCR.DEF",SDLK_u);
+			}
+			else
+			{
+				upgrade = new AdventureMapButton("",CGI->generaltexth->zelp[446].second,boost::function<void()>(),385, 148,"IVIEWCR.DEF");
+				upgrade->callback.funcs.clear();
+				upgrade->setOffset(2);
+			}
+
+		}
+		if(Dsm)
+		{
+			CFunctionList<void()> fs[2];
+			//on dismiss confirmed
+			fs[0] += Dsm; //dismiss
+			fs[0] += boost::bind(&CCreatureWindow::close,this);//close this window
+			CFunctionList<void()> cfl;
+			cfl = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector<SComponent*>(),fs[0],fs[1],false);
+			dismiss = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,cfl,333, 148,"IVIEWCR2.DEF",SDLK_d);
+		}
+		ok = new AdventureMapButton("",CGI->generaltexth->zelp[445].second,boost::bind(&CCreatureWindow::close,this),489, 148,"IOKAY.DEF",SDLK_RETURN); //TODO: Remove duplicate
+	}
+}
+
+void CCreatureWindow::printLine(int nr, const std::string &text, int baseVal, int val/*=-1*/, bool range/*=false*/)
+{
+	printAt(text, 155, 48 + nr*19, FONT_SMALL, zwykly, *bitmap);
+
+	std::string hlp;
+	if(range && baseVal != val)
+		hlp = boost::str(boost::format("%d - %d") % baseVal % val);
+	else if(baseVal != val && val>=0)
+		hlp = boost::str(boost::format("%d (%d)") % baseVal % val);
+	else
+		hlp = boost::lexical_cast<std::string>(baseVal);
+
+	printTo(hlp, 325, 64 + nr*19, FONT_SMALL, zwykly, *bitmap);
+}
+
+void CCreatureWindow::scrollArt(int dir)
+{
+}
+
+void CCreatureWindow::close()
+{
+	GH.popIntTotally(this);
+}

+ 67 - 0
client/CCreatureWindow.h

@@ -0,0 +1,67 @@
+#include "../global.h"
+#include "GUIBase.h"
+#include "GUIClasses.h"
+#include "../lib/HeroBonus.h"
+
+/*
+ * CCreatureWindow.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+class Bonus;
+class CCreature;
+class CStackInstance;
+class CStack;
+class AdventureMapButton;
+
+class CCreatureWindow : public CIntObject
+{
+public:
+	enum CreWinType {OTHER = 0, BATTLE = 1, ARMY = 2, HERO = 3};
+	//bool active; //TODO: comment me
+	int type;//0 - rclick popup; 1 - normal window
+	CPicture *bitmap; //background
+	std::string count; //creature count in text format
+
+	boost::function<void()> dsm; //dismiss button callback
+	boost::function<void()> Upg; //upgrade button callback
+	CCreaturePic *anim; //related creature's animation
+	const CCreature *c; //related creature
+	std::vector<SComponent*> upgResCost; //cost of upgrade (if not possible then empty)
+
+	MoraleLuckBox *luck, *morale;
+	LRClickableAreaWText * expArea; //displays exp details
+	CArtPlace *creatureArtifact;
+
+	CSlider * slider; //Abilities
+	AdventureMapButton *dismiss, *upgrade, *ok;
+	AdventureMapButton * leftArtRoll, * rightArtRoll; //artifact selection - do we need it?
+	//TODO: Arifact drop
+
+	//CCreatureWindow(const CStackInstance &st, boost::function<void()> Upg = 0, boost::function<void()> Dsm = 0, UpgradeInfo *ui = NULL); //c-tor
+	CCreatureWindow(const CStack & stack, int type); //battle c-tor
+	CCreatureWindow (const CStackInstance &stack, int Type); //pop-up c-tor
+	CCreatureWindow(const CStackInstance &st, int Type, boost::function<void()> Upg, boost::function<void()> Dsm, UpgradeInfo *ui); //full garrison window
+	//CCreatureWindow(int Cid, int Type, int creatureCount); //c-tor
+	void init(const CStackInstance *stack, const CBonusSystemNode *stackNode, const CGHeroInstance *heroOwner);
+	void printLine(int nr, const std::string &text, int baseVal, int val=-1, bool range=false);
+	//~CCreatureWindow(); //d-tor
+	//void activate();
+	void close();
+	//void clickRight(tribool down, bool previousState); //call-in
+	//void dismissF();
+	//void keyPressed (const SDL_KeyboardEvent & key); //call-in
+	//void deactivate();
+	//void show(SDL_Surface * to);
+	void scrollArt(int dir);
+};
+
+class CBonusItem : LRClickableAreaWTextComp //responsible for displaying creature skill, active or not
+{
+	const Bonus * bonus;
+};

+ 1 - 1
client/CMessage.cpp

@@ -28,7 +28,7 @@
 
 SDL_Color tytulowy = {229, 215, 123, 0}, 
 	tlo = {66, 44, 24, 0}, 
-	zwykly = {255, 255, 255, 0},
+	zwykly = {255, 243, 222, 0},
 	darkTitle = {215, 175, 78, 0};
 
 extern SDL_Surface * screen;

+ 7 - 2
client/GUIClasses.cpp

@@ -6,6 +6,7 @@
 #include "CBattleInterface.h"
 #include "../CCallback.h"
 #include "CCastleInterface.h"
+#include "CCreatureWindow.h"
 #include "CCursorHandler.h"
 #include "CGameInfo.h"
 #include "CHeroWindow.h"
@@ -169,7 +170,10 @@ bool CGarrisonSlot::our()
 void CGarrisonSlot::clickRight(tribool down, bool previousState)
 {
 	if(down && creature)
-		GH.pushInt(new CCreInfoWindow(*myStack));
+	{
+		//GH.pushInt(new CCreInfoWindow(*myStack));
+		GH.pushInt(new CCreatureWindow(*myStack, 4));
+	}
 }
 void CGarrisonSlot::clickLeft(tribool down, bool previousState)
 {
@@ -189,7 +193,8 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
 				if (canUpgrade) upgr = boost::bind(&CCallback::upgradeCreature, LOCPLINT->cb, getObj(), ID, pom.newID[0]);
 				if (canDismiss) dism = boost::bind(&CCallback::dismissCreature, LOCPLINT->cb, getObj(), ID);
 
-				CCreInfoWindow *creWindow = new CCreInfoWindow( *myStack, 1, upgr, dism, &pom);
+				//CCreInfoWindow *creWindow = new CCreInfoWindow( *myStack, 1, upgr, dism, &pom);
+				CCreatureWindow *creWindow = new CCreatureWindow( *myStack, 2, upgr, dism, &pom);
 				
 				GH.pushInt(creWindow);
 

+ 2 - 1
global.h

@@ -126,7 +126,8 @@ const int CREEP_SIZE = 2000000000;
 const int WEEKLY_GROWTH = 10; //percent
 const int AVAILABLE_HEROES_PER_PLAYER = 2;
 const bool DWELLINGS_ACCUMULATE_CREATURES = true;
-const bool STACK_EXP = false;
+const bool STACK_EXP = true;
+const bool STACK_ARTIFACT = true;
 
 const int BFIELD_WIDTH = 17;
 const int BFIELD_HEIGHT = 11;

+ 0 - 1
lib/CCreatureHandler.cpp

@@ -979,7 +979,6 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, std::string & src
 			loadToIt (curVal, src, it, 4);
 			if (curVal == 1)
 			{
-				b.val = curVal;
 				b.limiter.reset (new RankRangeLimiter(i));
 				bl.push_back(new Bonus(b));
 				break; //never turned off it seems

+ 6 - 0
lib/HeroBonus.cpp

@@ -749,6 +749,7 @@ namespace Selector
 	DLL_EXPORT CSelectFieldEqual<TBonusType> type(&Bonus::type, 0);
 	DLL_EXPORT CSelectFieldEqual<TBonusSubtype> subtype(&Bonus::subtype, 0);
 	DLL_EXPORT CSelectFieldEqual<si32> info(&Bonus::additionalInfo, 0);
+	DLL_EXPORT CSelectFieldEqual<ui16> duration(&Bonus::duration, 0);
 	DLL_EXPORT CSelectFieldEqual<ui8> sourceType(&Bonus::source, 0);
 	DLL_EXPORT CSelectFieldEqual<ui8> effectRange(&Bonus::effectRange, Bonus::NO_LIMIT);
 	DLL_EXPORT CWillLastTurns turns;
@@ -768,6 +769,11 @@ namespace Selector
 		return CSelectFieldEqual<ui8>(&Bonus::source, source) && CSelectFieldEqual<ui32>(&Bonus::sid, sourceID);
 	}
 
+	CSelector DLL_EXPORT durationType(ui16 duration)
+	{
+		return CSelectFieldEqual<ui16>(&Bonus::duration, duration);
+	}
+
 	CSelector DLL_EXPORT sourceTypeSel(ui8 source)
 	{
 		return CSelectFieldEqual<ui8>(&Bonus::source, source);

+ 3 - 1
lib/HeroBonus.h

@@ -183,7 +183,7 @@ struct DLL_EXPORT Bonus
 		ARTIFACT,
 		ARTIFACT_INSTANCE,
 		OBJECT,
-		CREATURE_ABILITY,
+			CREATURE_ABILITY,
 		TERRAIN_NATIVE,
 		TERRAIN_OVERLAY,
 		SPELL_EFFECT,
@@ -696,6 +696,7 @@ namespace Selector
 	extern DLL_EXPORT CSelectFieldEqual<TBonusType> type;
 	extern DLL_EXPORT CSelectFieldEqual<TBonusSubtype> subtype;
 	extern DLL_EXPORT CSelectFieldEqual<si32> info;
+	extern DLL_EXPORT CSelectFieldEqual<ui16> duration;
 	extern DLL_EXPORT CSelectFieldEqual<ui8> sourceType;
 	extern DLL_EXPORT CSelectFieldEqual<ui8> effectRange;
 	extern DLL_EXPORT CWillLastTurns turns;
@@ -703,6 +704,7 @@ namespace Selector
 	CSelector DLL_EXPORT typeSybtype(TBonusType Type, TBonusSubtype Subtype);
 	CSelector DLL_EXPORT typeSybtypeInfo(TBonusType type, TBonusSubtype subtype, si32 info);
 	CSelector DLL_EXPORT source(ui8 source, ui32 sourceID);
+	CSelector DLL_EXPORT durationType(ui16 duration);
 	CSelector DLL_EXPORT sourceTypeSel(ui8 source);
 
 	bool DLL_EXPORT matchesType(const CSelector &sel, TBonusType type);