Jelajahi Sumber

Fixing sieges, part 1

Ivan Savenko 2 tahun lalu
induk
melakukan
35576834c9

+ 40 - 23
client/battle/CBattleAnimations.cpp

@@ -134,9 +134,9 @@ void CAttackAnimation::nextFrame()
 	if(!soundPlayed)
 	{
 		if(shooting)
-			CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), shoot));
+			CCS->soundh->playSound(battle_sound(getCreature(), shoot));
 		else
-			CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), attack));
+			CCS->soundh->playSound(battle_sound(getCreature(), attack));
 		soundPlayed = true;
 	}
 	CBattleAnimation::nextFrame();
@@ -164,6 +164,14 @@ bool CAttackAnimation::checkInitialConditions()
 	return isEarliest(false);
 }
 
+const CCreature * CAttackAnimation::getCreature()
+{
+	if (attackingStack->getCreature()->idNumber == CreatureID::ARROW_TOWERS)
+		return owner->siegeController->getTurretCreature();
+	else
+		return attackingStack->getCreature();
+}
+
 CAttackAnimation::CAttackAnimation(CBattleInterface *_owner, const CStack *attacker, BattleHex _dest, const CStack *defender)
 	: CBattleStackAnimation(_owner, attacker),
 		shooting(false), group(CCreatureAnim::SHOOT_FRONT),
@@ -767,7 +775,7 @@ void CShootingAnimation::setAnimationGroup()
 	//maximal angle in radians between straight horizontal line and shooting line for which shot is considered to be straight (absoulte value)
 	static const double straightAngle = 0.2;
 
-	double projectileAngle = atan2(shotTarget.y - shooterPos.y, std::abs(shotTarget.x - shooterPos.x));
+	double projectileAngle = -atan2(shotTarget.y - shooterPos.y, std::abs(shotTarget.x - shooterPos.x));
 
 	// Calculate projectile start position. Offsets are read out of the CRANIM.TXT.
 	if (projectileAngle > straightAngle)
@@ -780,11 +788,7 @@ void CShootingAnimation::setAnimationGroup()
 
 void CShootingAnimation::initializeProjectile()
 {
-	const CCreature *shooterInfo = attackingStack->getCreature();
-
-	if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS)
-		shooterInfo = owner->siegeController->getTurretCreature();
-
+	const CCreature *shooterInfo = getCreature();
 	Point shotTarget = owner->stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225);
 	Point shotOrigin = stackAnimation(attackingStack)->pos.topLeft() + Point(222, 265);
 	int multiplier = stackFacingRight(attackingStack) ? 1 : -1;
@@ -828,12 +832,25 @@ void CShootingAnimation::nextFrame()
 			return;
 	}
 
+	// animation should be paused if there is an active projectile
+	if (projectileEmitted)
+	{
+		if (owner->projectilesController->hasActiveProjectile(attackingStack))
+		{
+			stackAnimation(attackingStack)->pause();
+			return;
+		}
+		else
+			stackAnimation(attackingStack)->play();
+	}
+
+	CAttackAnimation::nextFrame();
+
 	if (!projectileEmitted)
 	{
-		const CCreature *shooterInfo = attackingStack->getCreature();
+		const CCreature *shooterInfo = getCreature();
 
-		if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS)
-			shooterInfo = owner->siegeController->getTurretCreature();
+		assert(stackAnimation(attackingStack)->isShooting());
 
 		// emit projectile once animation playback reached "climax" frame
 		if ( stackAnimation(attackingStack)->getCurrentFrame() >= shooterInfo->animation.attackClimaxFrame )
@@ -842,17 +859,13 @@ void CShootingAnimation::nextFrame()
 			return;
 		}
 	}
