소스 검색

* improved handling of animations in battles

mateuszb 16 년 전
부모
커밋
e77e49783a
6개의 변경된 파일71개의 추가작업 그리고 47개의 파일을 삭제
  1. 56 36
      client/CBattleInterface.cpp
  2. 4 2
      client/CBattleInterface.h
  3. 1 1
      client/CPlayerInterface.cpp
  4. 2 2
      lib/NetPacks.h
  5. 6 4
      server/CGameHandler.cpp
  6. 2 2
      server/CGameHandler.h

+ 56 - 36
client/CBattleInterface.cpp

@@ -218,7 +218,14 @@ bool CDefenceAnim::init()
 		if(dynamic_cast<CBattleAttack *>(it->first))
 			continue;
 
-		if(dynamic_cast<CReverseAnim *>(it->first))
+		const CStack * attacker = LOCPLINT->cb->battleGetStackByID(IDby, false);
+		int attackerAnimType = owner->creAnims[IDby]->getType();
+		if( attackerAnimType == 11 && attackerAnimType == 12 && attackerAnimType == 13 && owner->creAnims[IDby]->getFrame() < attacker->creature->attackClimaxFrame )
+			return false;
+
+		CReverseAnim * animAsRev = dynamic_cast<CReverseAnim *>(it->first);
+
+		if(animAsRev && animAsRev->priority)
 			return false;
 
 		if(it->first)
@@ -276,18 +283,13 @@ bool CDefenceAnim::init()
 
 void CDefenceAnim::nextFrame()
 {
-	if(continueAnim)
+	if(!owner->creAnims[stackID]->onLastFrameInGroup())
 	{
 		if( owner->creAnims[stackID]->getType() == 5 && (owner->animCount+1)%(4/CBattleInterface::settings.animSpeed)==0
 			&& !owner->creAnims[stackID]->onLastFrameInGroup() )
 		{
 			owner->creAnims[stackID]->incrementFrame();
 		}
-
-		if(owner->creAnims[stackID]->onLastFrameInGroup())
-		{
-			continueAnim = false;
-		}
 	}
 	else
 	{
@@ -328,7 +330,7 @@ void CDefenceAnim::endAnim()
 }
 
 CDefenceAnim::CDefenceAnim(SStackAttackedInfo _attackedInfo, CBattleInterface * _owner)
-: CBattleStackAnimation(_owner, _attackedInfo.ID), continueAnim(true), dmg(_attackedInfo.dmg),
+: CBattleStackAnimation(_owner, _attackedInfo.ID), dmg(_attackedInfo.dmg),
 	amountKilled(_attackedInfo.amountKilled), IDby(_attackedInfo.IDby), byShooting(_attackedInfo.byShooting),
 	killed(_attackedInfo.killed)
 {
@@ -356,8 +358,6 @@ bool CBattleStackMoved::init()
 	std::pair<int, int> begPosition = CBattleHex::getXYUnitAnim(curStackPos, movedStack->attackerOwned, movedStack, owner);
 	std::pair<int, int> endPosition = CBattleHex::getXYUnitAnim(destHex, movedStack->attackerOwned, movedStack, owner);
 
-	CGI->curh->hide();
-
 	int mutPos = BattleInfo::mutualPosition(curStackPos, destHex);
 	
 	//reverse unit if necessary
@@ -556,9 +556,7 @@ void CBattleMoveEnd::endAnim()
 {
 	CBattleAnimation::endAnim();
 
-	const CStack * movedStack = LOCPLINT->cb->battleGetStackByID(stackID);
-
-	if(movedStack)
+	if(owner->creAnims[stackID]->getType() != 5)
 		owner->creAnims[stackID]->setType(2); //resetting to default
 
 	CGI->curh->show();
@@ -642,7 +640,7 @@ bool CMeleeAttack::init()
 	//	return false;
 	//}
 
-	owner->pendingAnims.push_back(std::make_pair(new CBattleMoveStart(owner, stackID), false));
+	//owner->pendingAnims.push_back(std::make_pair(new CBattleMoveStart(owner, stackID), false));
 
 	const CStack * aStack = LOCPLINT->cb->battleGetStackByID(stackID, false); //attacking stack
 
@@ -885,10 +883,10 @@ CShootingAnim::CShootingAnim(CBattleInterface * _owner, int attacker, int _dest)
 ////////////////////////
 
 CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect)
-	: attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), 
+	: attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), activeStack(-1), stackToActivate(-1),
 	  mouseHoveredStack(-1), previouslyHoveredHex(-1), currentlyHoveredHex(-1), spellDestSelectMode(false),
 	  spellToCast(NULL), givenCommand(NULL), myTurn(false), resWindow(NULL), animIDhelper(0),
