1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Bugfixing: fix crashes on battle start & most noticeable glitches

This commit is contained in:
Ivan Savenko 2022-11-27 02:26:02 +02:00
parent 0cae259f53
commit e76cd1b6a7
16 changed files with 156 additions and 143 deletions

View File

@ -161,7 +161,26 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
// 1) Vampire mansion in Necropolis (not 1st color is transparent)
// 2) Battle background when fighting on grass/dirt, topmost sky part (NO transparent color)
// 3) New objects that may use 24-bit images for icons (e.g. witchking arts)
if (ret->format->palette)
// 4) special case - there are 2 .bmp images that have semi-transparency (CCELLGRD.BMP & CCELLSHD.BMP)
if (ret->format->palette &&
ret->format->palette->colors[0].r == 255 &&
ret->format->palette->colors[0].g == 0 &&
ret->format->palette->colors[0].b == 255 )
{
static SDL_Color shadow[3] =
{
{ 0, 0, 0, 0},// 100% - transparency
{ 0, 0, 0, 32},// 75% - shadow border,
{ 0, 0, 0, 128},// 50% - shadow body
};
CSDL_Ext::setColorKey(ret, ret->format->palette->colors[0]);
ret->format->palette->colors[0] = shadow[0];
ret->format->palette->colors[1] = shadow[1];
ret->format->palette->colors[4] = shadow[2];
}
else if (ret->format->palette)
{
CSDL_Ext::setDefaultColorKeyPresize(ret);
}
@ -173,6 +192,7 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
{
CSDL_Ext::setDefaultColorKey(ret);
}
return ret;
}

View File

