Parcourir la source

* battle settings will be remembered between battles
* call-ins for serializing client and playerinterfaces (not used really yet)

Michał W. Urbańczyk il y a 16 ans
Parent
commit
fca28fab10

+ 24 - 22
CBattleInterface.cpp

@@ -33,6 +33,8 @@ extern SDL_Surface * screen;
 extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
 extern SDL_Color zwykly;
 
+BattleSettings CBattleInterface::settings;
+
 struct CMP_stack2
 {
 	inline bool operator ()(const CStack& a, const CStack& b)
@@ -42,9 +44,9 @@ struct CMP_stack2
 } cmpst2 ;
 
 CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect)
-: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), givenCommand(NULL),
-	attackingInfo(NULL), myTurn(false), resWindow(NULL), showStackQueue(false), animSpeed(2), printStackRange(true),
-	printMouseShadow(true), spellDestSelectMode(false), spellToCast(NULL), previouslyHoveredHex(-1), moveStarted(false), mouseHoveredStack(-1)
+  : attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), givenCommand(NULL),
+	attackingInfo(NULL), myTurn(false), resWindow(NULL), showStackQueue(false), 
+	spellDestSelectMode(false), spellToCast(NULL), previouslyHoveredHex(-1), moveStarted(false), mouseHoveredStack(-1)
 {
 	pos = myRect;
 	strongInterest = true;
@@ -311,19 +313,19 @@ CBattleInterface::~CBattleInterface()
 
 void CBattleInterface::setPrintCellBorders(bool set)
 {
-	printCellBorders = set;
+	settings.printCellBorders = set;
 	redrawBackgroundWithHexes(activeStack);
 }
 
 void CBattleInterface::setPrintStackRange(bool set)
 {
-	printStackRange = set;
+	settings.printStackRange = set;
 	redrawBackgroundWithHexes(activeStack);
 }
 
 void CBattleInterface::setPrintMouseShadow(bool set)
 {
-	printMouseShadow = set;
+	settings.printMouseShadow = set;
 }
 
 void CBattleInterface::activate()
@@ -392,7 +394,7 @@ void CBattleInterface::show(SDL_Surface * to)
 	{
 		//showing background
 		blitAt(background, pos.x, pos.y, to);
-		if(printCellBorders)
+		if(settings.printCellBorders)
 		{
 			CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, to, &pos);
 		}
@@ -410,7 +412,7 @@ void CBattleInterface::show(SDL_Surface * to)
 				currentlyHoveredHex = b;
 			}
 			//print shade