-	  showStackQueue(false), moveStarted(false), moveSh(-1), siegeH(NULL)
+	  showStackQueue(false), moveStarted(false), moveSh(-1), siegeH(NULL), bresult(NULL)
 {
 	pos = myRect;
 	strongInterest = true;
@@ -1355,15 +1353,23 @@ void CBattleInterface::show(SDL_Surface * to)
 	if(preSize > 0 && pendingAnims.size() == 0)
 	{
 		//restoring good directions of stacks
-		std::map<int, CStack> stacks = LOCPLINT->cb->battleGetStacks();
-
 		for(std::map<int, CStack>::const_iterator it = stacks.begin(); it != stacks.end(); ++it)
 		{
-			if(creDir[it->second.ID] != bool(it->second.attackerOwned))
+			if(creDir[it->second.ID] != bool(it->second.attackerOwned) && it->second.alive())
 			{
 				pendingAnims.push_back(std::make_pair(new CReverseAnim(this, it->second.ID, it->second.position, false), false));
 			}
 		}
+
+		//activation of next stack
+		if(pendingAnims.size() == 0 && stackToActivate != -1)
+		{
+			activateStack();
+		}
+		if(pendingAnims.size() == 0 && bresult != NULL)
+		{
+			displayBattleFinished();
+		}
 	}
 
 	for(int b=0; b<BFIELD_SIZE; ++b) //showing dead stacks
@@ -1926,22 +1932,9 @@ void CBattleInterface::stackRemoved(int stackID)
 void CBattleInterface::stackActivated(int number)
 {
 	//givenCommand = NULL;
-	activeStack = number;
-	myTurn = true;
-	redrawBackgroundWithHexes(number);
-	bWait->block(vstd::contains(LOCPLINT->cb->battleGetStackByID(number)->state,WAITING)); //block waiting button if stack has been already waiting
-
-	//block cast spell button if hero doesn't have a spellbook
-	if(attackingHeroInstance && attackingHeroInstance->tempOwner==LOCPLINT->cb->battleGetStackByID(number)->owner)
-	{
-		if(!attackingHeroInstance->getArt(17)) //don't unlock if already locked
-			bSpell->block(!attackingHeroInstance->getArt(17));
-	}
-	else if(defendingHeroInstance && defendingHeroInstance->tempOwner==LOCPLINT->cb->battleGetStackByID(number)->owner)
-	{
-		if(!defendingHeroInstance->getArt(17)) //don't unlock if already locked
-			bSpell->block(!defendingHeroInstance->getArt(17));
-	}
+	stackToActivate = number;
+	if(pendingAnims.size() == 0)
+		activateStack();
 }
 
 void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int distance)
@@ -2269,12 +2262,18 @@ void CBattleInterface::stackIsShooting(int ID, int dest)
 }
 
 void CBattleInterface::battleFinished(const BattleResult& br)
+{
+	bresult = &br;
+	displayBattleFinished();
+}
+
+void CBattleInterface::displayBattleFinished()
 {
 	CGI->curh->changeGraphic(0,0);
 	
 	SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
 	CGI->musich->stopMusic();
-	resWindow = new CBattleResultWindow(br, temp_rect, this);
+	resWindow = new CBattleResultWindow(*bresult, temp_rect, this);
 	GH.pushInt(resWindow);
 }
 
@@ -2522,6 +2521,27 @@ int CBattleInterface::getAnimSpeed() const
 	return settings.animSpeed;
 }
 
+void CBattleInterface::activateStack()
+{
+	activeStack = stackToActivate;
+	stackToActivate = -1;
+	myTurn = true;
+	redrawBackgroundWithHexes(activeStack);
+	bWait->block(vstd::contains(LOCPLINT->cb->battleGetStackByID(activeStack)->state,WAITING)); //block waiting button if stack has been already waiting
+
+	//block cast spell button if hero doesn't have a spellbook
+	if(attackingHeroInstance && LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned)
+	{
+		if(!attackingHeroInstance->getArt(17)) //don't unlock if already locked
+			bSpell->block(!attackingHeroInstance->getArt(17));
+	}
+	else if(defendingHeroInstance && !LOCPLINT->cb->battleGetStackByID(activeStack)->attackerOwned)
+	{
+		if(!defendingHeroInstance->getArt(17)) //don't unlock if already locked
+			bSpell->block(!defendingHeroInstance->getArt(17));
+	}
+}
+
 float CBattleInterface::getAnimSpeedMultiplier() const
 {
 	switch(settings.animSpeed)

+ 4 - 2
client/CBattleInterface.h

@@ -104,8 +104,6 @@ private:
 	int IDby; //ID of attacking stack
 	bool byShooting; //if true, stack has been attacked by shooting
 	bool killed; //if true, stack has been killed
-
-	bool continueAnim;
 public:
 	bool init();
 	void nextFrame();
@@ -332,6 +330,8 @@ private:
 	std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation>
 	unsigned char animCount;
 	int activeStack; //number of active stack; -1 - no one
+	int stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; -1 of none
+	void activateStack(); //sets activeStack to stackToActivate etc.
 	int mouseHoveredStack; //stack hovered by mouse; if -1 -> none
 	std::vector<int> shadedHexes; //hexes available for active stack
 	int previouslyHoveredHex; //number of hex that was hovered by the cursor a while ago
@@ -440,6 +440,8 @@ public:
 	void hexLclicked(int whichOne); //hex only call-in
 	void stackIsShooting(int ID, int dest); //called when stack with id ID is shooting to hex dest
 	void battleFinished(const BattleResult& br); //called when battle is finished - battleresult window should be printed
+	const BattleResult * bresult; //result of a battle; if non-zero then display when all animations end
+	void displayBattleFinished(); //displays battle result
 	void spellCast(SpellCast * sc); //called when a hero casts a spell
 	void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
 	void castThisSpell(int spellID); //called when player has chosen a spell from spellbook

+ 1 - 1
client/CPlayerInterface.cpp

@@ -1171,7 +1171,7 @@ void CPlayerInterface::battleStacksAttacked(std::set<BattleStackAttacked> & bsa)
 			if (stack != NULL)
 				battleInt->displayEffect(i->effect, stack->position);
 		}
