2
0
Эх сурвалжийг харах

* added calls for battle action start/end
* added interface for casting spells
* artifact info in backpack
* artifacts we pick up on the map go to the appropriate slot (if free)

Michał W. Urbańczyk 17 жил өмнө
parent
commit
89cb5cb81b

+ 2 - 1
CBattleInterface.cpp

@@ -713,8 +713,9 @@ void CBattleInterface::stackActivated(int number)
 	redrawBackgroundWithHexes(number);
 	redrawBackgroundWithHexes(number);
 }
 }
 
 
-void CBattleInterface::stackMoved(int number, int destHex, bool startMoving, bool endMoving)
+void CBattleInterface::stackMoved(int number, int destHex, bool endMoving)
 {
 {
+	bool startMoving = creAnims[number]->type==20;
 	//a few useful variables
 	//a few useful variables
 	int curStackPos = LOCPLINT->cb->battleGetPos(number);
 	int curStackPos = LOCPLINT->cb->battleGetPos(number);
 	int steps = creAnims[number]->framesInGroup(0)*getAnimSpeedMultiplier()-1;
 	int steps = creAnims[number]->framesInGroup(0)*getAnimSpeedMultiplier()-1;

+ 1 - 1
CBattleInterface.h

@@ -207,7 +207,7 @@ public:
 	void stackRemoved(CStack stack); //stack disappeared from batlefiled
 	void stackRemoved(CStack stack); //stack disappeared from batlefiled
 	void stackKilled(int ID, int dmg, int killed, int IDby, bool byShooting); //stack has been killed (but corpses remain)
 	void stackKilled(int ID, int dmg, int killed, int IDby, bool byShooting); //stack has been killed (but corpses remain)
 	void stackActivated(int number); //active stack has been changed
 	void stackActivated(int number); //active stack has been changed
-	void stackMoved(int number, int destHex, bool startMoving, bool endMoving); //stack with id number moved to destHex
+	void stackMoved(int number, int destHex, bool endMoving); //stack with id number moved to destHex
 	void stackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting); //called when stack id attacked by stack with id IDby
 	void stackIsAttacked(int ID, int dmg, int killed, int IDby, bool byShooting); //called when stack id attacked by stack with id IDby
 	void stackAttacking(int ID, int dest); //called when stack with id ID is attacking something on hex dest
 	void stackAttacking(int ID, int dest); //called when stack with id ID is attacking something on hex dest
 	void newRound(int number); //caled when round is ended; number is the number of round
 	void newRound(int number); //caled when round is ended; number is the number of round

+ 6 - 0
CCallback.cpp

@@ -452,6 +452,12 @@ CStack* CCallback::battleGetStackByID(int ID)
 	return gs->curB->getStack(ID);
 	return gs->curB->getStack(ID);
 }
 }
 
 