@ -28,7 +28,6 @@
#include "../gui/CAnimation.h"
#include "../gui/CCursorHandler.h"
#include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../../CCallback.h"
#include "../../lib/CStack.h"
@ -488,8 +487,8 @@ bool CMovementAnimation::init()
owner->moveSoundHander = CCS->soundh->playSound(battle_sound(stack->getCreature(), move), -1);
}
Point begPosition = CClickableHex::getXYUnitAnim(oldPos, stack, owner);
Point endPosition = CClickableHex::getXYUnitAnim(nextHex, stack, owner);
Point begPosition = owner->stacksController->getStackPositionAtHex(oldPos, stack);
Point endPosition = owner->stacksController->getStackPositionAtHex(nextHex, stack);
timeToMove = AnimationControls::getMovementDuration(stack->getCreature());
@ -522,7 +521,7 @@ void CMovementAnimation::nextFrame()
if(progress >= 1.0)
{
// Sets the position of the creature animation sprites
Point coords = CClickableHex::getXYUnitAnim(nextHex, stack, owner);
Point coords = owner->stacksController->getStackPositionAtHex(nextHex, stack);
myAnim->pos = coords;
// true if creature haven't reached the final destination hex
@ -552,7 +551,7 @@ void CMovementAnimation::endAnim()
{
assert(stack);
myAnim->pos = CClickableHex::getXYUnitAnim(nextHex, stack, owner);
myAnim->pos = owner->stacksController->getStackPositionAtHex(nextHex, stack);
CBattleAnimation::endAnim();
owner->stacksController->addNewAnim(new CMovementEndAnimation(owner, stack, nextHex));
@ -692,7 +691,7 @@ void CBattleStackAnimation::rotateStack(BattleHex hex)
{
setStackFacingRight(stack, !stackFacingRight(stack));
stackAnimation(stack)->pos = CClickableHex::getXYUnitAnim(hex, stack, owner);
stackAnimation(stack)->pos = owner->stacksController->getStackPositionAtHex(hex, stack);
}
void CReverseAnimation::setupSecondPart()
@ -761,7 +760,7 @@ bool CShootingAnimation::init()
void CShootingAnimation::setAnimationGroup()
{
Point shooterPos = stackAnimation(attackingStack)->pos.topLeft();
Point shotTarget = CClickableHex::getXYUnitAnim(dest, attackedStack, owner) + Point(225, 225);
Point shotTarget = owner->stacksController->getStackPositionAtHex(dest, attackedStack) + Point(225, 225);
//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;
@ -784,7 +783,7 @@ void CShootingAnimation::initializeProjectile()
if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS)
shooterInfo = owner->siegeController->getTurretCreature();
Point shotTarget = CClickableHex::getXYUnitAnim(dest, attackedStack, owner) + Point(225, 225);
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;
@ -922,9 +921,9 @@ bool CCastAnimation::init()
// NOTE: two lines below return different positions (very notable with 2-hex creatures). Obtaining via creanims seems to be more precise
fromPos = stackAnimation(attackingStack)->pos.topLeft();
//xycoord = CClickableHex::getXYUnitAnim(shooter->getPosition(), true, shooter, owner);
//xycoord = owner->stacksController->getStackPositionAtHex(shooter->getPosition(), shooter);
destPos = CClickableHex::getXYUnitAnim(dest, attackedStack, owner);
destPos = owner->stacksController->getStackPositionAtHex(dest, attackedStack);
double projectileAngle = atan2(fabs((double)destPos.y - fromPos.y), fabs((double)destPos.x - fromPos.x));

View File

@ -26,10 +26,11 @@
#include "../../lib/CStack.h"
#include "../../lib/CConfigHandler.h"
CBattleControlPanel::CBattleControlPanel(CBattleInterface * owner):
CBattleControlPanel::CBattleControlPanel(CBattleInterface * owner, const Point & position):
owner(owner)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos += position;
//preparing buttons and console
bOptions = std::make_shared<CButton> (Point( 3, 5), "icm003.def", CGI->generaltexth->zelp[381], std::bind(&CBattleControlPanel::bOptionsf,this), SDLK_o);
@ -55,6 +56,21 @@ CBattleControlPanel::CBattleControlPanel(CBattleInterface * owner):
tacticPhaseEnded();
}
void CBattleControlPanel::show(SDL_Surface * to)
{
//show menu before all other elements to keep it in background
menu->show(to);
CIntObject::show(to);
}
void CBattleControlPanel::showAll(SDL_Surface * to)
{
//show menu before all other elements to keep it in background
menu->showAll(to);
CIntObject::showAll(to);
}
void CBattleControlPanel::tacticPhaseStarted()
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
@ -63,6 +79,7 @@ void CBattleControlPanel::tacticPhaseStarted()
btactEnd = std::make_shared<CButton>(Point(419, 4), "icm012.def", std::make_pair("", ""), [&](){ bTacticPhaseEnd();}, SDLK_RETURN);
menu = std::make_shared<CPicture>("COPLACBR.BMP", 0, 0);
menu->colorize(owner->curInt->playerID);
menu->recActions &= ~(SHOWALL | UPDATE);
}
void CBattleControlPanel::tacticPhaseEnded()
{
@ -73,6 +90,7 @@ void CBattleControlPanel::tacticPhaseEnded()
menu = std::make_shared<CPicture>("CBAR.BMP", 0, 0);
menu->colorize(owner->curInt->playerID);
menu->recActions &= ~(SHOWALL | UPDATE);
}
void CBattleControlPanel::bOptionsf()
@ -82,9 +100,7 @@ void CBattleControlPanel::bOptionsf()
CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
Rect tempRect = genRect(431, 481, 160, 84);
tempRect += pos.topLeft();
GH.pushIntT<CBattleOptionsWindow>(tempRect, owner);
GH.pushIntT<CBattleOptionsWindow>(owner);
}
void CBattleControlPanel::bSurrenderf()

View File

@ -57,8 +57,12 @@ public:
// unlike activate/deactivate this method will correctly grey-out all elements
void blockUI(bool on);
void show(SDL_Surface * to) override;
void showAll(SDL_Surface * to) override;
void tacticPhaseStarted();
void tacticPhaseEnded();
CBattleControlPanel(CBattleInterface * owner);
CBattleControlPanel(CBattleInterface * owner, const Point & position);
};

View File