-		SStackAttackedInfo to_put = {i->stackAttacked, i->damageAmount, i->killedAmount, LOCPLINT->curAction->stackNumber, LOCPLINT->curAction->actionType==7, i->killed()};
+		SStackAttackedInfo to_put = {i->stackAttacked, i->damageAmount, i->killedAmount, i->attackerID, LOCPLINT->curAction->actionType==7, i->killed()};
 		arg.push_back(to_put);
 	}
 

+ 2 - 2
lib/NetPacks.h

@@ -810,7 +810,7 @@ struct BattleStackAttacked : public CPackForClient//3005
 	void applyCl(CClient *cl);
 	DLL_EXPORT void applyGs(CGameState *gs);
 
-	ui32 stackAttacked;
+	ui32 stackAttacked, attackerID;
 	ui32 newAmount, newHP, killedAmount, damageAmount;
 	ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown;
 	ui32 effect; //set only if flag 2 is present
@@ -825,7 +825,7 @@ struct BattleStackAttacked : public CPackForClient//3005
 	}
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount & effect;
+		h & stackAttacked & attackerID & newAmount & newHP & flags & killedAmount & damageAmount & effect;
 	}
 	bool operator<(const BattleStackAttacked &b) const
 	{

+ 6 - 4
server/CGameHandler.cpp

@@ -533,7 +533,7 @@ askInterfaceForMove:
 	delete battleResult.data;
 }
 
-void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, CStack *def)
+void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, const CStack *def)
 {	
 	bsa.killedAmount = bsa.damageAmount / def->MaxHealth();
 	unsigned damageFirst = bsa.damageAmount % def->MaxHealth();
@@ -560,7 +560,7 @@ void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, CStack *def)
 	}
 }
 
-void CGameHandler::prepareAttack(BattleAttack &bat, CStack *att, CStack *def, int distance)
+void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CStack *def, int distance)
 {
 	bat.bsa.clear();
 	bat.stackAttacking = att->ID;
@@ -571,14 +571,15 @@ void CGameHandler::prepareAttack(BattleAttack &bat, CStack *att, CStack *def, in
 		BattleStackAttacked *bsa = &*i;
 	#endif
 
-		bsa->stackAttacked = def->ID;
+	bsa->stackAttacked = def->ID;
+	bsa->attackerID = att->ID;
 	bsa->damageAmount = BattleInfo::calculateDmg(att, def, gs->battleGetOwner(att->ID), gs->battleGetOwner(def->ID), bat.shot(), distance);//counting dealt damage
 	if(att->Luck() > 0  &&  rand()%24 < att->Luck())
 	{
 		bsa->damageAmount *= 2;
 		bat.flags |= 4;
 	}
-	prepareAttacked(*bsa,def);
+	prepareAttacked(*bsa, def);
 }
 void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 {
@@ -3030,6 +3031,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 						bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim;
 						bsa.damageAmount = calculateSpellDmg(s, h, *it);
 						bsa.stackAttacked = (*it)->ID;
+						bsa.attackerID = -1;
 						prepareAttacked(bsa,*it);
 						si.stacks.insert(bsa);
 					}

+ 2 - 2
server/CGameHandler.h

@@ -85,8 +85,8 @@ public:
 	void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
 	int moveStack(int stack, int dest); //returned value - travelled distance
 	void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
-	void prepareAttack(BattleAttack &bat, CStack *att, CStack *def, int distance); //distance - number of hexes travelled before attacking
-	void prepareAttacked(BattleStackAttacked &bsa, CStack *def);
+	void prepareAttack(BattleAttack &bat, const CStack *att, const CStack *def, int distance); //distance - number of hexes travelled before attacking
+	void prepareAttacked(BattleStackAttacked &bsa, const CStack *def);
 	void checkForBattleEnd( std::vector<CStack*> &stacks );
 	void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank, const CGTownInstance *town);