+int CCallback::battleMakeAction(BattleAction* action)
+{
+	*cl->serv << ui16(3003) << *action;
+	return 0;
+}
+
 CStack* CCallback::battleGetStackByPos(int pos)
 CStack* CCallback::battleGetStackByPos(int pos)
 {
 {
 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);

+ 2 - 3
CCallback.h

@@ -75,7 +75,7 @@ public:
 	virtual CStack * battleGetStackByID(int ID)=0; //returns stack info by given ID
 	virtual CStack * battleGetStackByID(int ID)=0; //returns stack info by given ID
 	virtual CStack * battleGetStackByPos(int pos)=0; //returns stack info by given pos
 	virtual CStack * battleGetStackByPos(int pos)=0; //returns stack info by given pos
 	virtual int battleGetPos(int stack)=0; //returns position (tile ID) of stack
 	virtual int battleGetPos(int stack)=0; //returns position (tile ID) of stack
-	//virtual int battleMakeAction(BattleAction* action)=0;//perform action with an active stack (or custom action)
+	virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack
 	virtual std::map<int, CStack> battleGetStacks()=0; //returns stacks on battlefield
 	virtual std::map<int, CStack> battleGetStacks()=0; //returns stacks on battlefield
 	virtual CCreature battleGetCreature(int number)=0; //returns type of creature by given number of stack
 	virtual CCreature battleGetCreature(int number)=0; //returns type of creature by given number of stack
 	//virtual bool battleMoveCreature(int ID, int dest)=0; //moves creature with id ID to dest if possible
 	//virtual bool battleMoveCreature(int ID, int dest)=0; //moves creature with id ID to dest if possible
@@ -159,10 +159,9 @@ public:
 	CStack * battleGetStackByID(int ID); //returns stack info by given ID
 	CStack * battleGetStackByID(int ID); //returns stack info by given ID
 	CStack * battleGetStackByPos(int pos); //returns stack info by given pos
 	CStack * battleGetStackByPos(int pos); //returns stack info by given pos
 	int battleGetPos(int stack); //returns position (tile ID) of stack
 	int battleGetPos(int stack); //returns position (tile ID) of stack
-	//int battleMakeAction(BattleAction* action);//perform action with an active stack (or custom action)
+	int battleMakeAction(BattleAction* action);//for casting spells by hero - DO NOT use it for moving active stack
 	std::map<int, CStack> battleGetStacks(); //returns stacks on battlefield
 	std::map<int, CStack> battleGetStacks(); //returns stacks on battlefield
 	CCreature battleGetCreature(int number); //returns type of creature by given number of stack
 	CCreature battleGetCreature(int number); //returns type of creature by given number of stack
-	//bool battleMoveCreature(int ID, int dest); //moves creature with id ID to dest if possible
 	std::vector<int> battleGetAvailableHexes(int ID); //reutrns numbers of hexes reachable by creature with id ID
 	std::vector<int> battleGetAvailableHexes(int ID); //reutrns numbers of hexes reachable by creature with id ID
 	bool battleIsStackMine(int ID); //returns true if stack with id ID belongs to caller
 	bool battleIsStackMine(int ID); //returns true if stack with id ID belongs to caller
 	bool battleCanShoot(int ID, int dest); //returns true if unit with id ID can shoot to dest
 	bool battleCanShoot(int ID, int dest); //returns true if unit with id ID can shoot to dest

+ 4 - 4
CGameInterface.h

@@ -65,14 +65,14 @@ public:
 	virtual void availableCreaturesChanged(const CGTownInstance *town){};
 	virtual void availableCreaturesChanged(const CGTownInstance *town){};
 
 
 	//battle call-ins
 	//battle call-ins
-	//virtual void actionFinished(BattleAction action){};//occurs AFTER every action taken by any stack or by the hero
-	//virtual void actionStarted(BattleAction action){};//occurs BEFORE every action taken by any stack or by the hero
+	virtual void actionFinished(const BattleAction *action){};//occurs AFTER every action taken by any stack or by the hero
+	virtual void actionStarted(const BattleAction *action){};//occurs BEFORE every action taken by any stack or by the hero
 	virtual BattleAction activeStack(int stackID)=0; //called when it's turn of that stack
 	virtual BattleAction activeStack(int stackID)=0; //called when it's turn of that stack
 	virtual void battleAttack(BattleAttack *ba){};
 	virtual void battleAttack(BattleAttack *ba){};
 	virtual void battleEnd(BattleResult *br){};
 	virtual void battleEnd(BattleResult *br){};
 	virtual void battleNewRound(int round){}; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
 	virtual void battleNewRound(int round){}; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
-	virtual void battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting)=0;
-	virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)=0;
+	virtual void battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting){};
+	virtual void battleStackMoved(int ID, int dest){};
 	virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
 	virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
 	virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
 	virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
 	//
 	//

+ 1 - 0
CGameState.h

@@ -140,6 +140,7 @@ private:
 	std::map<ui8,PlayerState> players; //ID <-> playerstate
 	std::map<ui8,PlayerState> players; //ID <-> playerstate
 	std::map<int, CGDefInfo*> villages, forts, capitols; //def-info for town graphics
 	std::map<int, CGDefInfo*> villages, forts, capitols; //def-info for town graphics
 	std::vector<ui32> resVals;
 	std::vector<ui32> resVals;
+	std::vector<CGHeroInstance *> heroesPool; //[subID] - heroes available to buy; NULL if not available
 
 
 	boost::shared_mutex *mx;
 	boost::shared_mutex *mx;
 
 

+ 28 - 24
CHeroWindow.cpp

