1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +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) // 1) Vampire mansion in Necropolis (not 1st color is transparent)
// 2) Battle background when fighting on grass/dirt, topmost sky part (NO transparent color) // 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) // 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); CSDL_Ext::setDefaultColorKeyPresize(ret);
} }
@@ -173,6 +192,7 @@ SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fna
{ {
CSDL_Ext::setDefaultColorKey(ret); CSDL_Ext::setDefaultColorKey(ret);
} }
return ret; return ret;
} }

View File

@@ -28,7 +28,6 @@
#include "../gui/CAnimation.h" #include "../gui/CAnimation.h"
#include "../gui/CCursorHandler.h" #include "../gui/CCursorHandler.h"
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../../CCallback.h" #include "../../CCallback.h"
#include "../../lib/CStack.h" #include "../../lib/CStack.h"
@@ -488,8 +487,8 @@ bool CMovementAnimation::init()
owner->moveSoundHander = CCS->soundh->playSound(battle_sound(stack->getCreature(), move), -1); owner->moveSoundHander = CCS->soundh->playSound(battle_sound(stack->getCreature(), move), -1);
} }
Point begPosition = CClickableHex::getXYUnitAnim(oldPos, stack, owner); Point begPosition = owner->stacksController->getStackPositionAtHex(oldPos, stack);
Point endPosition = CClickableHex::getXYUnitAnim(nextHex, stack, owner); Point endPosition = owner->stacksController->getStackPositionAtHex(nextHex, stack);
timeToMove = AnimationControls::getMovementDuration(stack->getCreature()); timeToMove = AnimationControls::getMovementDuration(stack->getCreature());
@@ -522,7 +521,7 @@ void CMovementAnimation::nextFrame()
if(progress >= 1.0) if(progress >= 1.0)
{ {
// Sets the position of the creature animation sprites // 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; myAnim->pos = coords;
// true if creature haven't reached the final destination hex // true if creature haven't reached the final destination hex
@@ -552,7 +551,7 @@ void CMovementAnimation::endAnim()
{ {
assert(stack); assert(stack);
myAnim->pos = CClickableHex::getXYUnitAnim(nextHex, stack, owner); myAnim->pos = owner->stacksController->getStackPositionAtHex(nextHex, stack);
CBattleAnimation::endAnim(); CBattleAnimation::endAnim();
owner->stacksController->addNewAnim(new CMovementEndAnimation(owner, stack, nextHex)); owner->stacksController->addNewAnim(new CMovementEndAnimation(owner, stack, nextHex));
@@ -692,7 +691,7 @@ void CBattleStackAnimation::rotateStack(BattleHex hex)
{ {
setStackFacingRight(stack, !stackFacingRight(stack)); setStackFacingRight(stack, !stackFacingRight(stack));
stackAnimation(stack)->pos = CClickableHex::getXYUnitAnim(hex, stack, owner); stackAnimation(stack)->pos = owner->stacksController->getStackPositionAtHex(hex, stack);
} }
void CReverseAnimation::setupSecondPart() void CReverseAnimation::setupSecondPart()
@@ -761,7 +760,7 @@ bool CShootingAnimation::init()
void CShootingAnimation::setAnimationGroup() void CShootingAnimation::setAnimationGroup()
{ {
Point shooterPos = stackAnimation(attackingStack)->pos.topLeft(); 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) //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;
@@ -784,7 +783,7 @@ void CShootingAnimation::initializeProjectile()
if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS) if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS)
shooterInfo = owner->siegeController->getTurretCreature(); 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); Point shotOrigin = stackAnimation(attackingStack)->pos.topLeft() + Point(222, 265);
int multiplier = stackFacingRight(attackingStack) ? 1 : -1; 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 // 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(); 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)); 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/CStack.h"
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
CBattleControlPanel::CBattleControlPanel(CBattleInterface * owner): CBattleControlPanel::CBattleControlPanel(CBattleInterface * owner, const Point & position):
owner(owner) owner(owner)
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos += position;
//preparing buttons and console //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); 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(); 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() void CBattleControlPanel::tacticPhaseStarted()
{ {
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; 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); 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 = std::make_shared<CPicture>("COPLACBR.BMP", 0, 0);
menu->colorize(owner->curInt->playerID); menu->colorize(owner->curInt->playerID);
menu->recActions &= ~(SHOWALL | UPDATE);
} }
void CBattleControlPanel::tacticPhaseEnded() void CBattleControlPanel::tacticPhaseEnded()
{ {
@@ -73,6 +90,7 @@ void CBattleControlPanel::tacticPhaseEnded()
menu = std::make_shared<CPicture>("CBAR.BMP", 0, 0); menu = std::make_shared<CPicture>("CBAR.BMP", 0, 0);
menu->colorize(owner->curInt->playerID); menu->colorize(owner->curInt->playerID);
menu->recActions &= ~(SHOWALL | UPDATE);
} }
void CBattleControlPanel::bOptionsf() void CBattleControlPanel::bOptionsf()
@@ -82,9 +100,7 @@ void CBattleControlPanel::bOptionsf()
CCS->curh->changeGraphic(ECursor::ADVENTURE,0); CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
Rect tempRect = genRect(431, 481, 160, 84); GH.pushIntT<CBattleOptionsWindow>(owner);
tempRect += pos.topLeft();
GH.pushIntT<CBattleOptionsWindow>(tempRect, owner);
} }
void CBattleControlPanel::bSurrenderf() void CBattleControlPanel::bSurrenderf()