@ -29,7 +29,7 @@
CBattleFieldController::CBattleFieldController(CBattleInterface * owner):
owner(owner),
attackingHex(-1)
attackingHex(BattleHex::INVALID)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos.w = owner->pos.w;
@ -58,7 +58,14 @@ CBattleFieldController::CBattleFieldController(CBattleInterface * owner):
cellBorders = std::make_shared<CCanvas>(Point(background->width(), background->height()));
for (int i=0; i<GameConstants::BFIELD_SIZE; ++i)
{
if ( i % GameConstants::BFIELD_WIDTH == 0)
continue;
if ( i % GameConstants::BFIELD_WIDTH == GameConstants::BFIELD_WIDTH - 1)
continue;
cellBorders->draw(cellBorder, hexPositionLocal(i).topLeft());
}
backgroundWithHexes = std::make_shared<CCanvas>(Point(background->width(), background->height()));

View File

@ -24,19 +24,12 @@
#include "../CGameInfo.h"
#include "../CMessage.h"
#include "../CMT.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../CVideoHandler.h"
#include "../Graphics.h"
#include "../gui/CAnimation.h"
#include "../gui/CCanvas.h"
#include "../gui/CCursorHandler.h"
#include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../windows/CAdvmapInterface.h"
#include "../windows/CCreatureWindow.h"
#include "../windows/CSpellWindow.h"
#include "../../CCallback.h"
#include "../../lib/CStack.h"
@ -44,15 +37,7 @@
#include "../../lib/CGeneralTextHandler.h"
#include "../../lib/CHeroHandler.h"
#include "../../lib/CondSh.h"
#include "../../lib/CRandomGenerator.h"
#include "../../lib/spells/CSpellHandler.h"
#include "../../lib/spells/ISpellMechanics.h"
#include "../../lib/spells/Problem.h"
#include "../../lib/CTownHandler.h"
#include "../../lib/BattleFieldHandler.h"
#include "../../lib/ObstacleHandler.h"
#include "../../lib/CGameState.h"
#include "../../lib/mapping/CMap.h"
#include "../../lib/mapObjects/CGTownInstance.h"
#include "../../lib/NetPacks.h"
#include "../../lib/UnlockGuard.h"
@ -127,10 +112,14 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
this->army1 = army1;
this->army2 = army2;
controlPanel = std::make_shared<CBattleControlPanel>(this, Point(0, 556));
//preparing menu background and terrain
fieldController.reset( new CBattleFieldController(this));
stacksController.reset( new CBattleStacksController(this));
actionsController.reset( new CBattleActionsController(this));
effectsController.reset(new CBattleEffectsController(this));
//loading hero animations
if(hero1) // attacking hero
@ -517,7 +506,7 @@ void CBattleInterface::spellCast(const BattleSpellCast * sc)
{
if(casterStack != nullptr)
{
srccoord = CClickableHex::getXYUnitAnim(casterStack->getPosition(), casterStack, this);
srccoord = stacksController->getStackPositionAtHex(casterStack->getPosition(), casterStack);
srccoord.x += 250;
srccoord.y += 240;
}
@ -536,7 +525,7 @@ void CBattleInterface::spellCast(const BattleSpellCast * sc)
//playing projectile animation
if (sc->tile.isValid())
{
Point destcoord = CClickableHex::getXYUnitAnim(sc->tile, curInt->cb->battleGetStackByPos(sc->tile), this); //position attacked by projectile
Point destcoord = stacksController->getStackPositionAtHex(sc->tile, curInt->cb->battleGetStackByPos(sc->tile)); //position attacked by projectile
destcoord.x += 250; destcoord.y += 240;
//animation angle
@ -921,7 +910,6 @@ void CBattleInterface::showAll(SDL_Surface *to)
void CBattleInterface::show(SDL_Surface *to)
{
auto canvas = std::make_shared<CCanvas>(to);
assert(to);
SDL_Rect buf;
@ -944,7 +932,7 @@ void CBattleInterface::show(SDL_Surface *to)
}
fieldController->showHighlightedHexes(canvas);
showBattlefieldObjects(to);
showBattlefieldObjects(canvas);
projectilesController->showProjectiles(canvas);
if(battleActionsStarted)
@ -952,7 +940,7 @@ void CBattleInterface::show(SDL_Surface *to)
SDL_SetClipRect(to, &buf); //restoring previous clip_rect
showInterface(to);
showInterface(canvas);
//activation of next stack, if any
//TODO: should be moved to the very start of this method?
@ -968,17 +956,15 @@ void CBattleInterface::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, c
effectsController->showBattlefieldObjects(canvas, location);
}
void CBattleInterface::showBattlefieldObjects(SDL_Surface *to)
void CBattleInterface::showBattlefieldObjects(std::shared_ptr<CCanvas> canvas)
{
auto canvas = std::make_shared<CCanvas>(to);
showBattlefieldObjects(canvas, BattleHex::HEX_BEFORE_ALL);
// show heroes after "beforeAll" - e.g. topmost wall in siege
if (attackingHero)
attackingHero->show(to);
attackingHero->show(canvas->getSurface());
if (defendingHero)
defendingHero->show(to);
defendingHero->show(canvas->getSurface());
for (int i = 0; i < GameConstants::BFIELD_SIZE; ++i)
showBattlefieldObjects(canvas, BattleHex(i));
@ -986,11 +972,11 @@ void CBattleInterface::showBattlefieldObjects(SDL_Surface *to)
showBattlefieldObjects(canvas, BattleHex::HEX_AFTER_ALL);
}
void CBattleInterface::showInterface(SDL_Surface *to)
void CBattleInterface::showInterface(std::shared_ptr<CCanvas> canvas)
{
//showing in-game console
LOCPLINT->cingconsole->show(to);
controlPanel->show(to);
LOCPLINT->cingconsole->show(canvas->getSurface());
controlPanel->showAll(canvas->getSurface());
Rect posWithQueue = Rect(pos.x, pos.y, 800, 600);
@ -1002,13 +988,13 @@ void CBattleInterface::showInterface(SDL_Surface *to)
posWithQueue.h += queue->pos.h;
}
queue->showAll(to);
queue->showAll(canvas->getSurface());
}
//printing border around interface
if (screen->w != 800 || screen->h !=600)
{
CMessage::drawBorder(curInt->playerID,to,posWithQueue.w + 28, posWithQueue.h + 28, posWithQueue.x-14, posWithQueue.y-15);
CMessage::drawBorder(curInt->playerID,canvas->getSurface(),posWithQueue.w + 28, posWithQueue.h + 28, posWithQueue.x-14, posWithQueue.y-15);
}
}