@@ -194,6 +194,7 @@ void CHeroWindow::show(SDL_Surface *to)
 
 
 void CHeroWindow::setHero(const CGHeroInstance *Hero)
 void CHeroWindow::setHero(const CGHeroInstance *Hero)
 {
 {
+	char bufor[400];
 	CGHeroInstance *hero = const_cast<CGHeroInstance*>(Hero); //but don't modify hero! - it's only for easy map reading
 	CGHeroInstance *hero = const_cast<CGHeroInstance*>(Hero); //but don't modify hero! - it's only for easy map reading
 	if(!hero) //something strange... no hero? it shouldn't happen
 	if(!hero) //something strange... no hero? it shouldn't happen
 	{
 	{
@@ -204,15 +205,11 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero)
 	gar2button->callback.clear();
 	gar2button->callback.clear();
 	gar2button->callback2.clear();
 	gar2button->callback2.clear();
 
 
-	char * prhlp = new char[200];
-	sprintf(prhlp, CGI->generaltexth->heroscrn[16].c_str(), curHero->name.c_str(), curHero->type->heroClass->name.c_str());
-	dismissButton->hoverTexts[0] = std::string(prhlp);
-	delete [] prhlp;
+	sprintf(bufor, CGI->generaltexth->heroscrn[16].c_str(), curHero->name.c_str(), curHero->type->heroClass->name.c_str());
+	dismissButton->hoverTexts[0] = std::string(bufor);
 
 
-	prhlp = new char[200];
-	sprintf(prhlp, CGI->generaltexth->allTexts[15].c_str(), curHero->name.c_str(), curHero->type->heroClass->name.c_str());
-	portraitArea->hoverText = std::string(prhlp);
-	delete [] prhlp;
+	sprintf(bufor, CGI->generaltexth->allTexts[15].c_str(), curHero->name.c_str(), curHero->type->heroClass->name.c_str());
+	portraitArea->hoverText = std::string(bufor);
 
 
 	portraitArea->text = hero->biography;
 	portraitArea->text = hero->biography;
 
 
@@ -232,20 +229,15 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero)
 		std::string hlp = CGI->abilh->abilities[ hero->secSkills[g].first ]->infoTexts[hero->secSkills[g].second-1];
 		std::string hlp = CGI->abilh->abilities[ hero->secSkills[g].first ]->infoTexts[hero->secSkills[g].second-1];
 		secSkillAreas[g]->text = hlp.substr(1, hlp.size()-2);
 		secSkillAreas[g]->text = hlp.substr(1, hlp.size()-2);
 
 
-		char * hlpp = new char[200];
-		sprintf(hlpp, CGI->generaltexth->heroscrn[21].c_str(), CGI->abilh->levels[hero->secSkills[g].second-1].c_str(), CGI->abilh->abilities[hero->secSkills[g].first]->name.c_str());
-		secSkillAreas[g]->hoverText = std::string(hlpp);
-		delete [] hlpp;
+		sprintf(bufor, CGI->generaltexth->heroscrn[21].c_str(), CGI->abilh->levels[hero->secSkills[g].second-1].c_str(), CGI->abilh->abilities[hero->secSkills[g].first]->name.c_str());
+		secSkillAreas[g]->hoverText = std::string(bufor);
 	}
 	}
 
 