-			if(printMouseShadow)
+			if(settings.printMouseShadow)
 			{
 				int x = 14 + ((b/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(b%BFIELD_WIDTH) + pos.x;
 				int y = 86 + 42 * (b/BFIELD_WIDTH) + pos.y;
@@ -448,7 +450,7 @@ void CBattleInterface::show(SDL_Surface * to)
 		int x = ((obstacles[b].pos/BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(obstacles[b].pos%BFIELD_WIDTH);
 		int y = 86 + 42 * (obstacles[b].pos/BFIELD_WIDTH);
 		std::vector<Cimage> &images = idToObstacle[obstacles[b].ID]->ourImages;
-		blitAt(images[((animCount+1)/(4/animSpeed))%images.size()].bitmap, x, y, to);
+		blitAt(images[((animCount+1)/(4/settings.animSpeed))%images.size()].bitmap, x, y, to);
 	}
 
 	//showing hero animations
@@ -488,13 +490,13 @@ void CBattleInterface::show(SDL_Surface * to)
 			int curStackID = stackAliveByHex[b][v];
 			const CStack &curStack = stacks[curStackID];
 			int animType = creAnims[curStackID]->getType();
-			bool incrementFrame = (animCount%(4/animSpeed)==0) && animType!=5 && animType!=20 && animType!=3 && animType!=2;
+			bool incrementFrame = (animCount%(4/settings.animSpeed)==0) && animType!=5 && animType!=20 && animType!=3 && animType!=2;
 
 			if(animType == 2)
 			{
 				if(standingFrame.find(curStackID)!=standingFrame.end())
 				{
-					incrementFrame = (animCount%(8/animSpeed)==0);
+					incrementFrame = (animCount%(8/settings.animSpeed)==0);
 					if(incrementFrame)
 					{
 						++standingFrame[curStackID];
@@ -934,7 +936,7 @@ void CBattleInterface::handleStartMoving(int number)
 		show();
 		CSDL_Ext::update();
 		SDL_framerateDelay(LOCPLINT->mainFPSmng);
-		if((animCount+1)%(4/animSpeed)==0)
+		if((animCount+1)%(4/settings.animSpeed)==0)
 			creAnims[number]->incrementFrame();
 	}
 }
@@ -1250,7 +1252,7 @@ void CBattleInterface::stacksAreAttacked(std::vector<CBattleInterface::SStackAtt
 		SDL_framerateDelay(LOCPLINT->mainFPSmng);
 		for(size_t g=0; g<attackedInfos.size(); ++g)
 		{
-			if((animCount+1)%(4/animSpeed)==0 && !creAnims[attackedInfos[g].ID]->onLastFrameInGroup())
+			if((animCount+1)%(4/settings.animSpeed)==0 && !creAnims[attackedInfos[g].ID]->onLastFrameInGroup())
 			{
 				creAnims[attackedInfos[g].ID]->incrementFrame();
 			}
@@ -1851,17 +1853,17 @@ void CBattleInterface::displayEffect(ui32 effect, int destTile)
 
 void CBattleInterface::setAnimSpeed(int set)
 {
-	animSpeed = set;
+	settings.animSpeed = set;
 }
 
 int CBattleInterface::getAnimSpeed() const
 {
-	return animSpeed;
+	return settings.animSpeed;
 }
 
 float CBattleInterface::getAnimSpeedMultiplier() const
 {
-	switch(animSpeed)
+	switch(settings.animSpeed)
 	{
 	case 1:
 		return 3.5f;
@@ -2059,7 +2061,7 @@ void CBattleInterface::attackingShowHelper()
 		if(attackingInfo)
 		{
 			attackingInfo->hitCount++;
-			if(attackingInfo->hitCount%(4/animSpeed) == 0)
+			if(attackingInfo->hitCount%(4/settings.animSpeed) == 0)
 				attackingInfo->frame++;
 		}
 	}
@@ -2071,10 +2073,10 @@ void CBattleInterface::redrawBackgroundWithHexes(int activeStack)
 
 	//preparating background graphic with hexes and shaded hexes
 	blitAt(background, 0, 0, backgroundWithHexes);
-	if(printCellBorders)
+	if(settings.printCellBorders)
 		CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, backgroundWithHexes, NULL);
 
-	if(printStackRange)
+	if(settings.printStackRange)
 	{
 		for(size_t m=0; m<shadedHexes.size(); ++m) //rows
 		{
@@ -2688,11 +2690,11 @@ CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInt
 	graphics->blueToPlayersAdv(background, LOCPLINT->playerID);
 
 	viewGrid = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintCellBorders, owner, true), boost::bind(&CBattleInterface::setPrintCellBorders, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[427].first)(3,CGI->generaltexth->zelp[427].first), CGI->generaltexth->zelp[427].second, false, "sysopchk.def", NULL, 185, 140, false);
-	viewGrid->select(owner->printCellBorders);
+	viewGrid->select(owner->settings.printCellBorders);
 	movementShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintStackRange, owner, true), boost::bind(&CBattleInterface::setPrintStackRange, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[428].first)(3,CGI->generaltexth->zelp[428].first), CGI->generaltexth->zelp[428].second, false, "sysopchk.def", NULL, 185, 173, false);
-	movementShadow->select(owner->printStackRange);
+	movementShadow->select(owner->settings.printStackRange);
 	mouseShadow = new CHighlightableButton(boost::bind(&CBattleInterface::setPrintMouseShadow, owner, true), boost::bind(&CBattleInterface::setPrintMouseShadow, owner, false), boost::assign::map_list_of(0,CGI->generaltexth->zelp[429].first)(3,CGI->generaltexth->zelp[429].first), CGI->generaltexth->zelp[429].second, false, "sysopchk.def", NULL, 185, 207, false);
-	mouseShadow->select(owner->printMouseShadow);
+	mouseShadow->select(owner->settings.printMouseShadow);
 
 	animSpeeds = new CHighlightableButtonsGroup(0);
 	animSpeeds->addButton(boost::assign::map_list_of(0,CGI->generaltexth->zelp[422].first),CGI->generaltexth->zelp[422].second, "sysopb9.def",188, 309, 1);

+ 27 - 9
CBattleInterface.h

@@ -119,6 +119,27 @@ public:
 	void show(SDL_Surface * to = 0);
 };
 
+struct BattleSettings
+{
+	BattleSettings()
+	{
+		printCellBorders = true;
+		printStackRange = true;
+		animSpeed = 2;
+		printMouseShadow = true;
+	}
+	bool printCellBorders; //if true, cell borders will be printed
+	bool printStackRange; //if true,range of active stack will be printed
+	int animSpeed; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
+	bool printMouseShadow; //if true, hex under mouse will be shaded
+
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & printCellBorders & printStackRange & printMouseShadow;
+	}
+};
+
 class CBattleInterface : public CMainInterface, public MotionInterested, public KeyInterested
 {
 private:
@@ -140,7 +161,6 @@ private:
 	std::vector<int> shadedHexes; //hexes available for active stack
 	int previouslyHoveredHex; //number of hex that was hovered by the cursor a while ago
 	int currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon)
-	int animSpeed; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
 	float getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group
 	std::map<int, int> standingFrame; //number of frame in standing animation by stack ID, helps in showing 'random moves'
 
@@ -193,14 +213,12 @@ public:
 	~CBattleInterface(); //d-tor
 
 	//std::vector<TimeInterested*> timeinterested; //animation handling
-	bool printCellBorders; //if true, cell borders will be printed
-	void setPrintCellBorders(bool set); //set for above member
-	bool printStackRange; //if true,range of active stack will be printed
-	void setPrintStackRange(bool set); //set for above member
-	bool printMouseShadow; //if true, hex under mouse will be shaded
-	void setPrintMouseShadow(bool set); //set for above member
-	void setAnimSpeed(int set); //set for animSpeed
-	int getAnimSpeed() const; //get for animSpeed
+	static BattleSettings settings;
+	void setPrintCellBorders(bool set); //if true, cell borders will be printed
+	void setPrintStackRange(bool set); //if true,range of active stack will be printed
+	void setPrintMouseShadow(bool set); //if true, hex under mouse will be shaded
+	void setAnimSpeed(int set); //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
+	int getAnimSpeed() const; //speed of animation; 1 - slowest, 2 - medium, 4 - fastest
 
 	CBattleHex bfield[BFIELD_SIZE]; //11 lines, 17 hexes on each
 	std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield

+ 5 - 2
CGameInterface.cpp

@@ -29,11 +29,14 @@ CGlobalAI * CAIHandler::getNewAI(CCallback * cb, std::string dllname)
 	void *dll = dlopen(dllname.c_str(), RTLD_LOCAL | RTLD_LAZY);
 	getName = (void(*)(char*))dlsym(dll,"GetAiName");
 	getAI = (CGlobalAI*(*)())dlsym(dll,"GetNewAI");
-	; //TODO: handle AI library on Linux
 #endif
 	getName(temp);
 	tlog0 << "Loaded .dll with AI named " << temp << std::endl;
 	ret = getAI();
-	 
+
+	if(!ret)
+		tlog1 << "Cannot get AI!\n";
+
+	ret->dllName = dllname;	 
 	return ret;
 }

+ 8 - 0
CGameInterface.h

@@ -25,6 +25,11 @@ struct BattleStackAttacked;
 struct SpellCasted;
 struct SetStackEffect;
 struct HeroBonus;
+class CLoadFile;
+class CSaveFile;
+template <typename Serializer> class CISer;
+template <typename Serializer> class COSer;
+
 class CObstacle
 {
 	int ID;
@@ -47,6 +52,7 @@ class CGameInterface
 public:
 	bool human;
 	int playerID, serialID;
+	std::string dllName;
 
 	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
 	virtual void garrisonChanged(const CGObjectInstance * obj){};
@@ -70,6 +76,8 @@ public:
 	virtual void yourTurn(){};
 	virtual void availableCreaturesChanged(const CGTownInstance *town){};
 	virtual void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
+	virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving
+	virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
 
 	//battle call-ins
 	virtual void actionFinished(const BattleAction *action){};//occurs AFTER every action taken by any stack or by the hero

+ 18 - 0
CPlayerInterface.cpp

@@ -21,6 +21,7 @@
 #include "hch/CHeroHandler.h"
 #include "hch/CLodHandler.h"
 #include "hch/CObjectHandler.h"
+#include "lib/Connection.h"
 #include "hch/CSpellHandler.h"
 #include "hch/CTownHandler.h"
 #include "lib/CondSh.h"
@@ -2526,6 +2527,23 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroB
 	redrawHeroWin(hero);
 }
 
+template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version )
+{
+	h & playerID & serialID;
+	h & heroMoveSpeed & mapScrollingSpeed;
+	h & CBattleInterface::settings;
+}
+
+void CPlayerInterface::serialize( COSer<CSaveFile> &h, const int version )
+{
+	serializeTempl(h,version);
+}
+
+void CPlayerInterface::serialize( CISer<CLoadFile> &h, const int version )
+{
+	serializeTempl(h,version);
+}
+
 void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
 {
 	if(!vstd::contains(graphics->heroWins,hero->subID))

+ 8 - 0
CPlayerInterface.h

@@ -546,6 +546,9 @@ public:
 	void yourTurn();
 	void availableCreaturesChanged(const CGTownInstance *town);
 	void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it
+	void serialize(COSer<CSaveFile> &h, const int version); //saving
+	void serialize(CISer<CLoadFile> &h, const int version); //loading
+
 	//for battles
 	void actionFinished(const BattleAction* action);//occurs AFTER action taken by active stack or by the hero
 	void actionStarted(const BattleAction* action);//occurs BEFORE action taken by active stack or by the hero
@@ -583,7 +586,12 @@ public:
 
 	CPlayerInterface(int Player, int serial);//c-tor
 	~CPlayerInterface();//d-tor
+
+	//////////////////////////////////////////////////////////////////////////
+
+	template <typename Handler> void serializeTempl(Handler &h, const int version);
 };
+
 class CStatusBar
 	: public CIntObject, public IStatusBar
 {

+ 39 - 0
client/Client.cpp

@@ -342,3 +342,42 @@ void CClient::waitForServer()
 		shared->sr->cond.wait(slock);
 	}
 }
