浏览代码

* moving units and some minor improvements

mateuszb 17 年之前
父节点
当前提交
fc4e0215fb
共有 9 个文件被更改,包括 143 次插入78 次删除
  1. 15 63
      CBattleInterface.cpp
  2. 4 2
      CBattleInterface.h
  3. 14 0
      CCallback.cpp
  4. 3 2
      CCallback.h
  5. 4 4
      CGameInterface.h
  6. 95 2
      CGameState.cpp
  7. 2 0
      CGameState.h
  8. 4 3
      CPlayerInterface.cpp
  9. 2 2
      CPlayerInterface.h

+ 15 - 63
CBattleInterface.cpp

@@ -14,7 +14,7 @@ extern SDL_Surface * screen;
 SDL_Surface * CBattleInterface::cellBorder, * CBattleInterface::cellShade;
 
 CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2) 
-: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1)
+: printCellBorders(true), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), curStackActed(false)
 {
 	//initializing armies
 	this->army1 = army1;
@@ -181,14 +181,8 @@ void CBattleInterface::show(SDL_Surface * to)
 		}
 	}
 	//showing selected unit's range
-	for(std::map<int, CCreatureAnimation*>::iterator j=creAnims.begin(); j!=creAnims.end(); ++j)
-	{
-		if(j->first == activeStack) //print range of selected unit //TODO: check if it is to be done
-		{
-			showRange(to, stacks[j->first].position, LOCPLINT->cb->battleGetCreature(j->first).speed);
-			break;
-		}
-	}
+	showRange(to, activeStack);
+
 	//showing menu background
 	blitAt(menu, 0, 556, to);
 
@@ -281,75 +275,33 @@ void CBattleInterface::stackRemoved(CStack stack)
 
 void CBattleInterface::stackActivated(int number)
 {
+	curStackActed = false;
 	activeStack = number;
 }
 
 void CBattleInterface::stackMoved(int number, int destHex)
 {
+	int curStackPos = LOCPLINT->cb->battleGetPos(number);
+	for(int i=0; i<6; ++i)
+	{
+		//creAnims[number]->setType(0);
+	}
 }
 
 void CBattleInterface::hexLclicked(int whichOne)
 {
 	if((whichOne%17)!=0 && (whichOne%17)!=16)
+	{
 		LOCPLINT->cb->battleMoveCreature(activeStack, whichOne);
+	}
 }
 