-	char * th = new char[200];
-	sprintf(th, CGI->generaltexth->allTexts[2].substr(1, CGI->generaltexth->allTexts[2].size()-2).c_str(), hero->level, CGI->heroh->reqExp(hero->level+1), hero->exp);
-	expArea->text = std::string(th);
-	delete [] th;
-	th = new char[400];
-	sprintf(th, CGI->generaltexth->allTexts[205].substr(1, CGI->generaltexth->allTexts[205].size()-2).c_str(), hero->name.c_str(), hero->mana, hero->primSkills[3]*10);
-	spellPointsArea->text = std::string(th);
-	delete [] th;
+	sprintf(bufor, CGI->generaltexth->allTexts[2].substr(1, CGI->generaltexth->allTexts[2].size()-2).c_str(), hero->level, CGI->heroh->reqExp(hero->level+1), hero->exp);
+	expArea->text = std::string(bufor);
+
+	sprintf(bufor, CGI->generaltexth->allTexts[205].substr(1, CGI->generaltexth->allTexts[205].size()-2).c_str(), hero->name.c_str(), hero->mana, hero->primSkills[3]*10);
+	spellPointsArea->text = std::string(bufor);
 
 
 	for(int g=0; g<artWorn.size(); ++g)
 	for(int g=0; g<artWorn.size(); ++g)
 	{
 	{
@@ -277,19 +269,31 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero)
 	for(int g=0; g<artWorn.size(); ++g)
 	for(int g=0; g<artWorn.size(); ++g)
 	{
 	{
 		artWorn[g]->slotID = g;
 		artWorn[g]->slotID = g;
-		char * hll = new char[200];
-		sprintf(hll, CGI->generaltexth->heroscrn[1].c_str(), (artWorn[g]->ourArt ? artWorn[g]->ourArt->name.c_str() : ""));
-		artWorn[g]->hoverText = std::string(hll);
-		delete [] hll;
+		if(artWorn[g]->ourArt)
+		{
+			sprintf(bufor, CGI->generaltexth->heroscrn[1].c_str(), artWorn[g]->ourArt->name.c_str());
+			artWorn[g]->hoverText = std::string(bufor);
+		}
+		else
+		{
+			artWorn[g]->hoverText = CGI->generaltexth->allTexts[507];
+		}
 	}
 	}
 
 
 	for(int s=0; s<5; ++s)
 	for(int s=0; s<5; ++s)
 	{
 	{
 		CArtPlace * add;
 		CArtPlace * add;
 		if( s < curHero->artifacts.size() )
 		if( s < curHero->artifacts.size() )
+		{
 			add = new CArtPlace(&CGI->arth->artifacts[curHero->artifacts[(s+backpackPos) % curHero->artifacts.size() ]]);
 			add = new CArtPlace(&CGI->arth->artifacts[curHero->artifacts[(s+backpackPos) % curHero->artifacts.size() ]]);
+			sprintf(bufor, CGI->generaltexth->heroscrn[1].c_str(), add->ourArt->name.c_str());
+			add->hoverText = bufor;
+		}
 		else
 		else
+		{
 			add = new CArtPlace(NULL);
 			add = new CArtPlace(NULL);
+			add->hoverText = CGI->generaltexth->allTexts[507];
+		}
 		add->pos.x = 403 + 46*s;
 		add->pos.x = 403 + 46*s;
 		add->pos.y = 365;
 		add->pos.y = 365;
 		add->pos.h = add->pos.w = 44;
 		add->pos.h = add->pos.w = 44;

+ 1 - 1
CLua.cpp

@@ -589,7 +589,7 @@ void CPickable::onHeroVisit(int objid, int heroID)
 	{
 	{
 	case 5: //artifact
 	case 5: //artifact
 		{
 		{
-			cb->giveHeroArtifact(os->subID,heroID,-1); //TODO: na pozycje
+			cb->giveHeroArtifact(os->subID,heroID,-2);
 			InfoWindow iw;
 			InfoWindow iw;
 			iw.player = cb->getOwner(heroID);
 			iw.player = cb->getOwner(heroID);
 			iw.components.push_back(Component(4,os->subID,0,0));
 			iw.components.push_back(Component(4,os->subID,0,0));

+ 18 - 15
CPlayerInterface.cpp

@@ -2012,17 +2012,19 @@ void CPlayerInterface::battlefieldPrepared(int battlefieldType, std::vector<CObs
 
 
 void CPlayerInterface::battleNewRound(int round) //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
 void CPlayerInterface::battleNewRound(int round) //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
 {
 {
+	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	dynamic_cast<CBattleInterface*>(curint)->newRound(round);
 	dynamic_cast<CBattleInterface*>(curint)->newRound(round);
 }
 }
 
 
-//void CPlayerInterface::actionStarted(BattleAction action)//occurs BEFORE every action taken by any stack or by the hero
-//{
-//}
-//
-//void CPlayerInterface::actionFinished(BattleAction action)//occurs AFTER every action taken by any stack or by the hero
-//{
-//	//dynamic_cast<CBattleInterface*>(curint)->givenCommand = -1;
-//}
+void CPlayerInterface::actionStarted(const BattleAction* action)
+{
+	curAction = action;
+}
+
+void CPlayerInterface::actionFinished(const BattleAction* action)
+{
+	curAction = NULL;
+}
 
 
 BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
 BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
 {
 {
@@ -2047,12 +2049,13 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
 
 
 void CPlayerInterface::battleEnd(BattleResult *br)
 void CPlayerInterface::battleEnd(BattleResult *br)
 {
 {
+	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	((CBattleInterface*)curint)->battleFinished(*br);
 	((CBattleInterface*)curint)->battleFinished(*br);
 }
 }
 
 
 void CPlayerInterface::battleResultQuited()
 void CPlayerInterface::battleResultQuited()
 {
 {
-	//boost::unique_lock<boost::recursive_mutex> un(*pim);
+	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	((CBattleInterface*)curint)->resWindow->deactivate();
 	((CBattleInterface*)curint)->resWindow->deactivate();
 	objsToBlit -= curint;
 	objsToBlit -= curint;
 	delete curint;
 	delete curint;
@@ -2060,10 +2063,10 @@ void CPlayerInterface::battleResultQuited()
 	adventureInt->activate();
 	adventureInt->activate();
 }
 }
 
 
-void CPlayerInterface::battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)
+void CPlayerInterface::battleStackMoved(int ID, int dest)
 {
 {
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
 	boost::unique_lock<boost::recursive_mutex> un(*pim);
-	dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest, startMoving, endMoving);
+	dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest,dest==curAction->destinationTile);
 }
 }
 void CPlayerInterface::battleAttack(BattleAttack *ba)
 void CPlayerInterface::battleAttack(BattleAttack *ba)
 {
 {
@@ -2082,10 +2085,10 @@ void CPlayerInterface::battleStackKilled(int ID, int dmg, int killed, int IDby,
 	dynamic_cast<CBattleInterface*>(curint)->stackKilled(ID, dmg, killed, IDby, byShooting);
 	dynamic_cast<CBattleInterface*>(curint)->stackKilled(ID, dmg, killed, IDby, byShooting);
 }
 }
 
 
-void CPlayerInterface::battleStackIsShooting(int ID, int dest)
-{
-	dynamic_cast<CBattleInterface*>(curint)->stackIsShooting(ID, dest);
-}
+//void CPlayerInterface::battleStackIsShooting(int ID, int dest)
+//{
+//	dynamic_cast<CBattleInterface*>(curint)->stackIsShooting(ID, dest);
+//}
 
 
 void CPlayerInterface::showComp(SComponent comp)
 void CPlayerInterface::showComp(SComponent comp)
 {
 {

+ 6 - 5
CPlayerInterface.h

@@ -327,6 +327,7 @@ public:
 	IStatusBar *statusbar;
 	IStatusBar *statusbar;
 	//to commucate with engine
 	//to commucate with engine
 	CCallback * cb;
 	CCallback * cb;
+	const BattleAction *curAction;
 
 
 	//GUI elements
 	//GUI elements
 	std::list<ClickableL*> lclickable;
 	std::list<ClickableL*> lclickable;
@@ -357,16 +358,16 @@ public:
 	void yourTurn();
 	void yourTurn();
 	void availableCreaturesChanged(const CGTownInstance *town);
 	void availableCreaturesChanged(const CGTownInstance *town);
 	//for battles
 	//for battles
-	//void actionFinished(BattleAction action);//occurs AFTER every action taken by any stack or by the hero
-	//void actionStarted(BattleAction action);//occurs BEFORE every action taken by any stack or by the hero
+	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
 	BattleAction activeStack(int stackID); //called when it's turn of that stack
 	BattleAction activeStack(int stackID); //called when it's turn of that stack
-	void battleAttack(BattleAttack *ba);
+	void battleAttack(BattleAttack *ba); //stack performs attack
 	void battleEnd(BattleResult *br);
 	void battleEnd(BattleResult *br);
 	void battleResultQuited();
 	void battleResultQuited();
 	void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
 	void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
-	void battleStackIsShooting(int ID, int dest); //called when stack with id ID is shooting to hex dest
+	//void battleStackIsShooting(int ID, int dest); //called when stack with id ID is shooting to hex dest
 	void battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting);
 	void battleStackKilled(int ID, int dmg, int killed, int IDby, bool byShooting);
-	void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving);
+	void battleStackMoved(int ID, int dest);
 	void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
 	void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
 	void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
 	void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
 
 

+ 1 - 1
CPreGame.cpp

@@ -977,9 +977,9 @@ void MapSel::show()
 	//SDL_Flip(screen);
 	//SDL_Flip(screen);
 	CSDL_Ext::update(screen);
 	CSDL_Ext::update(screen);
 }
 }
-boost::mutex mx;
 void MapSel::processMaps(std::vector<std::string> &pliczkiTemp, int &index)
 void MapSel::processMaps(std::vector<std::string> &pliczkiTemp, int &index)
 {
 {
+	static boost::mutex mx;
 	bool areMaps=true;
 	bool areMaps=true;
 	int pom=-1;
 	int pom=-1;
 	while(areMaps)
 	while(areMaps)

+ 1 - 1
client/CCreatureAnimation.h

@@ -29,8 +29,8 @@ private:
 	unsigned char * FDef; //animation raw data
 	unsigned char * FDef; //animation raw data
 	unsigned int curFrame; //number of currently displayed frame
 	unsigned int curFrame; //number of currently displayed frame
 	unsigned int frames; //number of frames
 	unsigned int frames; //number of frames
-	int type; //type of animation being displayed (-1 - whole animation, >0 - specified part [default: -1])
 public:
 public:
+	int type; //type of animation being displayed (-1 - whole animation, >0 - specified part [default: -1])
 	int fullWidth, fullHeight; //read-only, please!
 	int fullWidth, fullHeight; //read-only, please!
 	CCreatureAnimation(std::string name); //c-tor
 	CCreatureAnimation(std::string name); //c-tor
 	~CCreatureAnimation(); //d-tor
 	~CCreatureAnimation(); //d-tor

+ 28 - 7
client/Client.cpp

@@ -167,6 +167,7 @@ CClient::~CClient(void)
 }
 }
 void CClient::process(int what)
 void CClient::process(int what)
 {
 {
+	static BattleAction curbaction;
 	switch (what)
 	switch (what)
 	{
 	{
 	case 100: //one of our interaces has turn
 	case 100: //one of our interaces has turn
@@ -518,9 +519,9 @@ void CClient::process(int what)
 			*serv >> br;
 			*serv >> br;
 			tlog5 << "Stack "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
 			tlog5 << "Stack "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
 			if(playerint.find(gs->curB->side1) != playerint.end())
 			if(playerint.find(gs->curB->side1) != playerint.end())
-				playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile,br.flags&1,br.flags&2);
+				playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile);
 			if(playerint.find(gs->curB->side2) != playerint.end())
 			if(playerint.find(gs->curB->side2) != playerint.end())
-				playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile,br.flags&1,br.flags&2);
+				playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile);
 			gs->apply(&br);
 			gs->apply(&br);
 			break;
 			break;
 		}
 		}
@@ -533,14 +534,34 @@ void CClient::process(int what)
 			LOCPLINT->battleAttack(&ba);
 			LOCPLINT->battleAttack(&ba);
 			break;
 			break;
 		}
 		}
+	case 3007:
+		{
+			*serv >> curbaction;
+			tlog5 << "Action started. ID: " << curbaction.actionType << ". Destination: "<< curbaction.destinationTile <<std::endl;
+			if(playerint.find(gs->curB->side1) != playerint.end())
+				playerint[gs->curB->side1]->actionStarted(&curbaction);
+			if(playerint.find(gs->curB->side2) != playerint.end())
+				playerint[gs->curB->side2]->actionStarted(&curbaction);
+			break;
+		}
+	case 3008:
+		{
+			tlog5 << "Action ended!\n";
+			if(!gs->curB)
+			{
+				tlog2 << "There is no battle state!\n";
+				break;
+			}
+			if(playerint.find(gs->curB->side1) != playerint.end())
+				playerint[gs->curB->side1]->actionFinished(&curbaction);
+			if(playerint.find(gs->curB->side2) != playerint.end())
+				playerint[gs->curB->side2]->actionFinished(&curbaction);
+			break;
+		}
 	case 9999:
 	case 9999:
 		break;
 		break;
 	default:
 	default:
-#ifndef __GNUC__
-		throw std::exception("Not supported server message!");
-#else
-		throw std::exception();
-#endif
+		throw std::string("Not supported server message!");
 		break;
 		break;
 	}
 	}
 }
 }