+
+template <typename Handler>
+void CClient::serialize( Handler &h, const int version )
+{
+	if(h.saving)
+	{
+		ui8 players = playerint.size();
+		h & players;
+
+		for(std::map<ui8,CGameInterface *>::iterator i = playerint.begin(); i != playerint.end(); i++)
+		{
+			h & i->first & i->second->dllName;
+			i->second->serialize(h,version);
+		}
+	}
+	else
+	{
+		ui8 players;
+		h & players;
+
+		for(int i=0; i < players; i++)
+		{
+			std::string dllname;
+			ui8 pid;
+			h & pid & dllname;
+
+			if(dllname.length())
+			{
+				CCallback *callback = new CCallback(gs,pid,this);
+				callbacks.insert(callback);
+				playerint[pid] =  CAIHandler::getNewAI(callback,dllname);
+				playerint[pid]->init(callback);
+			}
+		}
+	}
+}
+
+template void CClient::serialize( CISer<CLoadFile> &h, const int version );
+template void CClient::serialize( COSer<CSaveFile> &h, const int version );

+ 6 - 0
client/Client.h

@@ -5,6 +5,7 @@
 #include "../global.h"
 #include <boost/thread.hpp>
 #include "../lib/IGameCallback.h"
+
 struct StartInfo;
 class CGameState;
 class CGameInterface;
