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:
		| @@ -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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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)); | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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())); | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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)); | ||||
| 		} | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
| }; | ||||
|   | ||||
| @@ -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 }; | ||||
|   | ||||
| @@ -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) | ||||
| { | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user