-void CBattleInterface::showRange(SDL_Surface * to, int initialPlace, int radius)
+void CBattleInterface::showRange(SDL_Surface * to, int ID)
 {
-	int dists[187]; //calculated distances
-	std::queue<int> hexq; //bfs queue
-	hexq.push(initialPlace);
-	for(int g=0; g<187; ++g)
-		dists[g] = 100000000;
-	dists[initialPlace] = 0;
-	int curNext = -1; //for bfs loop only (helper var)
-	while(!hexq.empty()) //bfs loop
+	std::vector<int> shadedHexes = LOCPLINT->cb->battleGetAvailableHexes(ID);
+	for(int i=0; i<shadedHexes.size(); ++i)
 	{
-		int curHex = hexq.front();
-		hexq.pop();
-		curNext = curHex - ( (curHex/17)%2 ? 17 : 18 );
-		if((curNext > 0) && bfield[curNext].accesible  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
-		{
-			hexq.push(curNext);
-			dists[curNext] = dists[curHex] + 1;
-		}
-		curNext = curHex - ( (curHex/17)%2 ? 16 : 17 );
-		if((curNext > 0) && bfield[curNext].accesible  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
-		{
-			hexq.push(curNext);
-			dists[curNext] = dists[curHex] + 1;
-		}
-		curNext = curHex - 1;
-		if((curNext > 0) && bfield[curNext].accesible  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
-		{
-			hexq.push(curNext);
-			dists[curNext] = dists[curHex] + 1;
-		}
-		curNext = curHex + 1;
-		if((curNext < 187) && bfield[curNext].accesible  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
-		{
-			hexq.push(curNext);
-			dists[curNext] = dists[curHex] + 1;
-		}
-		curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
-		if((curNext < 187) && bfield[curNext].accesible  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
-		{
-			hexq.push(curNext);
-			dists[curNext] = dists[curHex] + 1;
-		}
-		curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
-		if((curNext < 187) && bfield[curNext].accesible  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
-		{
-			hexq.push(curNext);
-			dists[curNext] = dists[curHex] + 1;
-		}
-	}
-	for(int i=0; i<187; ++i)
-	{
-		if(dists[i]<=radius)
-		{
-			CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[i].pos);
-		}
+		CSDL_Ext::blit8bppAlphaTo24bpp(CBattleInterface::cellShade, NULL, to, &bfield[shadedHexes[i]].pos);
 	}
 }
 

+ 4 - 2
CBattleInterface.h

@@ -56,10 +56,10 @@ private:
 	CBattleHero * attackingHero, * defendingHero;
 	CCreatureSet * army1, * army2; //fighting armies
 	CGHeroInstance * attackingHeroInstance, * defendingHeroInstance;
-	std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order like in BattleInfo's stacks)
+	std::map< int, CCreatureAnimation * > creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
 	unsigned char animCount;
 	int activeStack; //number of active stack; -1 - no one
-	void showRange(SDL_Surface * to, int initialPlace, int radius); //show helper funtion ot mark range of a unit
+	void showRange(SDL_Surface * to, int ID); //show helper funtion ot mark range of a unit
 
 public:
 	CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2); //c-tor
@@ -70,6 +70,7 @@ public:
 	CBattleHex bfield[187]; //11 lines, 17 hexes on each
 	std::vector< CBattleObstacle * > obstacles; //vector of obstacles on the battlefield
 	static SDL_Surface * cellBorder, * cellShade;
+	bool curStackActed; //true if we have i.e. moved current unit
 
 	//button handle funcs:
 	void bOptionsf();
@@ -92,5 +93,6 @@ public:
 	void stackRemoved(CStack stack); //stack disappeared from batlefiled
 	void stackActivated(int number); //active stack has been changed
 	void stackMoved(int number, int destHex); //stack with id number moved to destHex
+	void turnEnded(); //caled when current unit cannot get new orders
 	void hexLclicked(int whichOne); //hex only call-in
 };

+ 14 - 0
CCallback.cpp

@@ -540,6 +540,15 @@ int CCallback::battleGetBattlefieldType()
 	return CGI->mh->ttiles[CGI->state->curB->tile.x][CGI->state->curB->tile.y][CGI->state->curB->tile.z].terType;
 }
 
+int CCallback::battleGetPos(int stack)
+{
+	for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
+	{
+		if(CGI->state->curB->stacks[g]->ID == stack)
+			return CGI->state->curB->stacks[g]->position;
+	}
+}
+
 std::map<int, CStack> CCallback::battleGetStacks()
 {
 	std::map<int, CStack> ret;
@@ -568,6 +577,11 @@ bool CCallback::battleMoveCreature(int ID, int dest)
 	return CGI->state->battleMoveCreatureStack(ID, dest); //everything finished successfully
 }
 
+std::vector<int> CCallback::battleGetAvailableHexes(int ID)
+{
+	return CGI->state->battleGetRange(ID);
+}
+
 int3 CScriptCallback::getPos(CGObjectInstance * ob)
 {
 	return ob->pos;

+ 3 - 2
CCallback.h

@@ -11,7 +11,7 @@ class CGObjectInstance;
 class SComponent;
 class IChosen;
 class CSelectableComponent;
-struct Action;
+struct BattleAction;
 typedef struct lua_State lua_State;
 
 class ICallback
@@ -98,10 +98,11 @@ public:
 	int battleGetObstaclesAtTile(int tile); //returns bitfield 
 	int battleGetStack(int pos); //returns ID of stack on the tile
 	int battleGetPos(int stack); //returns position (tile ID) of stack
-	int battleMakeAction(Action* action);//perform action with an active stack (or custom action)
+	int battleMakeAction(BattleAction* action);//perform action with an active stack (or custom action)
 	std::map<int, CStack> battleGetStacks(); //returns stacks on battlefield
 	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
 	
 
 //friends

+ 4 - 4
CGameInterface.h

@@ -15,11 +15,11 @@ class CObstacle
 	int position;
 	//TODO: add some kind of the blockmap
 };
-struct Action
+struct BattleAction
 {
 	bool side; //who made this action: false - left, true - right player
 	int stackNumber;//stack ID, -1 left hero, -2 right hero, 
-	int actionType; //    0 = Cancel Action   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) 
+	int 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) 
 	int destinationTile; 
 	int additionalInfo; // e.g. spell number if type is 1 || 10
 };
@@ -46,8 +46,8 @@ public:
 	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 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 actionStarted(Action action){};//occurs BEFORE every action taken by any stack or by the hero
-	virtual void actionFinished(Action 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(BattleAction action){};//occurs AFTER every action taken by any stack or by the hero
 	virtual void activeStack(int stackID){}; //called when it's turn of that stack
 	virtual void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner){};
 	virtual void battleStackMoved(int ID, int dest)=0;

+ 95 - 2
CGameState.cpp

@@ -28,6 +28,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 	curB->side1=(hero1)?(hero1->tempOwner):(-1);
 	curB->side2=(hero2)?(hero2->tempOwner):(-1);
 	curB->round = -2;
+	curB->stackActionPerformed = false;
 	for(std::map<int,std::pair<CCreature*,int> >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++)
 	{
 		stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size()));