+ 1 - 1
lib/BattleAction.h

@@ -5,7 +5,7 @@ struct BattleAction
 	ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
 	ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
 	ui8 actionType; //    0 = Cancel BattleAction   1 = Hero cast a spell   2 = Walk   3 = Defend   4 = Retreat from the battle   5 = Surrender   6 = Walk and Attack   7 = Shoot    8 = Wait   9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)
 	ui8 actionType; //    0 = Cancel BattleAction   1 = Hero cast a spell   2 = Walk   3 = Defend   4 = Retreat from the battle   5 = Surrender   6 = Walk and Attack   7 = Shoot    8 = Wait   9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)
 	ui16 destinationTile;
 	ui16 destinationTile;
-	si32 additionalInfo; // e.g. spell number if type is 1 || 10
+	si32 additionalInfo; // e.g. spell number if type is 1 || 10; tile to attack if type is 6
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
 		h & side & stackNumber & actionType & destinationTile & additionalInfo;
 		h & side & stackNumber & actionType & destinationTile & additionalInfo;

+ 14 - 14
lib/NetPacks.h

@@ -1,4 +1,5 @@
 #include "../global.h"
 #include "../global.h"
+#include "BattleAction.h"
 struct IPack
 struct IPack
 {
 {
 	virtual ui16 getType()const = 0 ;
 	virtual ui16 getType()const = 0 ;
@@ -404,22 +405,10 @@ struct BattleResult : public CPack<BattleResult>//3003
 struct BattleStackMoved : public CPack<BattleStackMoved>//3004
 struct BattleStackMoved : public CPack<BattleStackMoved>//3004
 {
 {
 	ui32 stack, tile;
 	ui32 stack, tile;
-	ui8 flags; // 1 - start moving, 2 - end moving
-
-
-
-	BattleStackMoved(){flags = 0; type = 3004;};
-	bool startMoving()
-	{
-		return flags & 1;
-	}
-	bool endMoving()
-	{
-		return flags & 2;
-	}
+	BattleStackMoved(){type = 3004;};
 	template <typename Handler> void serialize(Handler &h, const int version)
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 	{
-		h & stack & tile & flags;
+		h & stack & tile;
 	}
 	}
 };
 };
 
 
@@ -468,6 +457,17 @@ struct BattleAttack : public CPack<BattleAttack>//3006
 	}
 	}
 };
 };
 
 