@@ -44,6 +45,7 @@ class CClient : public IGameCallback
 {
 public:
 	CCallback *cb;
+	std::set<CCallback*> callbacks; //callbacks given to player interfaces
 	std::map<ui8,CGameInterface *> playerint;
 	CConnection *serv;
 	SharedMem *shared;
@@ -100,6 +102,10 @@ public:
 	
 	static void runServer(const char * portc);
 	void waitForServer();
+
+	//////////////////////////////////////////////////////////////////////////
+
+	template <typename Handler> void serialize(Handler &h, const int version);
 };
 
 #endif // __CLIENT_H__

+ 6 - 0
client/NetPacksClient.cpp

@@ -3,6 +3,7 @@
 #include "../client/Client.h"
 #include "../CPlayerInterface.h"
 #include "../CGameInfo.h"
+#include "../lib/Connection.h"
 #include "../hch/CGeneralTextHandler.h"
 #include "../hch/CDefObjInfoHandler.h"
 #include "../hch/CHeroHandler.h"
@@ -411,6 +412,11 @@ void YourTurn::applyCl( CClient *cl )
 	boost::thread(boost::bind(&CGameInterface::yourTurn,cl->playerint[player]));
 }
 
+void SaveGame::applyCl(CClient *cl)
+{
+	CSaveFile save("Games" PATHSEPARATOR + fname + ".vcgm1");
+	save << *cl;
+}
 
 void PlayerMessage::applyCl(CClient *cl)
 {

+ 15 - 13
lib/NetPacks.h

@@ -794,19 +794,6 @@ struct ShowInInfobox : public CPackForClient //107
 
 /***********************************************************************************************************/
 
-struct SaveGame : public CPackForServer
-{
-	SaveGame(){};
-	SaveGame(const std::string &Fname) :fname(Fname){};
-	std::string fname;
-
-	void applyGh(CGameHandler *gh);
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & fname;
-	}
-};
-
 struct CloseServer : public CPackForServer
 {
 	void applyGh(CGameHandler *gh);
@@ -1048,6 +1035,21 @@ struct MakeCustomAction : public CPackForServer
 
 /***********************************************************************************************************/
 
+struct SaveGame : public CPackForClient, public CPackForServer
+{
+	SaveGame(){};
+	SaveGame(const std::string &Fname) :fname(Fname){};
+	std::string fname;
+
+	void applyCl(CClient *cl);
+	void applyGs(CGameState *gs){};
+	void applyGh(CGameHandler *gh);
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & fname;
+	}
+};
+
 struct PlayerMessage : public CPackForClient, public CPackForServer //513
 {
 	PlayerMessage(){CPackForClient::type = 513;};

+ 2 - 1
lib/RegisterTypes.cpp

@@ -82,6 +82,7 @@ void registerTypes2(Serializer &s)
 	s.template registerType<SetStackEffect>();
 	s.template registerType<ShowInInfobox>();
 
+	s.template registerType<SaveGame>();
 	s.template registerType<SetSelection>();
 	s.template registerType<PlayerMessage>();
 }
@@ -89,7 +90,6 @@ void registerTypes2(Serializer &s)
 template<typename Serializer> DLL_EXPORT
 void registerTypes3(Serializer &s)
 {
-	s.template registerType<SaveGame>();
 	s.template registerType<CloseServer>();
 	s.template registerType<EndTurn>();
 	s.template registerType<DismissHero>();
@@ -109,6 +109,7 @@ void registerTypes3(Serializer &s)
 	s.template registerType<MakeAction>();
 	s.template registerType<MakeCustomAction>();
 
+	s.template registerType<SaveGame>();
 	s.template registerType<SetSelection>();
 	s.template registerType<PlayerMessage>();
 }

+ 8 - 0
server/CGameHandler.cpp

@@ -1466,6 +1466,14 @@ void CGameHandler::sendAndApply( CPackForClient * info )
 
 void CGameHandler::save( const std::string &fname )
 {
+
+	{
+		tlog0 << "Ordering clients to serialize...\n";
+		SaveGame sg(fname);
+		//TODO: uncomment when client saving is ready
+		//sendToAllClients(&sg);
+	}
+
 	{
 		tlog0 << "Serializing game info...\n";
 		CSaveFile save(std::string("Games") + PATHSEPARATOR + fname + ".vlgm1");