2
0
Эх сурвалжийг харах

Bugfixing: fix crashes on battle start & most noticeable glitches

Ivan Savenko 2 жил өмнө
parent
commit
e76cd1b6a7

+ 21 - 1
client/CBitmapHandler.cpp

@@ -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;
 }
 

+ 9 - 10
client/battle/CBattleAnimations.cpp

@@ -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));

+ 20 - 4
client/battle/CBattleControlPanel.cpp

@@ -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()

+ 5 - 1
client/battle/CBattleControlPanel.h

@@ -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);
 };
+

+ 8 - 1
client/battle/CBattleFieldController.cpp

@@ -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()));
 

+ 17 - 31
client/battle/CBattleInterface.cpp

@@ -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);
 	}
 }
 

+ 2 - 2
client/battle/CBattleInterface.h

@@ -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);

+ 2 - 46
client/battle/CBattleInterfaceClasses.cpp

@@ -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;

+ 2 - 8
client/battle/CBattleInterfaceClasses.h

@@ -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;

+ 1 - 1
client/battle/CBattleObstacleController.cpp

@@ -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)

+ 1 - 1
client/battle/CBattleSiegeController.cpp

@@ -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));
 		}

+ 61 - 16
client/battle/CBattleStacksController.cpp

@@ -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();
+
+}

+ 5 - 0
client/battle/CBattleStacksController.h

@@ -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
 };

+ 0 - 1
client/battle/CCreatureAnimation.cpp

@@ -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 };

+ 0 - 18
client/gui/SDL_Extensions.cpp

@@ -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)
 {

+ 2 - 2
client/gui/SDL_Extensions.h

@@ -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);