View File

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

View File

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

View File

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

View File

@@ -26,7 +26,6 @@
#include "../gui/CAnimation.h" #include "../gui/CAnimation.h"
#include "../gui/CCursorHandler.h" #include "../gui/CCursorHandler.h"
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../widgets/Buttons.h" #include "../widgets/Buttons.h"
#include "../widgets/Images.h" #include "../widgets/Images.h"
#include "../widgets/TextControls.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))); 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); 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);} ); 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()); viewGrid->setSelected(settings["battle"]["cellBorders"].Bool());
@@ -577,46 +573,6 @@ void CBattleResultWindow::bExitf()
CCS->videoh->close(); 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) void CClickableHex::hover(bool on)
{ {
hovered = on; hovered = on;

View File

@@ -98,17 +98,16 @@ public:
}; };
/// Class which manages the battle options window /// Class which manages the battle options window
class CBattleOptionsWindow : public WindowBase class CBattleOptionsWindow : public CWindowObject
{ {
private: private:
std::shared_ptr<CPicture> background;
std::shared_ptr<CButton> setToDefault; std::shared_ptr<CButton> setToDefault;
std::shared_ptr<CButton> exit; std::shared_ptr<CButton> exit;
std::shared_ptr<CToggleGroup> animSpeeds; std::shared_ptr<CToggleGroup> animSpeeds;
std::vector<std::shared_ptr<CLabel>> labels; std::vector<std::shared_ptr<CLabel>> labels;
std::vector<std::shared_ptr<CToggleButton>> toggles; std::vector<std::shared_ptr<CToggleButton>> toggles;
public: public:
CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface * owner); CBattleOptionsWindow(CBattleInterface * owner);
void bDefaultf(); //default button callback void bDefaultf(); //default button callback
void bExitf(); //exit 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) 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 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 //for user interactions
void hover (bool on) override; void hover (bool on) override;
void mouseMoved (const SDL_MouseMotionEvent &sEvent) 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) if (obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
continue; continue;
if (obstacle->obstacleType != CObstacleInstance::MOAT) if (obstacle->obstacleType == CObstacleInstance::MOAT)
continue; continue;
if ( obstacle->pos != location) 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 //no attacker stack, assume spell-related (earthquake) - only hit animation
for (auto attackInfo : ca.attackedParts) 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)); owner->stacksController->addNewAnim(new CEffectAnimation(owner, "SGEXPL.DEF", destPos.x, destPos.y));
} }

View File