View File

@ -98,9 +98,9 @@ private:
const CGHeroInstance *getActiveHero(); //returns hero that can currently cast a spell
void showInterface(SDL_Surface *to);
void showInterface(std::shared_ptr<CCanvas> canvas);
void showBattlefieldObjects(SDL_Surface *to);
void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas);
void showBattlefieldObjects(std::shared_ptr<CCanvas> canvas, const BattleHex & location );
void setHeroAnimation(ui8 side, int phase);

View File

@ -26,7 +26,6 @@
#include "../gui/CAnimation.h"
#include "../gui/CCursorHandler.h"
#include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../widgets/Buttons.h"
#include "../widgets/Images.h"
#include "../widgets/TextControls.h"
@ -317,13 +316,10 @@ CHeroInfoWindow::CHeroInfoWindow(const InfoAboutHero & hero, Point * position)
labels.push_back(std::make_shared<CLabel>(39, 186, EFonts::FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, std::to_string(currentSpellPoints) + "/" + std::to_string(maxSpellPoints)));
}
CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner)
CBattleOptionsWindow::CBattleOptionsWindow(CBattleInterface *owner):
CWindowObject(PLAYER_COLORED, "comopbck.bmp")
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
pos = position;
background = std::make_shared<CPicture>("comopbck.bmp");
background->colorize(owner->getCurrentPlayerInterface()->playerID);
auto viewGrid = std::make_shared<CToggleButton>(Point(25, 56), "sysopchk.def", CGI->generaltexth->zelp[427], [=](bool on){owner->setPrintCellBorders(on);} );
viewGrid->setSelected(settings["battle"]["cellBorders"].Bool());
@ -577,46 +573,6 @@ void CBattleResultWindow::bExitf()
CCS->videoh->close();
}
Point CClickableHex::getXYUnitAnim(BattleHex hexNum, const CStack * stack, CBattleInterface * cbi)
{
assert(cbi);
Point ret(-500, -500); //returned value
if(stack && stack->initialPosition < 0) //creatures in turrets
return cbi->siegeController->getTurretCreaturePosition(stack->initialPosition);
static const Point basePos(-190, -139); // position of creature in topleft corner
static const int imageShiftX = 30; // X offset to base pos for facing right stacks, negative for facing left
ret.x = basePos.x + 22 * ( (hexNum.getY() + 1)%2 ) + 44 * hexNum.getX();
ret.y = basePos.y + 42 * hexNum.getY();
if (stack)
{
if(cbi->stacksController->facingRight(stack))
ret.x += imageShiftX;
else
ret.x -= imageShiftX;
//shifting position for double - hex creatures
if(stack->doubleWide())
{
if(stack->side == BattleSide::ATTACKER)
{
if(cbi->stacksController->facingRight(stack))
ret.x -= 44;
}
else
{
if(!cbi->stacksController->facingRight(stack))
ret.x += 44;
}
}
}
//returning
return ret + CPlayerInterface::battleInt->pos;
}
void CClickableHex::hover(bool on)
{
hovered = on;

View File

@ -98,17 +98,16 @@ public:
};
/// Class which manages the battle options window
class CBattleOptionsWindow : public WindowBase
class CBattleOptionsWindow : public CWindowObject
{
private:
std::shared_ptr<CPicture> background;
std::shared_ptr<CButton> setToDefault;
std::shared_ptr<CButton> exit;
std::shared_ptr<CToggleGroup> animSpeeds;
std::vector<std::shared_ptr<CLabel>> labels;
std::vector<std::shared_ptr<CToggleButton>> toggles;
public:
CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface * owner);
CBattleOptionsWindow(CBattleInterface * owner);
void bDefaultf(); //default button callback
void bExitf(); //exit button callback
@ -146,11 +145,6 @@ public:
bool strictHovered; //for determining if hex is hovered by mouse (this is different problem than hex's graphic hovering)
CBattleInterface * myInterface; //interface that owns me
/// returns (x, y) of left top corner of animation
/// FIXME: move someplace else?
/// FIXME: some usages should be replaced with creAnims->pos?
static Point getXYUnitAnim(BattleHex hexNum, const CStack * creature, CBattleInterface * cbi);
//for user interactions
void hover (bool on) override;
void mouseMoved (const SDL_MouseMotionEvent &sEvent) override;