@@ -176,6 +177,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 		for(int i=0;i<stacks.size();i++)
 		{
 			curB->activeStack = i;
+			curB->stackActionPerformed = false;
 			if(stacks[i]->alive) //niech interfejs ruszy oddzialem
 			{
 				unsigned char owner = (stacks[i]->owner)?(hero2->tempOwner):(hero1->tempOwner);
@@ -210,6 +212,9 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 
 bool CGameState::battleMoveCreatureStack(int ID, int dest)
 {
+	//first checks
+	if(curB->stackActionPerformed) //because unit cannot be moved more than once
+		return false;
 	//selecting moved stack
 	CStack * curStack = NULL;
 	for(int y=0; y<curB->stacks.size(); ++y)
@@ -245,14 +250,14 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
 	{
 		int curHex = hexq.front();
 		hexq.pop();
-		curNext = curHex - ( (curHex/17)%2 ? 17 : 18 );
+		curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
 		if((curNext > 0) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
 		{
 			hexq.push(curNext);
 			dists[curNext] = dists[curHex] + 1;
 			predecessor[curNext] = curHex;
 		}
-		curNext = curHex - ( (curHex/17)%2 ? 16 : 17 );
+		curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
 		if((curNext > 0) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
 		{
 			hexq.push(curNext);
@@ -301,6 +306,94 @@ bool CGameState::battleMoveCreatureStack(int ID, int dest)
 	for(int v=path.size()-1; v>=0; --v)
 	{
 		LOCPLINT->battleStackMoved(ID, path[v]);
+		curStack->position = path[v];
 	}
+	curB->stackActionPerformed = true;
+	LOCPLINT->actionFinished(BattleAction());
 	return true;
 }
+
+std::vector<int> CGameState::battleGetRange(int ID)
+{
+	int initialPlace=-1; //position of unit
+	int radius=-1; //range of unit
+	for(int g=0; g<curB->stacks.size(); ++g)
+	{
+		if(curB->stacks[g]->ID == ID)
+		{
+			initialPlace = curB->stacks[g]->position;
+			radius = curB->stacks[g]->creature->speed;
+			break;
+		}
+	}
+
+	bool accessibility[187]; //accesibility of hexes
+	for(int k=0; k<187; k++)
+		accessibility[k] = true;
+	for(int g=0; g<curB->stacks.size(); ++g)
+	{
+		accessibility[curB->stacks[g]->position] = false;
+	}
+
+
+	int dists[187]; //calculated distances
+	std::queue<int> hexq; //bfs queue
+	hexq.push(initialPlace);
+	for(int g=0; g<187; ++g)
+		dists[g] = 100000000;
+	dists[initialPlace] = 0;
+	int curNext = -1; //for bfs loop only (helper var)
+	while(!hexq.empty()) //bfs loop
+	{
+		int curHex = hexq.front();
+		hexq.pop();
+		curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
+		if((curNext > 0) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+		}
+		curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
+		if((curNext > 0) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+		}
+		curNext = curHex - 1;
+		if((curNext > 0) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+		}
+		curNext = curHex + 1;
+		if((curNext < 187) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+		}
+		curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
+		if((curNext < 187) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+		}
+		curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
+		if((curNext < 187) && accessibility[curNext]  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+		}
+	}
+
+	std::vector<int> ret;
+
+	for(int i=0; i<187; ++i)
+	{
+		if(dists[i]<=radius)
+		{
+			ret.push_back(i);
+		}
+	}
+	return ret;
+}
+

+ 2 - 0
CGameState.h

@@ -35,6 +35,7 @@ struct BattleInfo
 	CGHeroInstance *hero1, *hero2;
 	CCreatureSet * army1, * army2;
 	std::vector<CStack*> stacks;
+	bool stackActionPerformed; //true if current stack has been moved
 };
 
 class CStack
@@ -88,6 +89,7 @@ private:
 	}
 	void battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2);
 	bool battleMoveCreatureStack(int ID, int dest);
+	std::vector<int> battleGetRange(int ID); //called by std::vector<int> CCallback::battleGetAvailableHexes(int ID);
 public:
 	friend CCallback;
 	friend CPathfinder;;

+ 4 - 3
CPlayerInterface.cpp

@@ -1889,19 +1889,20 @@ void CPlayerInterface::battleNewRound(int round) //called at the beggining of ea
 {
 }
 
-void CPlayerInterface::actionStarted(Action action)//occurs BEFORE every action taken by any stack or by the hero
+void CPlayerInterface::actionStarted(BattleAction action)//occurs BEFORE every action taken by any stack or by the hero
 {
 }
 
-void CPlayerInterface::actionFinished(Action action)//occurs AFTER 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)->curStackActed = true;
 }
 
 void CPlayerInterface::activeStack(int stackID) //called when it's turn of that stack
 {
 	unsigned char showCount = 0;
 	dynamic_cast<CBattleInterface*>(curint)->stackActivated(stackID);
-	while(true)
+	while(!dynamic_cast<CBattleInterface*>(curint)->curStackActed) //while current unit can perform an action
 	{
 		++showCount;
 		SDL_Event sEvent;

+ 2 - 2
CPlayerInterface.h

@@ -314,8 +314,8 @@ public:
 	void battleStart(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, tribool 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 battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
-	void actionStarted(Action action);//occurs BEFORE every action taken by any stack or by the hero
-	void actionFinished(Action 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(BattleAction action);//occurs AFTER every action taken by any stack or by the hero
 	void activeStack(int stackID); //called when it's turn of that stack
 	void battleEnd(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, std::vector<int> capturedArtifacts, int expForWinner, bool winner);
 	void battleStackMoved(int ID, int dest);