@@ -18,7 +18,6 @@
#include "CBattleProjectileController.h" #include "CBattleProjectileController.h"
#include "CBattleControlPanel.h" #include "CBattleControlPanel.h"
#include "../gui/CAnimation.h" #include "../gui/CAnimation.h"
#include "../gui/SDL_Extensions.h"
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/CCanvas.h" #include "../gui/CCanvas.h"
#include "../../lib/battle/BattleHex.h" #include "../../lib/battle/BattleHex.h"
@@ -58,7 +57,14 @@ static void onAnimationFinished(const CStack *stack, std::weak_ptr<CCreatureAnim
} }
CBattleStacksController::CBattleStacksController(CBattleInterface * owner): 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 //preparing graphics for displaying amounts of creatures
amountNormal = IImage::createFromFile("CMNUMWIN.BMP"); amountNormal = IImage::createFromFile("CMNUMWIN.BMP");
@@ -66,10 +72,10 @@ CBattleStacksController::CBattleStacksController(CBattleInterface * owner):
amountNegative = IImage::createFromFile("CMNUMWIN.BMP"); amountNegative = IImage::createFromFile("CMNUMWIN.BMP");
amountEffNeutral = IImage::createFromFile("CMNUMWIN.BMP"); amountEffNeutral = IImage::createFromFile("CMNUMWIN.BMP");
ColorShifterAddMulExcept shifterNormal ({0,0,0,0}, {150, 48, 237, 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}, { 45, 255, 45, 255}, {132, 231, 255, 255}); ColorShifterAddMulExcept shifterPositive({0,0,0,0}, { 50, 255, 50, 255}, {255, 231, 132, 255});
ColorShifterAddMulExcept shifterNegative({0,0,0,0}, {255, 45, 45, 255}, {132, 231, 255, 255}); ColorShifterAddMulExcept shifterNegative({0,0,0,0}, {255, 50, 50, 255}, {255, 231, 132, 255});
ColorShifterAddMulExcept shifterNeutral ({0,0,0,0}, {255, 255, 45, 255}, {132, 231, 255, 255}); ColorShifterAddMulExcept shifterNeutral ({0,0,0,0}, {255, 255, 50, 255}, {255, 231, 132, 255});
amountNormal->adjustPalette(&shifterNormal); amountNormal->adjustPalette(&shifterNormal);
amountPositive->adjustPalette(&shifterPositive); amountPositive->adjustPalette(&shifterPositive);
@@ -119,8 +125,8 @@ void CBattleStacksController::showBattlefieldObjects(std::shared_ptr<CCanvas> ca
if (creAnims[stack->ID]->isDead()) if (creAnims[stack->ID]->isDead())
{ {
//if ( location == stack->getPosition() ) //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; continue;
} }
@@ -128,7 +134,7 @@ void CBattleStacksController::showBattlefieldObjects(std::shared_ptr<CCanvas> ca
if (!creAnims[stack->ID]->isMoving()) if (!creAnims[stack->ID]->isMoving())
{ {
if ( location == stack->getPosition() ) if ( location == stack->getPosition() )
{}; showStack(canvas, stack);
continue; continue;
} }
@@ -136,14 +142,14 @@ void CBattleStacksController::showBattlefieldObjects(std::shared_ptr<CCanvas> ca
if (stack->hasBonusOfType(Bonus::FLYING)) if (stack->hasBonusOfType(Bonus::FLYING))
{ {
if ( location == BattleHex::HEX_AFTER_ALL) if ( location == BattleHex::HEX_AFTER_ALL)
{}; showStack(canvas, stack);
continue; continue;
} }
// else - unit moving on ground // else - unit moving on ground
{ {
if ( location == getCurrentPosition(stack) ) if ( location == getCurrentPosition(stack) )
{}; showStack(canvas, stack);
continue; 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 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 if(stack->initialPosition < 0) //turret
{ {
@@ -396,7 +402,7 @@ void CBattleStacksController::stackRemoved(uint32_t stackID)
BattleAction *action = new BattleAction(); BattleAction *action = new BattleAction();
action->side = owner->defendingHeroInstance ? (owner->curInt->playerID == owner->defendingHeroInstance->tempOwner) : false; action->side = owner->defendingHeroInstance ? (owner->curInt->playerID == owner->defendingHeroInstance->tempOwner) : false;
action->actionType = EActionType::CANCEL; action->actionType = EActionType::CANCEL;
action->stackNumber = owner->stacksController->getActiveStack()->ID; action->stackNumber = getActiveStack()->ID;
owner->givenCommand.setn(action); owner->givenCommand.setn(action);
setActiveStack(nullptr); 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) bool CBattleStacksController::shouldRotate(const CStack * stack, const BattleHex & oldPos, const BattleHex & nextHex)
{ {
Point begPosition = CClickableHex::getXYUnitAnim(oldPos,stack, owner); Point begPosition = getStackPositionAtHex(oldPos,stack);
Point endPosition = CClickableHex::getXYUnitAnim(nextHex, stack, owner); Point endPosition = getStackPositionAtHex(nextHex, stack);
if((begPosition.x > endPosition.x) && facingRight(stack)) if((begPosition.x > endPosition.x) && facingRight(stack))
return true; return true;
@@ -510,7 +516,7 @@ void CBattleStacksController::activateStack()
setActiveStack(stackToActivate); setActiveStack(stackToActivate);
stackToActivate = nullptr; stackToActivate = nullptr;
const CStack * s = owner->stacksController->getActiveStack(); const CStack * s = getActiveStack();
if(!s) if(!s)
return; return;
@@ -565,3 +571,42 @@ SpellID CBattleStacksController::activeStackSpellToCast()
return SpellID::NONE; return SpellID::NONE;
return SpellID(creatureSpellToCast); 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 #pragma once
#include "../gui/Geometries.h"
struct BattleObjectsByHex; struct BattleObjectsByHex;
struct SDL_Surface; struct SDL_Surface;
struct BattleHex; struct BattleHex;
@@ -89,5 +91,8 @@ public:
const CStack* getActiveStack(); const CStack* getActiveStack();
const CStack* getSelectedStack(); 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 friend class CBattleAnimation; // for exposing pendingAnims/creAnims/creDir to animations
}; };

View File

@@ -13,7 +13,6 @@
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
#include "../../lib/CCreatureHandler.h" #include "../../lib/CCreatureHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../gui/CCanvas.h" #include "../gui/CCanvas.h"
static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 }; 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> template<int bpp>
int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect) 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; SDL_Color ignored;
public: public:
ColorShifterAddMulExcept(SDL_Color add, SDL_Color mul, SDL_Color ignored) : 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 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 * verticalFlip(SDL_Surface * toRot); //vertical flip
SDL_Surface * horizontalFlip(SDL_Surface * toRot); //horizontal flip SDL_Surface * horizontalFlip(SDL_Surface * toRot); //horizontal flip
Uint32 SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte = false); 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 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); Uint8 *getPxPtr(const SDL_Surface * const &srf, const int x, const int y);