Pārlūkot izejas kodu

* many fixes and improvements for battles

mateuszb 16 gadi atpakaļ
vecāks
revīzija
8799eddcdc
3 mainītis faili ar 72 papildinājumiem un 72 dzēšanām
  1. 66 71
      client/CBattleInterface.cpp
  2. 4 1
      client/CBattleInterface.h
  3. 2 0
      client/CCreatureAnimation.cpp

+ 66 - 71
client/CBattleInterface.cpp

@@ -119,6 +119,45 @@ CBattleStackAnimation::CBattleStackAnimation(CBattleInterface * _owner, int stac
 {
 }
 
+bool CBattleStackAnimation::isToReverseHlp(int hexFrom, int hexTo, bool curDir)
+{
+	int fromMod = hexFrom % BFIELD_WIDTH;
+	int fromDiv = hexFrom / BFIELD_WIDTH;
+	int toMod = hexTo % BFIELD_WIDTH;
+
+	if(curDir && fromMod < toMod)
+		return false;
+	else if(curDir && fromMod > toMod)
+		return true;
+	else if(curDir && fromMod == toMod)
+	{
+		return fromDiv % 2 == 0;
+	}
+	else if(!curDir && fromMod < toMod)
+		return true;
+	else if(!curDir && fromMod > toMod)
+		return false;
+	else if(!curDir && fromMod == toMod)
+	{
+		return fromDiv % 2 == 1;
+	}
+	tlog1 << "Catastrope in CBattleStackAnimation::isToReverse!" << std::endl;
+	return false; //should never happen
+}
+
+bool CBattleStackAnimation::isToReverse(int hexFrom, int hexTo, bool curDir, bool toDoubleWide, bool toDir)
+{
+	if(toDoubleWide)
+	{
+		return isToReverseHlp(hexFrom, hexTo, curDir) &&
+			(toDir ? isToReverseHlp(hexFrom, hexTo-1, curDir) : isToReverseHlp(hexFrom, hexTo+1, curDir) );
+	}
+	else
+	{
+		return isToReverseHlp(hexFrom, hexTo, curDir);
+	}
+}
+
 //revering animation
 
 bool CReverseAnim::init()
@@ -215,7 +254,9 @@ bool CDefenceAnim::init()
 	{
 		if(dynamic_cast<CDefenceAnim *>(it->first))
 			continue;
-		if(dynamic_cast<CBattleAttack *>(it->first))
+
+		CBattleAttack * attAnim = dynamic_cast<CBattleAttack *>(it->first);
+		if(attAnim && attAnim->stackID != stackID)
 			continue;
 
 		const CStack * attacker = LOCPLINT->cb->battleGetStackByID(IDby, false);
@@ -239,19 +280,13 @@ bool CDefenceAnim::init()
 	const CStack * attacked = LOCPLINT->cb->battleGetStackByID(stackID, false);
 
 	//reverse unit if necessary
-	if((attacked->position > attacker->position) && owner->creDir[stackID] == true)
-	{
-		owner->pendingAnims.push_back(std::make_pair(new CReverseAnim(owner, stackID, attacked->position, true), false));
-		return false;
-	}
-	else if ((attacked->position < attacker->position) && owner->creDir[stackID] == false)
+	if(isToReverse(attacked->position, attacker->position, owner->creDir[stackID], attacker->hasFeatureOfType(StackFeature::DOUBLE_WIDE), owner->creDir[IDby]))
 	{
 		owner->pendingAnims.push_back(std::make_pair(new CReverseAnim(owner, stackID, attacked->position, true), false));
 		return false;
 	}
 	//unit reversed
 
-
 	if(byShooting) //delay hit animation
 	{		
 		for(std::list<SProjectileInfo>::const_iterator it = owner->projectiles.begin(); it != owner->projectiles.end(); ++it)
@@ -283,6 +318,11 @@ bool CDefenceAnim::init()
 
 void CDefenceAnim::nextFrame()
 {
+	if(!killed && owner->creAnims[stackID]->getType() != 3)
+	{
+		owner->creAnims[stackID]->setType(3);
+	}
+
 	if(!owner->creAnims[stackID]->onLastFrameInGroup())
 	{
 		if( owner->creAnims[stackID]->getType() == 5 && (owner->animCount+1)%(4/CBattleInterface::settings.animSpeed)==0
@@ -623,9 +663,10 @@ bool CBattleAttack::checkInitialConditions()
 	return isEarliest(false);
 }
 
-CBattleAttack::CBattleAttack(CBattleInterface * _owner, int _stackID)
-: CBattleStackAnimation(_owner, _stackID), sh(-1)
+CBattleAttack::CBattleAttack(CBattleInterface * _owner, int _stackID, int _dest)
+: CBattleStackAnimation(_owner, _stackID), sh(-1), dest(_dest)
 {
+	attackedStack = LOCPLINT->cb->battleGetStackByPos(_dest, false);
 }
 
 ////melee attack
@@ -652,77 +693,33 @@ bool CMeleeAttack::init()
 	}
 
 	int reversedShift = 0; //shift of attacking stack's position due to reversing
-
-	//reversing stack if necessary
-	bool reverse = false;
 	if(aStack->attackerOwned)
 	{
-		if(aStack->hasFeatureOfType(StackFeature::DOUBLE_WIDE))
+		if(aStack->hasFeatureOfType(StackFeature::DOUBLE_WIDE) && BattleInfo::mutualPosition(aStack->position, dest) == -1)
 		{
-			switch(BattleInfo::mutualPosition(aStack->position, dest)) //attack direction
+			if(BattleInfo::mutualPosition(aStack->position + (aStack->attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
 			{
-			case 5:
-				reverse = true;
-				break;
-			case -1:
-				if(BattleInfo::mutualPosition(aStack->position + (aStack->attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
-				{
-					reverse = true;
-					reversedShift = (aStack->attackerOwned ? -1 : 1);
-				}
-				break;
-			}
-		}
-		else //else for if(astack->hasFeatureOfType(StackFeature::DOUBLE_WIDE))
-		{
-			switch(BattleInfo::mutualPosition(aStack->position, dest)) //attack direction
-			{
-			case 0: case 4: case 5:
-				{
-					reverse = true;
-					break;
-				}
+				reversedShift = (aStack->attackerOwned ? -1 : 1);
 			}
 		}
 	}
 	else //if(astack->attackerOwned)
 	{
-		if(aStack->hasFeatureOfType(StackFeature::DOUBLE_WIDE))
+		if(aStack->hasFeatureOfType(StackFeature::DOUBLE_WIDE) && BattleInfo::mutualPosition(aStack->position, dest) == -1)
 		{
-			switch(BattleInfo::mutualPosition(aStack->position, dest)) //attack direction
+			if(BattleInfo::mutualPosition(aStack->position + (aStack->attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
 			{
-			case 2:
-				{
-					reverse = true;
-					break;
-				}
-			case -1:
-				{
-					if(BattleInfo::mutualPosition(aStack->position + (aStack->attackerOwned ? -1 : 1), dest) >= 0) //if reversing stack will make its position adjacent to dest
-					{
-						reverse = true;
-						reversedShift = (aStack->attackerOwned ? -1 : 1);
-					}
-					break;
-				}
+				reversedShift = (aStack->attackerOwned ? -1 : 1);
 			}
 		}
-		else //else for if(astack->hasFeatureOfType(StackFeature::DOUBLE_WIDE))
-		{
-			switch(BattleInfo::mutualPosition(aStack->position, dest)) //attack direction
-			{
-			case 1: case 2: case 3:
-				{
-					reverse = true;
-					break;
-				}
-			}
 
-		}
 	}
-	if( reverse && owner->creDir[stackID] == bool(aStack->attackerOwned) )
+
+	//reversing stack if necessary
+	if(isToReverse(aStack->position, dest, owner->creDir[stackID], attackedStack->hasFeatureOfType(StackFeature::DOUBLE_WIDE), owner->creDir[attackedStack->ID]))
 	{
 		owner->pendingAnims.push_back(std::make_pair(new CReverseAnim(owner, stackID, aStack->position, true), false));
+		return false;
 	}
 	//reversed
 
@@ -766,9 +763,8 @@ void CMeleeAttack::endAnim()
 }
 
 CMeleeAttack::CMeleeAttack(CBattleInterface * _owner, int attacker, int _dest)
-: CBattleAttack(_owner, attacker)
+: CBattleAttack(_owner, attacker, _dest)
 {
-	dest = _dest;
 }
 
 //shooting anim
@@ -789,7 +785,7 @@ bool CShootingAnim::init()
 	//projectile
 	float projectileAngle; //in radians; if positive, projectiles goes up
 	float straightAngle = 0.2f; //maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value)
-	int fromHex = LOCPLINT->cb->battleGetPos(stackID);
+	int fromHex = shooter->position;
 	projectileAngle = atan2(float(abs(dest - fromHex)/BFIELD_WIDTH), float(abs(dest - fromHex)%BFIELD_WIDTH));
 	if(fromHex < dest)
 		projectileAngle = -projectileAngle;
@@ -803,7 +799,7 @@ bool CShootingAnim::init()
 	spi.spin = CGI->creh->idToProjectileSpin[spi.creID];
 
 	std::pair<int, int> xycoord = CBattleHex::getXYUnitAnim(shooter->position, true, shooter, owner);
-	std::pair<int, int> destcoord = CBattleHex::getXYUnitAnim(dest, false, LOCPLINT->cb->battleGetStackByPos(dest, false), owner); 
+	std::pair<int, int> destcoord = CBattleHex::getXYUnitAnim(dest, false, attackedStack, owner); 
 	destcoord.first += 250; destcoord.second += 210; //TODO: find a better place to shoot
 
 	if(projectileAngle > straightAngle) //upper shot
@@ -840,7 +836,7 @@ bool CShootingAnim::init()
 	owner->projectiles.push_back(spi);
 
 	//attack aniamtion
-	IDby = LOCPLINT->cb->battleGetStackByPos(dest, false)->ID;
+	IDby = attackedStack->ID;
 	posShiftDueToDist = 0;
 	shooting = true;
 
@@ -875,9 +871,8 @@ void CShootingAnim::endAnim()
 }
 
 CShootingAnim::CShootingAnim(CBattleInterface * _owner, int attacker, int _dest)
-: CBattleAttack(_owner, attacker)
+: CBattleAttack(_owner, attacker, _dest)
 {
-	dest = _dest;
 }
 
 ////////////////////////

+ 4 - 1
client/CBattleInterface.h

@@ -78,6 +78,8 @@ public:
 	int stackID; //id of stack whose animation it is
 
 	CBattleStackAnimation(CBattleInterface * _owner, int stack);
+	static bool isToReverseHlp(int hexFrom, int hexTo, bool curDir); //helper for isToReverse
+	static bool isToReverse(int hexFrom, int hexTo, bool curDir /*if true, creature is in attacker's direction*/, bool toDoubleWide, bool toDir); //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
 };
 
 class CReverseAnim : public CBattleStackAnimation
@@ -161,12 +163,13 @@ protected:
 	bool shooting;
 	int group; //if shooting is true, print this animation group
 	int sh;			   // temporary sound handler
+	const CStack * attackedStack;
 public:
 	void nextFrame();
 
 	bool checkInitialConditions();
 
-	CBattleAttack(CBattleInterface * _owner, int _stackID);
+	CBattleAttack(CBattleInterface * _owner, int _stackID, int _dest);
 };
 
 class CMeleeAttack : public CBattleAttack

+ 2 - 0
client/CCreatureAnimation.cpp

@@ -1,6 +1,7 @@
 #include "CCreatureAnimation.h"
 #include "../hch/CLodHandler.h"
 #include "../lib/VCMI_Lib.h"
+#include <assert.h>
 
 /*
  * CCreatureAnimation.cpp, part of VCMI engine
@@ -19,6 +20,7 @@ int CCreatureAnimation::getType() const
 
 void CCreatureAnimation::setType(int type)
 {
+	assert(framesInGroup(type) > 0 && "Bad type for void CCreatureAnimation::setType(int type)!");
 	this->type = type;
 	internalFrame = 0;
 	if(type!=-1)