-
-	// animation should be paused if there is an active projectile
-	if (projectileEmitted && owner->projectilesController->hasActiveProjectile(attackingStack))
-		return;
-
-
-	CAttackAnimation::nextFrame();
 }
 
 void CShootingAnimation::endAnim()
 {
+	assert(!owner->projectilesController->hasActiveProjectile(attackingStack));
+	assert(projectileEmitted);
+
 	// FIXME: is this possible? Animation is over but we're yet to fire projectile?
 	if (!projectileEmitted)
 	{
@@ -1157,11 +1170,15 @@ void CEffectAnimation::endAnim()
 {
 	CBattleAnimation::endAnim();
 
-	boost::range::remove_if(owner->effectsController->battleEffects,
-		[&](const BattleEffect & elem)
-		{
-			return elem.effectID == ID;
-		});
+	auto & effects = owner->effectsController->battleEffects;
+
+	for ( auto it = effects.begin(); it != effects.end(); )
+	{
+		if (it->effectID == ID)
+			it = effects.erase(it);
+		else
+			it++;
+	}
 
 	delete this;
 }

+ 2 - 0
client/battle/CBattleAnimations.h

@@ -73,6 +73,8 @@ protected:
 	const CStack *attackedStack;
 	const CStack *attackingStack;
 	int attackingStackPosBeforeReturn; //for stacks with return_after_strike feature
+
+	const CCreature * getCreature();
 public:
 	void nextFrame() override;
 	void endAnim() override;

+ 3 - 1
client/battle/CBattleFieldController.cpp

@@ -106,7 +106,9 @@ void CBattleFieldController::redrawBackgroundWithHexes()
 
 	//prepare background graphic with hexes and shaded hexes
 	backgroundWithHexes->draw(background, Point(0,0));
-	owner->obstacleController->redrawBackgroundWithHexes(backgroundWithHexes);
+	owner->obstacleController->showAbsoluteObstacles(backgroundWithHexes, Point(0,0));
+	if ( owner->siegeController )
+		owner->siegeController->showAbsoluteObstacles(backgroundWithHexes, Point(0,0));
 
 	if (settings["battle"]["stackRange"].Bool())
 	{

+ 2 - 2
client/battle/CBattleInterface.cpp

@@ -927,9 +927,9 @@ void CBattleInterface::show(SDL_Surface *to)
 	else
 	{
 		fieldController->showBackgroundImage(canvas);
-		obstacleController->showAbsoluteObstacles(canvas);
+		obstacleController->showAbsoluteObstacles(canvas, pos.topLeft());
 		if ( siegeController )
-			siegeController->showAbsoluteObstacles(canvas);
+			siegeController->showAbsoluteObstacles(canvas, pos.topLeft());
 	}
 	fieldController->showHighlightedHexes(canvas);
 

+ 2 - 16
client/battle/CBattleObstacleController.cpp

@@ -109,7 +109,7 @@ void CBattleObstacleController::obstaclePlaced(const CObstacleInstance & oi)
 	//CCS->soundh->playSound(sound);
 }
 
-void CBattleObstacleController::showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas)
+void CBattleObstacleController::showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas, const Point & offset)
 {
 	//Blit absolute obstacles
 	for(auto & oi : owner->curInt->cb->battleGetAllObstacles())
@@ -118,7 +118,7 @@ void CBattleObstacleController::showAbsoluteObstacles(std::shared_ptr<CCanvas> c
 		{
 			auto img = getObstacleImage(*oi);
 			if(img)
-				canvas->draw(img, Point(owner->pos.x + oi->getInfo().width, owner->pos.y + oi->getInfo().height));
+				canvas->draw(img, Point(offset.x + oi->getInfo().width, offset.y + oi->getInfo().height));
 		}
 	}
 }
@@ -196,17 +196,3 @@ Point CBattleObstacleController::getObstaclePosition(std::shared_ptr<IImage> ima
 
 	return r.topLeft();
 }
-
-void CBattleObstacleController::redrawBackgroundWithHexes(std::shared_ptr<CCanvas> to)
-{
-	//draw absolute obstacles (cliffs and so on)
-	for(auto & oi : owner->curInt->cb->battleGetAllObstacles())
-	{
-		if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
-		{
-			auto img = getObstacleImage(*oi);
-			if(img)
-				to->draw(img, Point(oi->getInfo().width, oi->getInfo().height));
-		}
-	}
-}

+ 1 - 3
client/battle/CBattleObstacleController.h

@@ -35,9 +35,7 @@ public:
 
 	void obstaclePlaced(const CObstacleInstance & oi);
 	void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance>> &obstacles);
-	void showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas);
+	void showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas, const Point & offset);
 
 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location );
-
-	void redrawBackgroundWithHexes(std::shared_ptr<CCanvas> to);
 };

+ 12 - 10
client/battle/CBattleProjectileController.cpp

@@ -246,7 +246,7 @@ bool CBattleProjectileController::hasActiveProjectile(const CStack * stack)
 
 void CBattleProjectileController::createProjectile(const CStack * shooter, const CStack * target, Point from, Point dest)
 {
-	const CCreature *shooterInfo = shooter->getCreature();
+	const CCreature *shooterInfo = getShooter(shooter);
 
 	std::shared_ptr<ProjectileBase> projectile;
 
@@ -262,8 +262,8 @@ void CBattleProjectileController::createProjectile(const CStack * shooter, const
 		catapultProjectile->step = 0;
 		catapultProjectile->steps = 0;
 
-		double animSpeed = AnimationControls::getProjectileSpeed() / 10;
-		catapultProjectile->steps = std::round(std::abs((dest.x - from.x) / animSpeed));
+		//double animSpeed = AnimationControls::getProjectileSpeed() / 10;
+		//catapultProjectile->steps = std::round(std::abs((dest.x - from.x) / animSpeed));
 	}
 	else
 	{
@@ -312,15 +312,17 @@ void CBattleProjectileController::createProjectile(const CStack * shooter, const
 			}
 			missileProjectile->frameNum = bestID;
 		}
+	}
 