View File

@ -130,7 +130,7 @@ void CBattleObstacleController::showBattlefieldObjects(std::shared_ptr<CCanvas>
if (obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
continue;
if (obstacle->obstacleType != CObstacleInstance::MOAT)
if (obstacle->obstacleType == CObstacleInstance::MOAT)
continue;
if ( obstacle->pos != location)

View File

@ -341,7 +341,7 @@ void CBattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
//no attacker stack, assume spell-related (earthquake) - only hit animation
for (auto attackInfo : ca.attackedParts)
{
Point destPos = CClickableHex::getXYUnitAnim(attackInfo.destinationTile, nullptr, owner) + Point(99, 120);
Point destPos = owner->stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120);
owner->stacksController->addNewAnim(new CEffectAnimation(owner, "SGEXPL.DEF", destPos.x, destPos.y));
}

View File

@ -18,7 +18,6 @@
#include "CBattleProjectileController.h"
#include "CBattleControlPanel.h"
#include "../gui/CAnimation.h"
#include "../gui/SDL_Extensions.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CCanvas.h"
#include "../../lib/battle/BattleHex.h"
@ -58,7 +57,14 @@ static void onAnimationFinished(const CStack *stack, std::weak_ptr<CCreatureAnim
}
CBattleStacksController::CBattleStacksController(CBattleInterface * owner):
owner(owner)
owner(owner),
activeStack(nullptr),
mouseHoveredStack(nullptr),
stackToActivate(nullptr),
selectedStack(nullptr),
stackCanCastSpell(false),
creatureSpellToCast(uint32_t(-1)),
animIDhelper(0)
{
//preparing graphics for displaying amounts of creatures
amountNormal = IImage::createFromFile("CMNUMWIN.BMP");
@ -66,10 +72,10 @@ CBattleStacksController::CBattleStacksController(CBattleInterface * owner):
amountNegative = IImage::createFromFile("CMNUMWIN.BMP");
amountEffNeutral = IImage::createFromFile("CMNUMWIN.BMP");
ColorShifterAddMulExcept shifterNormal ({0,0,0,0}, {150, 48, 237, 255}, {132, 231, 255, 255});
ColorShifterAddMulExcept shifterPositive({0,0,0,0}, { 45, 255, 45, 255}, {132, 231, 255, 255});
ColorShifterAddMulExcept shifterNegative({0,0,0,0}, {255, 45, 45, 255}, {132, 231, 255, 255});
ColorShifterAddMulExcept shifterNeutral ({0,0,0,0}, {255, 255, 45, 255}, {132, 231, 255, 255});
ColorShifterAddMulExcept shifterNormal ({0,0,0,0}, {150, 50, 255, 255}, {255, 231, 132, 255});
ColorShifterAddMulExcept shifterPositive({0,0,0,0}, { 50, 255, 50, 255}, {255, 231, 132, 255});
ColorShifterAddMulExcept shifterNegative({0,0,0,0}, {255, 50, 50, 255}, {255, 231, 132, 255});
ColorShifterAddMulExcept shifterNeutral ({0,0,0,0}, {255, 255, 50, 255}, {255, 231, 132, 255});
amountNormal->adjustPalette(&shifterNormal);
amountPositive->adjustPalette(&shifterPositive);
@ -119,8 +125,8 @@ void CBattleStacksController::showBattlefieldObjects(std::shared_ptr<CCanvas> ca
if (creAnims[stack->ID]->isDead())
{
//if ( location == stack->getPosition() )
if ( location == BattleHex::HEX_BEFORE_ALL ) //FIXME: any cases when this won't work?
{};
if ( location == BattleHex::HEX_BEFORE_ALL ) //FIXME: any cases when using BEFORE_ALL won't work?
showStack(canvas, stack);
continue;
}
@ -128,7 +134,7 @@ void CBattleStacksController::showBattlefieldObjects(std::shared_ptr<CCanvas> ca
if (!creAnims[stack->ID]->isMoving())
{
if ( location == stack->getPosition() )
{};
showStack(canvas, stack);
continue;
}
@ -136,14 +142,14 @@ void CBattleStacksController::showBattlefieldObjects(std::shared_ptr<CCanvas> ca
if (stack->hasBonusOfType(Bonus::FLYING))
{
if ( location == BattleHex::HEX_AFTER_ALL)
{};
showStack(canvas, stack);
continue;
}
// else - unit moving on ground
{
if ( location == getCurrentPosition(stack) )
{};
showStack(canvas, stack);
continue;
}
}
@ -177,7 +183,7 @@ void CBattleStacksController::stackAdded(const CStack * stack)
{
creDir[stack->ID] = stack->side == BattleSide::ATTACKER; // must be set before getting stack position
Point coords = CClickableHex::getXYUnitAnim(stack->getPosition(), stack, owner);
Point coords = getStackPositionAtHex(stack->getPosition(), stack);
if(stack->initialPosition < 0) //turret
{
@ -396,7 +402,7 @@ void CBattleStacksController::stackRemoved(uint32_t stackID)
BattleAction *action = new BattleAction();
action->side = owner->defendingHeroInstance ? (owner->curInt->playerID == owner->defendingHeroInstance->tempOwner) : false;
action->actionType = EActionType::CANCEL;
action->stackNumber = owner->stacksController->getActiveStack()->ID;
action->stackNumber = getActiveStack()->ID;
owner->givenCommand.setn(action);
setActiveStack(nullptr);
}
@ -448,8 +454,8 @@ void CBattleStacksController::stackAttacking( const CStack *attacker, BattleHex
bool CBattleStacksController::shouldRotate(const CStack * stack, const BattleHex & oldPos, const BattleHex & nextHex)
{
Point begPosition = CClickableHex::getXYUnitAnim(oldPos,stack, owner);
Point endPosition = CClickableHex::getXYUnitAnim(nextHex, stack, owner);
Point begPosition = getStackPositionAtHex(oldPos,stack);
Point endPosition = getStackPositionAtHex(nextHex, stack);
if((begPosition.x > endPosition.x) && facingRight(stack))
return true;
@ -510,7 +516,7 @@ void CBattleStacksController::activateStack()
setActiveStack(stackToActivate);
stackToActivate = nullptr;
const CStack * s = owner->stacksController->getActiveStack();
const CStack * s = getActiveStack();
if(!s)
return;
@ -565,3 +571,42 @@ SpellID CBattleStacksController::activeStackSpellToCast()
return SpellID::NONE;
return SpellID(creatureSpellToCast);
}
Point CBattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CStack * stack)
{
Point ret(-500, -500); //returned value
if(stack && stack->initialPosition < 0) //creatures in turrets
return owner->siegeController->getTurretCreaturePosition(stack->initialPosition);
static const Point basePos(-190, -139); // position of creature in topleft corner
static const int imageShiftX = 30; // X offset to base pos for facing right stacks, negative for facing left
ret.x = basePos.x + 22 * ( (hexNum.getY() + 1)%2 ) + 44 * hexNum.getX();
ret.y = basePos.y + 42 * hexNum.getY();
if (stack)
{
if(facingRight(stack))
ret.x += imageShiftX;
else
ret.x -= imageShiftX;
//shifting position for double - hex creatures
if(stack->doubleWide())
{
if(stack->side == BattleSide::ATTACKER)
{
if(facingRight(stack))
ret.x -= 44;
}
else
{
if(!facingRight(stack))
ret.x += 44;
}
}
}
//returning
return ret + owner->pos.topLeft();
}

View File

@ -9,6 +9,8 @@
*/
#pragma once
#include "../gui/Geometries.h"
struct BattleObjectsByHex;
struct SDL_Surface;
struct BattleHex;
@ -89,5 +91,8 @@ public:
const CStack* getActiveStack();
const CStack* getSelectedStack();
/// returns position of animation needed to place stack in specific hex
Point getStackPositionAtHex(BattleHex hexNum, const CStack * creature);
friend class CBattleAnimation; // for exposing pendingAnims/creAnims/creDir to animations
};

View File

@ -13,7 +13,6 @@
#include "../../lib/CConfigHandler.h"
#include "../../lib/CCreatureHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../gui/CCanvas.h"
static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 };

View File

@ -188,24 +188,6 @@ Uint32 CSDL_Ext::SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y
}
}
void CSDL_Ext::alphaTransform(SDL_Surface *src)
{
assert(src->format->BitsPerPixel == 8);
SDL_Color colors[] =
{
{ 0, 0, 0, 0}, { 0, 0, 0, 32}, { 0, 0, 0, 64},
{ 0, 0, 0, 128}, { 0, 0, 0, 128}
};
for (size_t i=0; i< ARRAY_COUNT(colors); i++ )
{
SDL_Color & palColor = src->format->palette->colors[i];
palColor = colors[i];
}
SDL_SetColorKey(src, SDL_TRUE, 0);
}
template<int bpp>
int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
{

View File

@ -197,7 +197,8 @@ class ColorShifterAddMulExcept : public ColorShifterAddMul
SDL_Color ignored;
public:
ColorShifterAddMulExcept(SDL_Color add, SDL_Color mul, SDL_Color ignored) :
ColorShifterAddMul(add, mul)
ColorShifterAddMul(add, mul),
ignored(ignored)
{}
SDL_Color shiftColor(SDL_Color input) const override
@ -241,7 +242,6 @@ namespace CSDL_Ext
SDL_Surface * verticalFlip(SDL_Surface * toRot); //vertical flip
SDL_Surface * horizontalFlip(SDL_Surface * toRot); //horizontal flip
Uint32 SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte = false);
void alphaTransform(SDL_Surface * src); //adds transparency and shadows (partial handling only; see examples of using for details)
bool isTransparent(SDL_Surface * srf, int x, int y); //checks if surface is transparent at given position
Uint8 *getPxPtr(const SDL_Surface * const &srf, const int x, const int y);