+struct StartAction : public CPack<StartAction>//3007
+{
+	BattleAction ba;
+	StartAction(){type = 3007;};
+	StartAction(const BattleAction &act){ba = act; type = 3007;};
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & ba;
+	}
+};
+
 struct ShowInInfobox : public CPack<ShowInInfobox> //107
 struct ShowInInfobox : public CPack<ShowInInfobox> //107
 {
 {
 	ShowInInfobox(){type = 107;};
 	ShowInInfobox(){type = 107;};

+ 48 - 8
server/CGameHandler.cpp

@@ -890,14 +890,16 @@ upgend:
 					break;
 					break;
 				}
 				}
 			case 3002:
 			case 3002:
-				{			
+				{	
 					BattleAction ba;
 					BattleAction ba;
 					c >> ba;
 					c >> ba;
 					switch(ba.actionType)
 					switch(ba.actionType)
 					{
 					{
 					case 2: //walk
 					case 2: //walk
 						{
 						{
-							moveStack(ba.stackNumber,ba.destinationTile);
+							sendAndApply(&StartAction(ba)); //start movement
+							moveStack(ba.stackNumber,ba.destinationTile); //move
+							sendDataToClients(ui16(3008)); //endmovement
 							break;
 							break;
 						}
 						}
 					case 3: //defend
 					case 3: //defend
@@ -918,6 +920,7 @@ upgend:
 						}
 						}
 					case 6: //walk or attack
 					case 6: //walk or attack
 						{
 						{
+							sendAndApply(&StartAction(ba)); //start movement and attack
 							moveStack(ba.stackNumber,ba.destinationTile);
 							moveStack(ba.stackNumber,ba.destinationTile);
 							CStack *curStack = gs->curB->getStack(ba.stackNumber),
 							CStack *curStack = gs->curB->getStack(ba.stackNumber),
 								*stackAtEnd = gs->curB->getStackT(ba.additionalInfo);
 								*stackAtEnd = gs->curB->getStackT(ba.additionalInfo);
@@ -940,18 +943,22 @@ upgend:
 							}
 							}
 
 
 							if(vstd::contains(curStack->abilities,TWICE_ATTACK)
 							if(vstd::contains(curStack->abilities,TWICE_ATTACK)
-								&& curStack->alive())
+								&& curStack->alive()
+								&& stackAtEnd->alive()  )
 							{
 							{
 								bat.flags = 0;
 								bat.flags = 0;
 								prepareAttack(bat,curStack,stackAtEnd);
 								prepareAttack(bat,curStack,stackAtEnd);
 								sendAndApply(&bat);
 								sendAndApply(&bat);
 							}
 							}
+							sendDataToClients(ui16(3008)); //end movement and attack
 							break;
 							break;
 						}
 						}
 					case 7: //shoot
 					case 7: //shoot
 						{
 						{
 							//TODO: check arrows count
 							//TODO: check arrows count
 							//TODO: check if stack isn't blocked by enemy
 							//TODO: check if stack isn't blocked by enemy
+
+							sendAndApply(&StartAction(ba)); //start shooting
 							CStack *curStack = gs->curB->getStack(ba.stackNumber),
 							CStack *curStack = gs->curB->getStack(ba.stackNumber),
 								*destStack= gs->curB->getStackT(ba.destinationTile);
 								*destStack= gs->curB->getStackT(ba.destinationTile);
 
 
@@ -967,11 +974,48 @@ upgend:
 							}
 							}
 
 
 							sendAndApply(&bat);
 							sendAndApply(&bat);
