mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Fixing sieges, part 1
This commit is contained in:
@@ -134,9 +134,9 @@ void CAttackAnimation::nextFrame()
|
|||||||
if(!soundPlayed)
|
if(!soundPlayed)
|
||||||
{
|
{
|
||||||
if(shooting)
|
if(shooting)
|
||||||
CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), shoot));
|
CCS->soundh->playSound(battle_sound(getCreature(), shoot));
|
||||||
else
|
else
|
||||||
CCS->soundh->playSound(battle_sound(attackingStack->getCreature(), attack));
|
CCS->soundh->playSound(battle_sound(getCreature(), attack));
|
||||||
soundPlayed = true;
|
soundPlayed = true;
|
||||||
}
|
}
|
||||||
CBattleAnimation::nextFrame();
|
CBattleAnimation::nextFrame();
|
||||||
@@ -164,6 +164,14 @@ bool CAttackAnimation::checkInitialConditions()
|
|||||||
return isEarliest(false);
|
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)
|
CAttackAnimation::CAttackAnimation(CBattleInterface *_owner, const CStack *attacker, BattleHex _dest, const CStack *defender)
|
||||||
: CBattleStackAnimation(_owner, attacker),
|
: CBattleStackAnimation(_owner, attacker),
|
||||||
shooting(false), group(CCreatureAnim::SHOOT_FRONT),
|
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)
|
//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;
|
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.
|
// Calculate projectile start position. Offsets are read out of the CRANIM.TXT.
|
||||||
if (projectileAngle > straightAngle)
|
if (projectileAngle > straightAngle)
|
||||||
@@ -780,11 +788,7 @@ void CShootingAnimation::setAnimationGroup()
|
|||||||
|
|
||||||
void CShootingAnimation::initializeProjectile()
|
void CShootingAnimation::initializeProjectile()
|
||||||
{
|
{
|
||||||
const CCreature *shooterInfo = attackingStack->getCreature();
|
const CCreature *shooterInfo = getCreature();
|
||||||
|
|
||||||
if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS)
|
|
||||||
shooterInfo = owner->siegeController->getTurretCreature();
|
|
||||||
|
|
||||||
Point shotTarget = owner->stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225);
|
Point shotTarget = owner->stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225);
|
||||||
Point shotOrigin = stackAnimation(attackingStack)->pos.topLeft() + Point(222, 265);
|
Point shotOrigin = stackAnimation(attackingStack)->pos.topLeft() + Point(222, 265);
|
||||||
int multiplier = stackFacingRight(attackingStack) ? 1 : -1;
|
int multiplier = stackFacingRight(attackingStack) ? 1 : -1;
|
||||||
@@ -828,12 +832,25 @@ void CShootingAnimation::nextFrame()
|
|||||||
return;
|
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)
|
if (!projectileEmitted)
|
||||||
{
|
{
|
||||||
const CCreature *shooterInfo = attackingStack->getCreature();
|
const CCreature *shooterInfo = getCreature();
|
||||||
|
|
||||||
if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS)
|
assert(stackAnimation(attackingStack)->isShooting());
|
||||||
shooterInfo = owner->siegeController->getTurretCreature();
|
|
||||||
|
|
||||||
// emit projectile once animation playback reached "climax" frame
|
// emit projectile once animation playback reached "climax" frame
|
||||||
if ( stackAnimation(attackingStack)->getCurrentFrame() >= shooterInfo->animation.attackClimaxFrame )
|
if ( stackAnimation(attackingStack)->getCurrentFrame() >= shooterInfo->animation.attackClimaxFrame )
|
||||||
@@ -842,17 +859,13 @@ void CShootingAnimation::nextFrame()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// animation should be paused if there is an active projectile
|
|
||||||
if (projectileEmitted && owner->projectilesController->hasActiveProjectile(attackingStack))
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
CAttackAnimation::nextFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CShootingAnimation::endAnim()
|
void CShootingAnimation::endAnim()
|
||||||
{
|
{
|
||||||
|
assert(!owner->projectilesController->hasActiveProjectile(attackingStack));
|
||||||
|
assert(projectileEmitted);
|
||||||
|
|
||||||
// FIXME: is this possible? Animation is over but we're yet to fire projectile?
|
// FIXME: is this possible? Animation is over but we're yet to fire projectile?
|
||||||
if (!projectileEmitted)
|
if (!projectileEmitted)
|
||||||
{
|
{
|
||||||
@@ -1157,11 +1170,15 @@ void CEffectAnimation::endAnim()
|
|||||||
{
|
{
|
||||||
CBattleAnimation::endAnim();
|
CBattleAnimation::endAnim();
|
||||||
|
|
||||||
boost::range::remove_if(owner->effectsController->battleEffects,
|
auto & effects = owner->effectsController->battleEffects;
|
||||||
[&](const BattleEffect & elem)
|
|
||||||
{
|
for ( auto it = effects.begin(); it != effects.end(); )
|
||||||
return elem.effectID == ID;
|
{
|
||||||
});
|
if (it->effectID == ID)
|
||||||
|
it = effects.erase(it);
|
||||||
|
else
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ protected:
|
|||||||
const CStack *attackedStack;
|
const CStack *attackedStack;
|
||||||
const CStack *attackingStack;
|
const CStack *attackingStack;
|
||||||
int attackingStackPosBeforeReturn; //for stacks with return_after_strike feature
|
int attackingStackPosBeforeReturn; //for stacks with return_after_strike feature
|
||||||
|
|
||||||
|
const CCreature * getCreature();
|
||||||
public:
|
public:
|
||||||
void nextFrame() override;
|
void nextFrame() override;
|
||||||
void endAnim() override;
|
void endAnim() override;
|
||||||
|
|||||||
@@ -106,7 +106,9 @@ void CBattleFieldController::redrawBackgroundWithHexes()
|
|||||||
|
|
||||||
//prepare background graphic with hexes and shaded hexes
|
//prepare background graphic with hexes and shaded hexes
|
||||||
backgroundWithHexes->draw(background, Point(0,0));
|
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())
|
if (settings["battle"]["stackRange"].Bool())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -927,9 +927,9 @@ void CBattleInterface::show(SDL_Surface *to)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fieldController->showBackgroundImage(canvas);
|
fieldController->showBackgroundImage(canvas);
|
||||||
obstacleController->showAbsoluteObstacles(canvas);
|
obstacleController->showAbsoluteObstacles(canvas, pos.topLeft());
|
||||||
if ( siegeController )
|
if ( siegeController )
|
||||||
siegeController->showAbsoluteObstacles(canvas);
|
siegeController->showAbsoluteObstacles(canvas, pos.topLeft());
|
||||||
}
|
}
|
||||||
fieldController->showHighlightedHexes(canvas);
|
fieldController->showHighlightedHexes(canvas);
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ void CBattleObstacleController::obstaclePlaced(const CObstacleInstance & oi)
|
|||||||
//CCS->soundh->playSound(sound);
|
//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
|
//Blit absolute obstacles
|
||||||
for(auto & oi : owner->curInt->cb->battleGetAllObstacles())
|
for(auto & oi : owner->curInt->cb->battleGetAllObstacles())
|
||||||
@@ -118,7 +118,7 @@ void CBattleObstacleController::showAbsoluteObstacles(std::shared_ptr<CCanvas> c
|
|||||||
{
|
{
|
||||||
auto img = getObstacleImage(*oi);
|
auto img = getObstacleImage(*oi);
|
||||||
if(img)
|
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();
|
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -35,9 +35,7 @@ public:
|
|||||||
|
|
||||||
void obstaclePlaced(const CObstacleInstance & oi);
|
void obstaclePlaced(const CObstacleInstance & oi);
|
||||||
void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance>> &obstacles);
|
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 showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location );
|
||||||
|
|
||||||
void redrawBackgroundWithHexes(std::shared_ptr<CCanvas> to);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ bool CBattleProjectileController::hasActiveProjectile(const CStack * stack)
|
|||||||
|
|
||||||
void CBattleProjectileController::createProjectile(const CStack * shooter, const CStack * target, Point from, Point dest)
|
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;
|
std::shared_ptr<ProjectileBase> projectile;
|
||||||
|
|
||||||
@@ -262,8 +262,8 @@ void CBattleProjectileController::createProjectile(const CStack * shooter, const
|
|||||||
catapultProjectile->step = 0;
|
catapultProjectile->step = 0;
|
||||||
catapultProjectile->steps = 0;
|
catapultProjectile->steps = 0;
|
||||||
|
|
||||||
double animSpeed = AnimationControls::getProjectileSpeed() / 10;
|
//double animSpeed = AnimationControls::getProjectileSpeed() / 10;
|
||||||
catapultProjectile->steps = std::round(std::abs((dest.x - from.x) / animSpeed));
|
//catapultProjectile->steps = std::round(std::abs((dest.x - from.x) / animSpeed));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -312,16 +312,18 @@ void CBattleProjectileController::createProjectile(const CStack * shooter, const
|
|||||||
}
|
}
|
||||||
missileProjectile->frameNum = bestID;
|
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->from = from;
|
||||||
projectile->dest = dest;
|
projectile->dest = dest;
|
||||||
projectile->shooterID = shooter->ID;
|
projectile->shooterID = shooter->ID;
|
||||||
|
|||||||
@@ -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 & ci = town->town->clientInfo;
|
||||||
auto const & pos = ci.siegePositions[what];
|
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
|
std::string CBattleSiegeController::getBattleBackgroundName() const
|
||||||
@@ -250,13 +251,13 @@ void CBattleSiegeController::gateStateChanged(const EGateState state)
|
|||||||
CCS->soundh->playSound(soundBase::DRAWBRG);
|
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))
|
if (getWallPieceExistance(EWallVisual::MOAT))
|
||||||
showWallPiece(canvas, EWallVisual::MOAT);
|
showWallPiece(canvas, EWallVisual::MOAT, owner->pos.topLeft());
|
||||||
|
|
||||||
if (getWallPieceExistance(EWallVisual::BACKGROUND_MOAT))
|
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 )
|
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::BOTTOM_BATTLEMENT &&
|
||||||
wallPiece != EWallVisual::UPPER_BATTLEMENT)
|
wallPiece != EWallVisual::UPPER_BATTLEMENT)
|
||||||
{
|
{
|
||||||
showWallPiece(canvas, wallPiece);
|
showWallPiece(canvas, wallPiece, owner->pos.topLeft());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +309,7 @@ void CBattleSiegeController::showBattlefieldObjects(std::shared_ptr<CCanvas> can
|
|||||||
if (turret)
|
if (turret)
|
||||||
{
|
{
|
||||||
owner->stacksController->showStack(canvas, turret);
|
owner->stacksController->showStack(canvas, turret);
|
||||||
showWallPiece(canvas, wallPiece);
|
showWallPiece(canvas, wallPiece, owner->pos.topLeft());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class CBattleSiegeController
|
|||||||
/// returns true if chosen wall piece should be present in current battle
|
/// returns true if chosen wall piece should be present in current battle
|
||||||
bool getWallPieceExistance(EWallVisual::EWallVisual what) const;
|
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:
|
public:
|
||||||
CBattleSiegeController(CBattleInterface * owner, const CGTownInstance *siegeTown);
|
CBattleSiegeController(CBattleInterface * owner, const CGTownInstance *siegeTown);
|
||||||
@@ -88,7 +88,7 @@ public:
|
|||||||
void stackIsCatapulting(const CatapultAttack & ca);
|
void stackIsCatapulting(const CatapultAttack & ca);
|
||||||
|
|
||||||
/// call-ins from other battle controllers
|
/// 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 );
|
void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location );
|
||||||
|
|
||||||
/// queries from other battle controllers
|
/// queries from other battle controllers
|
||||||
|
|||||||
@@ -222,7 +222,7 @@
|
|||||||
},
|
},
|
||||||
"moat" :
|
"moat" :
|
||||||
{
|
{
|
||||||
"bank" : { "x" : -1, "y" : -1 },
|
"bank" : { "x" : 406, "y" : 77 },
|
||||||
"moat" : { "x" : 406, "y" : 77 }
|
"moat" : { "x" : 406, "y" : 77 }
|
||||||
},
|
},
|
||||||
"static" :
|
"static" :
|
||||||
|
|||||||
Reference in New Issue
Block a user