Browse Source

* Fixed #30
* Fixed several shooting animation bugs
* Improved XY position of double wide creatures

beegee1 14 years ago
parent
commit
7962a9bc47

+ 57 - 29
client/CBattleInterface.cpp

@@ -972,25 +972,37 @@ bool CShootingAnim::init()
 		return false;
 		return false;
 	}
 	}
 
 
-	//projectile
+	// Create the projectile animation
+	
 	float projectileAngle; //in radians; if positive, projectiles goes up
 	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)
 	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 = shooter->position;
 	int fromHex = shooter->position;
-	projectileAngle = atan2(float(abs(dest - fromHex)/BFIELD_WIDTH), float(abs(dest - fromHex)%BFIELD_WIDTH));
+	projectileAngle = atan2(float(abs(dest - fromHex) / BFIELD_WIDTH), float(abs(dest - fromHex) % BFIELD_WIDTH));
 	if(fromHex < dest)
 	if(fromHex < dest)
 		projectileAngle = -projectileAngle;
 		projectileAngle = -projectileAngle;
-
+	
+	// Get further info about the shooter e.g. relative pos of projectile to unit.
+	// If the creature id is 149 then it's a arrow tower which has no additional info so get the
+	// actual arrow tower shooter instead.
+	const CCreature *shooterInfo = shooter->getCreature();
+	if (shooterInfo->idNumber == 149)
+	{
+		int creID = CGI->creh->factionToTurretCreature[owner->siegeH->town->town->typeID];
+		shooterInfo = CGI->creh->creatures[creID];
+	}
+	
 	SProjectileInfo spi;
 	SProjectileInfo spi;
 	spi.creID = shooter->getCreature()->idNumber;
 	spi.creID = shooter->getCreature()->idNumber;
+	spi.stackID = shooter->ID;
 	spi.reverse = !shooter->attackerOwned;
 	spi.reverse = !shooter->attackerOwned;
 
 
 	spi.step = 0;
 	spi.step = 0;
 	spi.frameNum = 0;
 	spi.frameNum = 0;
-	if(vstd::contains(CGI->creh->idToProjectileSpin, spi.creID))
-		spi.spin = CGI->creh->idToProjectileSpin[spi.creID];
+	if(vstd::contains(CGI->creh->idToProjectileSpin, shooterInfo->idNumber))
+		spi.spin = CGI->creh->idToProjectileSpin[shooterInfo->idNumber];
 	else
 	else
 	{
 	{
-		tlog2 << "Warning - no projectile spin for spi.creID " << spi.creID << std::endl;
+		tlog2 << "Warning - no projectile spin for spi.creID " << shooterInfo->idNumber << std::endl;
 		spi.spin = false;
 		spi.spin = false;
 	}
 	}
 
 
@@ -1007,26 +1019,35 @@ bool CShootingAnim::init()
 	}
 	}
 	destcoord.x += 250; destcoord.y += 210; //TODO: find a better place to shoot
 	destcoord.x += 250; destcoord.y += 210; //TODO: find a better place to shoot
 
 
-	if(projectileAngle > straightAngle) //upper shot
+	// The "master" point where all projectile positions relate to.
+	static const Point projectileOrigin(181, 252);
+
+	// Calculate projectile start position. Offsets are read out of the CRANIM.TXT.
+	if (projectileAngle > straightAngle)
 	{
 	{
-		spi.x = xycoord.x + 200 + shooter->getCreature()->upperRightMissleOffsetX;
-		spi.y = xycoord.y + 100 - shooter->getCreature()->upperRightMissleOffsetY;
+		//upper shot
+		spi.x = xycoord.x + projectileOrigin.x + shooterInfo->upperRightMissleOffsetX;
+		spi.y = xycoord.y + projectileOrigin.y + shooterInfo->upperRightMissleOffsetY;
 	}
 	}
-	else if(projectileAngle < -straightAngle) //lower shot
+	else if (projectileAngle < -straightAngle) 
 	{
 	{
-		spi.x = xycoord.x + 200 + shooter->getCreature()->lowerRightMissleOffsetX;
-		spi.y = xycoord.y + 150 - shooter->getCreature()->lowerRightMissleOffsetY;
+		//lower shot
+		spi.x = xycoord.x + projectileOrigin.x + shooterInfo->lowerRightMissleOffsetX;
+		spi.y = xycoord.y + projectileOrigin.y + shooterInfo->lowerRightMissleOffsetY;
 	}
 	}
-	else //straight shot
+	else 
 	{
 	{
-		spi.x = xycoord.x + 200 + shooter->getCreature()->rightMissleOffsetX;
-		spi.y = xycoord.y + 125 - shooter->getCreature()->rightMissleOffsetY;
+		//straight shot
+		spi.x = xycoord.x + projectileOrigin.x + shooterInfo->rightMissleOffsetX;
+		spi.y = xycoord.y + projectileOrigin.y + shooterInfo->rightMissleOffsetY;
 	}
 	}