+							sendDataToClients(ui16(3008)); //end shooting
 							break;
 							break;
 						}
 						}
 					}
 					}
 					battleMadeAction.setn(true);
 					battleMadeAction.setn(true);
-					//sprawdzic czy po tej akcji ktoras strona nie wygrala bitwy
+					break;
+				}
+			case 3003: //custom action (probably spell)
+				{
+					BattleAction ba;
+					c >> ba;
+					switch(ba.actionType)
+					{
+					case 1: //hero casts spell
+						{
+							CGHeroInstance *h = (ba.side) ? gs->curB->hero2 : gs->curB->hero1;
+							CSpell *s = &VLC->spellh->spells[ba.additionalInfo];
+							int skill = 0;
+
+							if(s->fire)
+								skill = std::max(skill,h->getSecSkillLevel(14);
+							if(s->air)
+								skill = std::max(skill,h->getSecSkillLevel(15);
+							if(s->water)
+								skill = std::max(skill,h->getSecSkillLevel(16);
+							if(s->earth)
+								skill = std::max(skill,h->getSecSkillLevel(17);
+
+							if(  !vstd::contains(h->spells,ba.additionalInfo) //hero doesn't know this spell
+								|| (h->mana < s->costs[skill]) //not enough mana
+								|| 0     )//TODO: hero has already casted a spell in this round
+							{
+								goto customactionend;
+							}
+
+							sendAndApply(&StartAction(ba)); //start spell casting
+							//TODO: spell efects
+							sendDataToClients(ui16(3008)); //end casting
+							break;
+						}
+					}
+customactionend:
 					break;
 					break;
 				}
 				}
 			default:
 			default:
@@ -1023,10 +1067,6 @@ void CGameHandler::moveStack(int stack, int dest)
 		BattleStackMoved sm;
 		BattleStackMoved sm;
 		sm.stack = curStack->ID;
 		sm.stack = curStack->ID;
 		sm.tile = path[v];
 		sm.tile = path[v];
-		if(v==path.size()-1) //move start - set flag
-			sm.flags |= 1;
-		if(v==0) //move end - set flag
-			sm.flags |= 2;
 		sendAndApply(&sm);
 		sendAndApply(&sm);
 	}
 	}
 }
 }

