Explorar el Código

Merge pull request #1792 from IvanSavenko/happy_dydzio

Fixes for beta - graphical artifacts
Ivan Savenko hace 2 años
padre
commit
974be97e6d

+ 0 - 1
Mods/vcmi/mod.json

@@ -38,7 +38,6 @@
 		"name" : "Ключевые файлы VCMI",
 		"description" : "Файлы, необходимые для полноценной работы VCMI",
 		"author" : "Команда VCMI",
-		"modType" : "Графический",
 
 		"skipValidation" : true,
 		"translations" : [

+ 1 - 1
client/CPlayerInterface.cpp

@@ -2033,7 +2033,7 @@ bool CPlayerInterface::capturedAllEvents()
 		return true;
 	}
 
-	bool needToLockAdventureMap = adventureInt->active && CGI->mh->hasOngoingAnimations();
+	bool needToLockAdventureMap = adventureInt && adventureInt->active && CGI->mh->hasOngoingAnimations();
 
 	if (ignoreEvents || needToLockAdventureMap)
 	{

+ 2 - 2
client/battle/BattleActionsController.cpp

@@ -694,14 +694,14 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
 				if (action.spell() == SpellID::SACRIFICE)
 				{
 					heroSpellToCast->aimToHex(targetHex);
-					possibleActions.push_back(PossiblePlayerBattleAction::SACRIFICE);
+					possibleActions.push_back({PossiblePlayerBattleAction::SACRIFICE, action.spell()});
 					owner.stacksController->setSelectedStack(targetStack);
 					return;
 				}
 				if (action.spell() == SpellID::TELEPORT)
 				{
 					heroSpellToCast->aimToUnit(targetStack);
-					possibleActions.push_back(PossiblePlayerBattleAction::TELEPORT);
+					possibleActions.push_back({PossiblePlayerBattleAction::TELEPORT, action.spell()});
 					owner.stacksController->setSelectedStack(targetStack);
 					return;
 				}

+ 10 - 11
client/battle/BattleFieldController.cpp

@@ -35,8 +35,6 @@
 #include "../../lib/CStack.h"
 #include "../../lib/spells/ISpellMechanics.h"
 
-#include <SDL_events.h>
-
 BattleFieldController::BattleFieldController(BattleInterface & owner):
 	owner(owner)
 {
@@ -67,10 +65,7 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
 
 	backgroundWithHexes = std::make_unique<Canvas>(Point(background->width(), background->height()));
 
-	auto accessibility = owner.curInt->cb->getAccesibility();
-	for(int i = 0; i < accessibility.size(); i++)
-		stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
-
+	updateAccessibleHexes();
 	addUsedEvents(LCLICK | RCLICK | MOVE);
 	LOCPLINT->cingconsole->pos = this->pos;
 }
@@ -180,11 +175,6 @@ void BattleFieldController::redrawBackgroundWithHexes()
 	if (activeStack)
 		occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes);
 
-	auto accessibility = owner.curInt->cb->getAccesibility();
-
-	for(int i = 0; i < accessibility.size(); i++)
-		stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
-
 	//prepare background graphic with hexes and shaded hexes
 	backgroundWithHexes->draw(background, Point(0,0));
 	owner.obstacleController->showAbsoluteObstacles(*backgroundWithHexes);
@@ -579,6 +569,14 @@ bool BattleFieldController::isTileAttackable(const BattleHex & number) const
 	return false;
 }
 