+	
 	spi.lastStep = sqrt((float)((destcoord.x - spi.x)*(destcoord.x - spi.x) + (destcoord.y - spi.y) * (destcoord.y - spi.y))) / 40;
 	spi.lastStep = sqrt((float)((destcoord.x - spi.x)*(destcoord.x - spi.x) + (destcoord.y - spi.y) * (destcoord.y - spi.y))) / 40;
 	if(spi.lastStep == 0)
 	if(spi.lastStep == 0)
 		spi.lastStep = 1;
 		spi.lastStep = 1;
 	spi.dx = (destcoord.x - spi.x) / spi.lastStep;
 	spi.dx = (destcoord.x - spi.x) / spi.lastStep;
 	spi.dy = (destcoord.y - spi.y) / spi.lastStep;
 	spi.dy = (destcoord.y - spi.y) / spi.lastStep;
+	
 	//set starting frame
 	//set starting frame
 	if(spi.spin)
 	if(spi.spin)
 	{
 	{
@@ -1036,8 +1057,9 @@ bool CShootingAnim::init()
 	{
 	{
 		spi.frameNum = ((M_PI/2.0f - projectileAngle) / (2.0f *M_PI) + 1/((float)(2*(owner->idToProjectile[spi.creID]->ourImages.size()-1)))) * (owner->idToProjectile[spi.creID]->ourImages.size()-1);
 		spi.frameNum = ((M_PI/2.0f - projectileAngle) / (2.0f *M_PI) + 1/((float)(2*(owner->idToProjectile[spi.creID]->ourImages.size()-1)))) * (owner->idToProjectile[spi.creID]->ourImages.size()-1);
 	}
 	}
-	//set delay
-	spi.animStartDelay = CGI->creh->creatures[spi.creID]->attackClimaxFrame;
+
+	// Set projectile animation start delay which is specified in frames
+	spi.animStartDelay = shooterInfo->attackClimaxFrame;
 	owner->projectiles.push_back(spi);
 	owner->projectiles.push_back(spi);
 
 
 	//attack animation
 	//attack animation
@@ -1545,7 +1567,7 @@ void CBattleInterface::show(SDL_Surface * to)
 			//print shade
 			//print shade
 			if(spellToCast) //when casting spell
 			if(spellToCast) //when casting spell
 			{
 			{
-				//calculating spell schoold level
+				//calculating spell school level
 				const CSpell & spToCast =  *CGI->spellh->spells[spellToCast->additionalInfo];
 				const CSpell & spToCast =  *CGI->spellh->spells[spellToCast->additionalInfo];
 				ui8 schoolLevel = 0;
 				ui8 schoolLevel = 0;
 				if( activeStack->attackerOwned )
 				if( activeStack->attackerOwned )
@@ -1600,7 +1622,7 @@ void CBattleInterface::show(SDL_Surface * to)
 	//double loop because dead stacks should be printed first
 	//double loop because dead stacks should be printed first
 	BOOST_FOREACH(const CStack *s, stacks)
 	BOOST_FOREACH(const CStack *s, stacks)
 	{
 	{
-		if(creAnims.find(s->ID) == creAnims.end()) //eg. for summoned but not yet handled stacks
+		if(creAnims.find(s->ID) == creAnims.end()) //e.g. for summoned but not yet handled stacks
 			continue;
 			continue;
 		if(creAnims[s->ID]->getType() != 5 && s->position >= 0) //don't show turrets here
 		if(creAnims[s->ID]->getType() != 5 && s->position >= 0) //don't show turrets here
 			stackAliveByHex[s->position].push_back(s);
 			stackAliveByHex[s->position].push_back(s);
@@ -1608,7 +1630,7 @@ void CBattleInterface::show(SDL_Surface * to)
 	std::vector<const CStack *> stackDeadByHex[BFIELD_SIZE];
 	std::vector<const CStack *> stackDeadByHex[BFIELD_SIZE];
 	BOOST_FOREACH(const CStack *s, stacks)
 	BOOST_FOREACH(const CStack *s, stacks)
 	{
 	{
-		if(creAnims.find(s->ID) == creAnims.end()) //eg. for summoned but not yet handled stacks
+		if(creAnims.find(s->ID) == creAnims.end()) //e.g. for summoned but not yet handled stacks
 			continue;
 			continue;
 		if(creAnims[s->ID]->getType() == 5)
 		if(creAnims[s->ID]->getType() == 5)
 			stackDeadByHex[s->position].push_back(s);
 			stackDeadByHex[s->position].push_back(s);
@@ -1752,7 +1774,8 @@ void CBattleInterface::show(SDL_Surface * to)
 
 
 	//units shown
 	//units shown
 
 
-	projectileShowHelper(to);//showing projectiles
+	// Show projectiles
+	projectileShowHelper(to);
 
 
 	//showing spell effects
 	//showing spell effects
 	if(battleEffects.size())
 	if(battleEffects.size())
@@ -2381,7 +2404,7 @@ void CBattleInterface::newStack(const CStack * stack)
 		const CCreature & turretCreature = *CGI->creh->creatures[ CGI->creh->factionToTurretCreature[siegeH->town->town->typeID] ];
 		const CCreature & turretCreature = *CGI->creh->creatures[ CGI->creh->factionToTurretCreature[siegeH->town->town->typeID] ];
 		creAnims[stack->ID] = new CCreatureAnimation(turretCreature.animDefName);	
 		creAnims[stack->ID] = new CCreatureAnimation(turretCreature.animDefName);	
 
 
-		// Remarks: Turret positions are read out of the /config/wall_pos.txt
+		// Turret positions are read out of the /config/wall_pos.txt
 		int posID = 0;
 		int posID = 0;
 		switch (stack->position)
 		switch (stack->position)
 		{
 		{
@@ -3523,11 +3546,15 @@ void CBattleInterface::projectileShowHelper(SDL_Surface * to)
 	std::list< std::list<SProjectileInfo>::iterator > toBeDeleted;
 	std::list< std::list<SProjectileInfo>::iterator > toBeDeleted;
 	for(std::list<SProjectileInfo>::iterator it=projectiles.begin(); it!=projectiles.end(); ++it)
 	for(std::list<SProjectileInfo>::iterator it=projectiles.begin(); it!=projectiles.end(); ++it)
 	{
 	{
-		if(it->animStartDelay>0)
-		{
-			--(it->animStartDelay);
-			continue;
-		}
+		// Creature have to be in a shooting anim and the anim start delay must be over.
+		// Otherwise abort to start moving the projectile.
+		if (it->animStartDelay > 0)
+			if(it->animStartDelay == creAnims[it->stackID]->getAnimationFrame() + 1
+					&& creAnims[it->stackID]->getType() >= 14 && creAnims[it->stackID]->getType() <= 16)
+				it->animStartDelay = 0;
+			else
+				continue;
+
 		SDL_Rect dst;
 		SDL_Rect dst;
 		dst.h = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap->h;
 		dst.h = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap->h;
 		dst.w = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap->w;
 		dst.w = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap->w;
@@ -3543,6 +3570,7 @@ void CBattleInterface::projectileShowHelper(SDL_Surface * to)
 		{
 		{
 			CSDL_Ext::blit8bppAlphaTo24bpp(idToProjectile[it->creID]->ourImages[it->frameNum].bitmap, NULL, to, &dst);
 			CSDL_Ext::blit8bppAlphaTo24bpp(idToProjectile[it->creID]->ourImages[it->frameNum].bitmap, NULL, to, &dst);
 		}
 		}
+
 		//actualizing projectile
 		//actualizing projectile
 		++it->step;
 		++it->step;
 		if(it->step == it->lastStep)
 		if(it->step == it->lastStep)
@@ -3941,11 +3969,11 @@ Point CBattleHex::getXYUnitAnim(const int & hexNum, const bool & attacker, const
 		{
 		{
 			if(attacker)
 			if(attacker)
 			{
 			{
-				ret.x -= 42;
+				ret.x -= 44;
 			}
 			}
 			else
 			else
 			{
 			{
-				ret.x += 42;
+				ret.x += 45;
 			}
 			}
 		}
 		}
 	}
 	}

+ 1 - 0
client/CBattleInterface.h

@@ -53,6 +53,7 @@ struct SProjectileInfo
 	int dx, dy; //change in position in one step
 	int dx, dy; //change in position in one step
 	int step, lastStep; //to know when finish showing this projectile
 	int step, lastStep; //to know when finish showing this projectile
 	int creID; //ID of creature that shot this projectile
 	int creID; //ID of creature that shot this projectile
+	int stackID; //ID of stack
 	int frameNum; //frame to display form projectile animation
 	int frameNum; //frame to display form projectile animation
 	bool spin; //if true, frameNum will be increased
 	bool spin; //if true, frameNum will be increased
 	int animStartDelay; //how many times projectile must be attempted to be shown till it's really show (decremented after hit)
 	int animStartDelay; //how many times projectile must be attempted to be shown till it's really show (decremented after hit)

+ 5 - 0
client/CCreatureAnimation.cpp

@@ -133,6 +133,11 @@ int CCreatureAnimation::getFrame() const
 	return curFrame;
 	return curFrame;
 }
 }
 
 
+int CCreatureAnimation::getAnimationFrame() const
+{
+	return internalFrame;
+}
+
 bool CCreatureAnimation::onFirstFrameInGroup()
 bool CCreatureAnimation::onFirstFrameInGroup()
 {
 {
 	return internalFrame == 0;
 	return internalFrame == 0;

+ 2 - 1
client/CCreatureAnimation.h

@@ -84,7 +84,8 @@ public:
 
 
 	int nextFrame(SDL_Surface * dest, int x, int y, bool attacker, unsigned char animCount, bool incrementFrame = true, bool yellowBorder = false, bool blueBorder = false, SDL_Rect * destRect = NULL); //0 - success, any other - error //print next 
 	int nextFrame(SDL_Surface * dest, int x, int y, bool attacker, unsigned char animCount, bool incrementFrame = true, bool yellowBorder = false, bool blueBorder = false, SDL_Rect * destRect = NULL); //0 - success, any other - error //print next 
 	void incrementFrame();
 	void incrementFrame();
-	int getFrame() const;
+	int getFrame() const; // Gets the current frame ID relative to DEF file.
+	int getAnimationFrame() const; // Gets the current frame ID relative to frame group.
 	bool onFirstFrameInGroup();
 	bool onFirstFrameInGroup();
 	bool onLastFrameInGroup();
 	bool onLastFrameInGroup();
 
 

+ 13 - 13
config/cr_shots.txt

@@ -1,40 +1,40 @@
 //here are defs with things shot by different units - don't delete this line; format: unit_ID def_name spin_projectile
 //here are defs with things shot by different units - don't delete this line; format: unit_ID def_name spin_projectile
 2 PLCBOWX.DEF 0
 2 PLCBOWX.DEF 0
 3 PLCBOWX.DEF 0
 3 PLCBOWX.DEF 0
-8 CPRZEAX.DEF 1
-9 CPRZEAX.DEF 1
+8 CPRZEAX.DEF 0
+9 CPRZEAX.DEF 0
 18 PELFX.DEF 0
 18 PELFX.DEF 0
 19 PELFX.DEF 0
 19 PELFX.DEF 0
-29 CPRGRE.DEF 1
-34 PMAGEX.DEF 1
-35 PMAGEX.DEF 1
+29 CPRGRE.DEF 0
+34 PMAGEX.DEF 0
+35 PMAGEX.DEF 0
 41 CPRGTIX.DEF 0
 41 CPRGTIX.DEF 0
-44 CPRGOGX.DEF 1
-45 CPRGOGX.DEF 1
+44 CPRGOGX.DEF 0
+45 CPRGOGX.DEF 0
 64 PLICH.DEF 0
 64 PLICH.DEF 0
 65 PLICH.DEF 0
 65 PLICH.DEF 0
 74 SMBALX.DEF 0
 74 SMBALX.DEF 0
 75 SMBALX.DEF 0
 75 SMBALX.DEF 0
 76 PMEDUSX.DEF 0
 76 PMEDUSX.DEF 0
 77 PMEDUSX.DEF 0
 77 PMEDUSX.DEF 0
-88 PORCHX.DEF 1
-89 PORCHX.DEF 1
-94 PCYCLBX.DEF 1
-95 PCYCLBX.DEF 1
+88 PORCHX.DEF 0
+89 PORCHX.DEF 0
+94 PCYCLBX.DEF 0
+95 PCYCLBX.DEF 0
 100 PPLIZAX.DEF 0
 100 PPLIZAX.DEF 0
 101 PPLIZAX.DEF 0
 101 PPLIZAX.DEF 0
 123 PICEE.DEF 0
 123 PICEE.DEF 0
 127 CPRGTIX.DEF 0
 127 CPRGTIX.DEF 0
 136 SMBALX.DEF 0
 136 SMBALX.DEF 0
 137 PELFX.DEF 0
 137 PELFX.DEF 0
-138 PHALF.DEF 1
+138 PHALF.DEF 0
 145 SMCATX.DEF 1
 145 SMCATX.DEF 1
 146 SMBALX.DEF 0
 146 SMBALX.DEF 0
 152 CPRGTIX.DEF 0
 152 CPRGTIX.DEF 0
 169 CPRZEAX.DEF 0
 169 CPRZEAX.DEF 0
 170 PLCBOWX.DEF 0
 170 PLCBOWX.DEF 0
 171 PLCBOWX.DEF 0
 171 PLCBOWX.DEF 0
-173 CPRGRE.DEF 1
+173 CPRGRE.DEF 0
 193 SMBALX.DEF 0
 193 SMBALX.DEF 0
 196 SMBALX.DEF 0
 196 SMBALX.DEF 0
 -1
 -1