+ 9 - 0
server/CGameHandler.h

@@ -86,6 +86,15 @@ public:
 		gsm.unlock();
 		gsm.unlock();
 	}
 	}
 
 
+	template <typename T>void sendDataToClients(const T & data)
+	{
+		for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
+		{
+			(*i)->wmx->lock();
+			**i << data;
+			(*i)->wmx->unlock();
+		}
+	}
 	template <typename T>void sendToAllClients(CPack<T> * info)
 	template <typename T>void sendToAllClients(CPack<T> * info)
 	{
 	{
 		for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
 		for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)

+ 23 - 1
server/CScriptCallback.cpp

@@ -4,6 +4,7 @@
 #include "CGameHandler.h"
 #include "CGameHandler.h"
 #include "../CGameState.h"
 #include "../CGameState.h"
 #include "../map.h"
 #include "../map.h"
+#include "../hch/CArtHandler.h"
 #include "../hch/CObjectHandler.h"
 #include "../hch/CObjectHandler.h"
 #include "../hch/CTownHandler.h"
 #include "../hch/CTownHandler.h"
 #include "../hch/CHeroHandler.h"
 #include "../hch/CHeroHandler.h"
@@ -173,12 +174,33 @@ void CScriptCallback::giveHeroArtifact(int artid, int hid, int position) //pos==
 	sha.artifacts = h->artifacts;
 	sha.artifacts = h->artifacts;
 	sha.artifWorn = h->artifWorn;
 	sha.artifWorn = h->artifWorn;
 	if(position<0)
 	if(position<0)
-		sha.artifacts.push_back(artid);
+	{
+		if(position == -2)
+		{
+			int i;
+			for(i=0; i<VLC->arth->artifacts[artid].possibleSlots.size(); i++) //try to put artifact into first avaialble slot
+			{
+				if( !vstd::contains(sha.artifWorn,VLC->arth->artifacts[artid].possibleSlots[i]) )
+				{
+					sha.artifWorn[VLC->arth->artifacts[artid].possibleSlots[i]] = artid;
+					break;
+				}
+			}
+			if(i==VLC->arth->artifacts[artid].possibleSlots.size()) //if haven't find proper slot, use backpack
+				sha.artifacts.push_back(artid);
+		}
+		else //should be -1 => putartifact into backpack
+		{
+			sha.artifacts.push_back(artid);
+		}
+	}
 	else
 	else
+	{
 		if(!vstd::contains(sha.artifWorn,ui16(position)))
 		if(!vstd::contains(sha.artifWorn,ui16(position)))
 			sha.artifWorn[position] = artid;
 			sha.artifWorn[position] = artid;
 		else
 		else
 			sha.artifacts.push_back(artid);
 			sha.artifacts.push_back(artid);
+	}
 	gh->sendAndApply(&sha);
 	gh->sendAndApply(&sha);
 }
 }
 
 

+ 1 - 1
server/CScriptCallback.h

@@ -52,7 +52,7 @@ public:
 	void showCompInfo(ShowInInfobox * comp);
 	void showCompInfo(ShowInInfobox * comp);
 	void heroVisitCastle(int obj, int heroID);
 	void heroVisitCastle(int obj, int heroID);
 	void stopHeroVisitCastle(int obj, int heroID);
 	void stopHeroVisitCastle(int obj, int heroID);
-	void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack
+	void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
 	void startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
 	void startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
 	void startBattle(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
 	void startBattle(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
 	void setAmount(int objid, ui32 val);
 	void setAmount(int objid, ui32 val);