+void BattleFieldController::updateAccessibleHexes()
+{
+	auto accessibility = owner.curInt->cb->getAccesibility();
+
+	for(int i = 0; i < accessibility.size(); i++)
+		stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE || (accessibility[i] == EAccessibility::SIDE_COLUMN));
+}
+
 bool BattleFieldController::stackCountOutsideHex(const BattleHex & number) const
 {
 	return stackCountOutsideHexes[number];
@@ -591,6 +589,7 @@ void BattleFieldController::showAll(SDL_Surface * to)
 
 void BattleFieldController::show(SDL_Surface * to)
 {
+	updateAccessibleHexes();
 	owner.stacksController->update();
 	owner.obstacleController->update();
 

+ 1 - 0
client/battle/BattleFieldController.h

@@ -56,6 +56,7 @@ class BattleFieldController : public CIntObject
 	void showBackgroundImage(Canvas & canvas);
 	void showBackgroundImageWithHexes(Canvas & canvas);
 	void showHighlightedHexes(Canvas & canvas);
+	void updateAccessibleHexes();
 
 	BattleHex::EDir selectAttackDirection(BattleHex myNumber, const Point & point);
 

+ 44 - 22
client/battle/BattleStacksController.cpp

@@ -267,12 +267,8 @@ bool BattleStacksController::stackNeedsAmountBox(const CStack * stack) const
 		return false;
 
 	// if stack has any ongoing animation - hide the box
-	for(auto anim : currentAnimations)
-	{
-		auto stackAnimation = dynamic_cast<BattleStackAnimation*>(anim);
-		if(stackAnimation && (stackAnimation->stack->ID == stack->ID))
-			return false;
-	}
+	if (stackAmountBoxHidden.count(stack->ID))
+		return false;
 
 	return true;
 }
@@ -300,26 +296,42 @@ std::shared_ptr<IImage> BattleStacksController::getStackAmountBox(const CStack *
 
 void BattleStacksController::showStackAmountBox(Canvas & canvas, const CStack * stack)
 {
-	//blitting amount background box
 	auto amountBG = getStackAmountBox(stack);
 
-	const int sideShift = stack->side == BattleSide::ATTACKER ? 1 : -1;
-	const int reverseSideShift = stack->side == BattleSide::ATTACKER ? -1 : 1;
-	const BattleHex nextPos = stack->getPosition() + sideShift;
-	const bool edge = stack->getPosition() % GameConstants::BFIELD_WIDTH == (stack->side == BattleSide::ATTACKER ? GameConstants::BFIELD_WIDTH - 2 : 1);
-	const bool moveInside = !edge && !owner.fieldController->stackCountOutsideHex(nextPos);
+	bool doubleWide = stack->doubleWide();
+	bool turnedRight = facingRight(stack);
+	bool attacker = stack->side == BattleSide::ATTACKER;
+
+	BattleHex stackPos = stack->getPosition();
 
-	int xAdd = (stack->side == BattleSide::ATTACKER ? 220 : 202) +
-			(stack->doubleWide() ? 44 : 0) * sideShift +
-			(moveInside ? amountBG->width() + 10 : 0) * reverseSideShift;
-	int yAdd = 260 + ((stack->side == BattleSide::ATTACKER || moveInside) ? 0 : -15);
+	// double-wide unit turned around - use opposite hex for stack label
+	if (doubleWide && turnedRight != attacker)
+		stackPos = stack->occupiedHex();
 
-	canvas.draw(amountBG, stackAnimation[stack->ID]->pos.topLeft() + Point(xAdd, yAdd));
+	BattleHex frontPos = turnedRight ?
+		stackPos.cloneInDirection(BattleHex::RIGHT) :
+		stackPos.cloneInDirection(BattleHex::LEFT);
+
+	bool moveInside = !owner.fieldController->stackCountOutsideHex(frontPos);
+
+	Point boxPosition;
+
+	if (moveInside)
+	{
+		boxPosition = owner.fieldController->hexPositionLocal(stackPos).center() + Point(-15, 1);
+	}
+	else
+	{
+		if (turnedRight)
+			boxPosition = owner.fieldController->hexPositionLocal(frontPos).center() + Point (-22, 1);
+		else
+			boxPosition = owner.fieldController->hexPositionLocal(frontPos).center() + Point(-8, -14);
+	}
 
-	//blitting amount
-	Point textPos = stackAnimation[stack->ID]->pos.topLeft() + amountBG->dimensions()/2 + Point(xAdd, yAdd);
+	Point textPosition = amountBG->dimensions()/2 + boxPosition;
 
-	canvas.drawText(textPos, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, TextOperations::formatMetric(stack->getCount(), 4));
+	canvas.draw(amountBG, boxPosition);
+	canvas.drawText(textPosition, EFonts::FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, TextOperations::formatMetric(stack->getCount(), 4));
 }
 
 void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
@@ -368,6 +380,7 @@ void BattleStacksController::updateBattleAnimations()
 
 	if (hadAnimations && currentAnimations.empty())
 	{
+		//stackAmountBoxHidden.clear();
 		owner.executeStagedAnimations();
 		if (currentAnimations.empty())
 			owner.onAnimationsFinished();
@@ -378,8 +391,15 @@ void BattleStacksController::updateBattleAnimations()
 
 void BattleStacksController::addNewAnim(BattleAnimation *anim)
 {
+	if (currentAnimations.empty())
+		stackAmountBoxHidden.clear();
+
 	owner.onAnimationsStarted();
 	currentAnimations.push_back(anim);
+
+	auto stackAnimation = dynamic_cast<BattleStackAnimation*>(anim);
+	if(stackAnimation)
+		stackAmountBoxHidden.insert(stackAnimation->stack->ID);
 }
 
 void BattleStacksController::stackRemoved(uint32_t stackID)
@@ -668,6 +688,8 @@ void BattleStacksController::endAction(const BattleAction* action)
 	owner.executeStagedAnimations();
 	owner.waitForAnimations();
 
+	stackAmountBoxHidden.clear();
+
 	owner.windowObject->blockUI(activeStack == nullptr);
 	removeExpiredColorFilters();
 }
@@ -738,8 +760,8 @@ Point BattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CSta
 	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
+	static const Point basePos(-189, -139); // position of creature in topleft corner
+	static const int imageShiftX = 29; // 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();

+ 3 - 0
client/battle/BattleStacksController.h

@@ -67,6 +67,9 @@ class BattleStacksController
 	/// <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
 	std::map<int, bool> stackFacingRight;
 
+	/// Stacks have amount box hidden due to ongoing animations
+	std::set<int> stackAmountBoxHidden;
+
 	/// currently active stack; nullptr - no one
 	const CStack *activeStack;
 

+ 4 - 2
client/mapView/MapView.cpp

@@ -66,16 +66,18 @@ void BasicMapView::render(Canvas & target, bool fullUpdate)
 
 void BasicMapView::show(SDL_Surface * to)
 {
-	controller->update(GH.mainFPSmng->getElapsedMilliseconds());
+	controller->updateBefore(GH.mainFPSmng->getElapsedMilliseconds());
 
 	Canvas target(to);
 	CSDL_Ext::CClipRectGuard guard(to, pos);
 	render(target, false);
+
+	controller->updateAfter(GH.mainFPSmng->getElapsedMilliseconds());
 }
 
 void BasicMapView::showAll(SDL_Surface * to)
 {
-	controller->update(0);
+	controller->updateBefore(0);
 
 	Canvas target(to);
 	CSDL_Ext::CClipRectGuard guard(to, pos);

+ 48 - 30
client/mapView/MapViewController.cpp

@@ -88,7 +88,7 @@ std::shared_ptr<IMapRendererContext> MapViewController::getContext() const
 	return context;
 }
 
-void MapViewController::update(uint32_t timeDelta)
+void MapViewController::updateBefore(uint32_t timeDelta)
 {
 	// confirmed to match H3 for
 	// - hero embarking on boat (500 ms)
@@ -116,56 +116,32 @@ void MapViewController::update(uint32_t timeDelta)
 			settings["adventure"]["enemyMoveTime"].Float();
 
 		movementContext->progress += timeDelta / heroMoveTime;
+		movementContext->progress = std::min( 1.0, movementContext->progress);
 
 		Point positionFrom = Point(hero->convertToVisitablePos(movementContext->tileFrom)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
 		Point positionDest = Point(hero->convertToVisitablePos(movementContext->tileDest)) * model->getSingleTileSize() + model->getSingleTileSize() / 2;
 
 		Point positionCurr = vstd::lerp(positionFrom, positionDest, movementContext->progress);
 
-		if(movementContext->progress >= 1.0)
-		{
-			setViewCenter(hero->getSightCenter());
-
-			removeObject(context->getObject(movementContext->target));
-			addObject(context->getObject(movementContext->target));
-
-			activateAdventureContext(movementContext->animationTime);
-		}
-		else
-		{
-			setViewCenter(positionCurr, movementContext->tileDest.z);
-		}
+		setViewCenter(positionCurr, movementContext->tileDest.z);
 	}
 
 	if(teleportContext)
 	{
 		teleportContext->progress += timeDelta / heroTeleportDuration;
-		if(teleportContext->progress >= 1.0)
-		{
-			activateAdventureContext(teleportContext->animationTime);
-		}
+		teleportContext->progress = std::min( 1.0, teleportContext->progress);
 	}
 
 	if(fadingOutContext)
 	{
 		fadingOutContext->progress -= timeDelta / fadeOutDuration;
-
-		if(fadingOutContext->progress <= 0.0)
-		{
-			removeObject(context->getObject(fadingOutContext->target));
-
-			activateAdventureContext(fadingOutContext->animationTime);
-		}
+		fadingOutContext->progress = std::max( 0.0, fadingOutContext->progress);
 	}
 
 	if(fadingInContext)
 	{
 		fadingInContext->progress += timeDelta / fadeInDuration;
-
-		if(fadingInContext->progress >= 1.0)
-		{
-			activateAdventureContext(fadingInContext->animationTime);
-		}
+		fadingInContext->progress = std::min( 1.0, fadingInContext->progress);
 	}
 
 	if(adventureContext)
@@ -180,6 +156,48 @@ void MapViewController::update(uint32_t timeDelta)
 	}
 }
 
+void MapViewController::updateAfter(uint32_t timeDelta)
+{
+	if(movementContext)
+	{
+		const auto * object = context->getObject(movementContext->target);
+		const auto * hero = dynamic_cast<const CGHeroInstance *>(object);
+		const auto * boat = dynamic_cast<const CGBoat *>(object);
+
+		assert(boat || hero);
+
+		if(!hero)
+			hero = boat->hero;
+
+		if(movementContext->progress >= 1.0)
+		{
+			setViewCenter(hero->getSightCenter());
+
+			removeObject(context->getObject(movementContext->target));
+			addObject(context->getObject(movementContext->target));
+
+			activateAdventureContext(movementContext->animationTime);
+		}
+	}
+
+	if(teleportContext && teleportContext->progress >= 1.0)
+	{
+		activateAdventureContext(teleportContext->animationTime);
+	}
+
+	if(fadingOutContext && fadingOutContext->progress <= 0.0)
+	{
+		removeObject(context->getObject(fadingOutContext->target));
+
+		activateAdventureContext(fadingOutContext->animationTime);
+	}
+
+	if(fadingInContext && fadingInContext->progress >= 1.0)
+	{
+		activateAdventureContext(fadingInContext->animationTime);
+	}
+}
+
 bool MapViewController::isEventVisible(const CGObjectInstance * obj)
 {
 	if(adventureContext == nullptr)

+ 2 - 1
client/mapView/MapViewController.h

@@ -83,7 +83,8 @@ public:
 	void setViewCenter(const int3 & position);
 	void setViewCenter(const Point & position, int level);
 	void setTileSize(const Point & tileSize);
-	void update(uint32_t timeDelta);
+	void updateBefore(uint32_t timeDelta);
+	void updateAfter(uint32_t timeDelta);
 
 	void activateAdventureContext(uint32_t animationTime);
 	void activateAdventureContext();