-		double animSpeed = AnimationControls::getProjectileSpeed(); // flight speed of projectile
-		double distanceSquared = (dest.x - from.x) * (dest.x - from.x) + (dest.y - from.y) * (dest.y - from.y);
-		double distance = sqrt(distanceSquared);
-		projectile->steps = std::round(distance / animSpeed);
-		if(projectile->steps == 0)
-			projectile->steps = 1;
+	double animSpeed = AnimationControls::getProjectileSpeed(); // flight speed of projectile
+	if (!target)
+		animSpeed *= 0.2; // catapult attack needs slower speed
 
-	}
+	double distanceSquared = (dest.x - from.x) * (dest.x - from.x) + (dest.y - from.y) * (dest.y - from.y);
+	double distance = sqrt(distanceSquared);
+	projectile->steps = std::round(distance / animSpeed);
+	if(projectile->steps == 0)
+		projectile->steps = 1;
 
 	projectile->from     = from;
 	projectile->dest     = dest;

+ 8 - 7
client/battle/CBattleSiegeController.cpp

@@ -104,12 +104,13 @@ std::string CBattleSiegeController::getWallPieceImageName(EWallVisual::EWallVisu
 	}
 }
 
-void CBattleSiegeController::showWallPiece(std::shared_ptr<CCanvas> canvas, EWallVisual::EWallVisual what)
+void CBattleSiegeController::showWallPiece(std::shared_ptr<CCanvas> canvas, EWallVisual::EWallVisual what, const Point & offset)
 {
 	auto & ci = town->town->clientInfo;
 	auto const & pos = ci.siegePositions[what];
 
-	canvas->draw(wallPieceImages[what], owner->pos.topLeft() + Point(pos.x, pos.y));
+	if ( wallPieceImages[what])
+		canvas->draw(wallPieceImages[what], offset + Point(pos.x, pos.y));
 }
 
 std::string CBattleSiegeController::getBattleBackgroundName() const
@@ -250,13 +251,13 @@ void CBattleSiegeController::gateStateChanged(const EGateState state)
 		CCS->soundh->playSound(soundBase::DRAWBRG);
 }
 
-void CBattleSiegeController::showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas)
+void CBattleSiegeController::showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas, const Point & offset)
 {
 	if (getWallPieceExistance(EWallVisual::MOAT))
-		showWallPiece(canvas, EWallVisual::MOAT);
+		showWallPiece(canvas, EWallVisual::MOAT, owner->pos.topLeft());
 
 	if (getWallPieceExistance(EWallVisual::BACKGROUND_MOAT))
-		showWallPiece(canvas, EWallVisual::BACKGROUND_MOAT);
+		showWallPiece(canvas, EWallVisual::BACKGROUND_MOAT, owner->pos.topLeft());
 }
 
 void CBattleSiegeController::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location )
@@ -275,7 +276,7 @@ void CBattleSiegeController::showBattlefieldObjects(std::shared_ptr<CCanvas> can
 			wallPiece != EWallVisual::BOTTOM_BATTLEMENT &&
 			wallPiece != EWallVisual::UPPER_BATTLEMENT)
 		{
-			showWallPiece(canvas, wallPiece);
+			showWallPiece(canvas, wallPiece, owner->pos.topLeft());
 			continue;
 		}
 
@@ -308,7 +309,7 @@ void CBattleSiegeController::showBattlefieldObjects(std::shared_ptr<CCanvas> can
 		if (turret)
 		{
 			owner->stacksController->showStack(canvas, turret);
-			showWallPiece(canvas, wallPiece);
+			showWallPiece(canvas, wallPiece, owner->pos.topLeft());
 		}
 	}
 }

+ 2 - 2
client/battle/CBattleSiegeController.h

@@ -78,7 +78,7 @@ class CBattleSiegeController
 	/// returns true if chosen wall piece should be present in current battle
 	bool getWallPieceExistance(EWallVisual::EWallVisual what) const;
 
-	void showWallPiece(std::shared_ptr<CCanvas> canvas, EWallVisual::EWallVisual what);
+	void showWallPiece(std::shared_ptr<CCanvas> canvas, EWallVisual::EWallVisual what, const Point & offset);
 
 public:
 	CBattleSiegeController(CBattleInterface * owner, const CGTownInstance *siegeTown);
@@ -88,7 +88,7 @@ public:
 	void stackIsCatapulting(const CatapultAttack & ca);
 
 	/// call-ins from other battle controllers
-	void showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas);
+	void showAbsoluteObstacles(std::shared_ptr<CCanvas> canvas, const Point & offset);
 	void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location );
 
 	/// queries from other battle controllers

+ 1 - 1
config/factions/necropolis.json

@@ -222,7 +222,7 @@
 				},
 				"moat" :
 				{
-					"bank" : { "x" : -1, "y" : -1 },
+					"bank" : { "x" : 406, "y" : 77 },
 					"moat" : { "x" : 406, "y" : 77 }
 				},
 				"static" :