Преглед изворни кода

Implemented teleportation animation effect

Ivan Savenko пре 2 година
родитељ
комит
e9e549148d

+ 1 - 1
AI/StupidAI/StupidAI.cpp

@@ -202,7 +202,7 @@ void CStupidAI::battleNewRound(int round)
 	print("battleNewRound called");
 }
 
-void CStupidAI::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance)
+void CStupidAI::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport)
 {
 	print("battleStackMoved called");
 }

+ 1 - 1
AI/StupidAI/StupidAI.h

@@ -36,7 +36,7 @@ public:
 	//void battleResultsApplied() override; //called when all effects of last battle are applied
 	void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied;
 	void battleNewRound(int round) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
-	void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) override;
+	void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport) override;
 	void battleSpellCast(const BattleSpellCast *sc) override;
 	void battleStacksEffectsSet(const SetStackEffect & sse) override;//called when a specific effect is set to stacks
 	//void battleTriggerEffect(const BattleTriggerEffect & bte) override;

+ 2 - 2
client/CPlayerInterface.cpp

@@ -913,12 +913,12 @@ void CPlayerInterface::battleLogMessage(const std::vector<MetaString> & lines)
 	battleInt->displayBattleLog(lines);
 }
 
-void CPlayerInterface::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance)
+void CPlayerInterface::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	BATTLE_EVENT_POSSIBLE_RETURN;
 
-	battleInt->stackMoved(stack, dest, distance);
+	battleInt->stackMoved(stack, dest, distance, teleport);
 }
 void CPlayerInterface::battleSpellCast( const BattleSpellCast *sc )
 {

+ 1 - 1
client/CPlayerInterface.h

@@ -193,7 +193,7 @@ public:
 	void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied; used for HP regen handling
 	void battleNewRound(int round) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
 	void battleLogMessage(const std::vector<MetaString> & lines) override;
-	void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) override;
+	void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport) override;
 	void battleSpellCast(const BattleSpellCast *sc) override;
 	void battleStacksEffectsSet(const SetStackEffect & sse) override; //called when a specific effect is set to stacks
 	void battleTriggerEffect(const BattleTriggerEffect & bte) override; //various one-shot effect

+ 1 - 1
client/NetPacksClient.cpp

@@ -738,7 +738,7 @@ void BattleResult::applyFirstCl(CClient *cl)
 void BattleStackMoved::applyFirstCl(CClient *cl)
 {
 	const CStack * movedStack = GS(cl)->curB->battleGetStackByID(stack);
-	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStackMoved, movedStack, tilesToMove, distance);
+	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStackMoved, movedStack, tilesToMove, distance, teleporting);
 }
 
 void BattleAttack::applyFirstCl(CClient *cl)

+ 29 - 9
client/battle/BattleAnimationClasses.cpp

@@ -331,11 +331,11 @@ bool MovementAnimation::init()
 {
 	assert(stack);
 	assert(!myAnim->isDeadOrDying());
+	assert(stackAnimation(stack)->framesInGroup(ECreatureAnimType::MOVING) > 0);
 
-	if(stackAnimation(stack)->framesInGroup(ECreatureAnimType::MOVING) == 0 ||
-	   stack->hasBonus(Selector::typeSubtype(Bonus::FLYING, 1)))
+	if(stackAnimation(stack)->framesInGroup(ECreatureAnimType::MOVING) == 0)
 	{
-		//no movement or teleport, end immediately
+		//no movement, end immediately
 		delete this;
 		return false;
 	}
@@ -576,6 +576,11 @@ ResurrectionAnimation::ResurrectionAnimation(BattleInterface & owner, const CSta
 	logAnim->debug("Created ResurrectionAnimation for %s", stack->getName());
 }
 
+bool ColorTransformAnimation::init()
+{
+	return true;
+}
+
 void ColorTransformAnimation::nextFrame()
 {
 	float elapsed  = GH.mainFPSmng->getElapsedMilliseconds() / 1000.f;
@@ -614,7 +619,7 @@ void ColorTransformAnimation::nextFrame()
 }
 
 ColorTransformAnimation::ColorTransformAnimation(BattleInterface & owner, const CStack * _stack, const CSpell * spell):
-	StackActionAnimation(owner, _stack),
+	BattleStackAnimation(owner, _stack),
 	spell(spell),
 	totalProgress(0.f)
 {
@@ -658,23 +663,38 @@ ColorTransformAnimation * ColorTransformAnimation::petrifyAnimation(BattleInterf
 	return result;
 }
 
-ColorTransformAnimation * ColorTransformAnimation::fadeInAnimation(BattleInterface & owner, const CStack * stack)
+ColorTransformAnimation * ColorTransformAnimation::summonAnimation(BattleInterface & owner, const CStack * stack)
+{
+	auto result = teleportInAnimation(owner, stack);
+	result->timePoints.back() = 1.0f;
+	return result;
+}
+
+
+ColorTransformAnimation * ColorTransformAnimation::teleportInAnimation(BattleInterface & owner, const CStack * stack)
 {
 	auto result = new ColorTransformAnimation(owner, stack, nullptr);
 	result->steps.push_back(ColorFilter::genAlphaShifter(0.f));
 	result->steps.push_back(ColorFilter::genEmptyShifter());
-	result->timePoints.push_back(0.f);
-	result->timePoints.push_back(1.f);
+	result->timePoints.push_back(0.0f);
+	result->timePoints.push_back(0.2f);
 	return result;
 }
 
-ColorTransformAnimation * ColorTransformAnimation::fadeOutAnimation(BattleInterface & owner, const CStack * stack)
+ColorTransformAnimation * ColorTransformAnimation::teleportOutAnimation(BattleInterface & owner, const CStack * stack)
 {
-	auto result = fadeInAnimation(owner, stack);
+	auto result = teleportInAnimation(owner, stack);
 	std::swap(result->steps[0], result->steps[1]);
 	return result;
 }
 
+ColorTransformAnimation * ColorTransformAnimation::fadeOutAnimation(BattleInterface & owner, const CStack * stack)
+{
+	auto result = teleportOutAnimation(owner, stack);
+	result->timePoints.back() = 1.0f;
+	return result;
+}
+
 RangedAttackAnimation::RangedAttackAnimation(BattleInterface & owner_, const CStack * attacker, BattleHex dest_, const CStack * defender)
 	: AttackAnimation(owner_, attacker, dest_, defender),
 	  projectileEmitted(false)

+ 9 - 6
client/battle/BattleAnimationClasses.h

@@ -112,7 +112,7 @@ public:
 	ResurrectionAnimation(BattleInterface & owner, const CStack * _stack);
 };
 
-class ColorTransformAnimation : public StackActionAnimation
+class ColorTransformAnimation : public BattleStackAnimation
 {
 	std::vector<ColorFilter> steps;
 	std::vector<float> timePoints;
@@ -120,16 +120,19 @@ class ColorTransformAnimation : public StackActionAnimation
 
 	float totalProgress;
 
+	bool init() override;
 	void nextFrame() override;
 
 	ColorTransformAnimation(BattleInterface & owner, const CStack * _stack, const CSpell * spell);
 public:
 
-	static ColorTransformAnimation * petrifyAnimation  (BattleInterface & owner, const CStack * _stack, const CSpell * spell);
-	static ColorTransformAnimation * cloneAnimation    (BattleInterface & owner, const CStack * _stack, const CSpell * spell);
-	static ColorTransformAnimation * bloodlustAnimation(BattleInterface & owner, const CStack * _stack, const CSpell * spell);
-	static ColorTransformAnimation * fadeInAnimation   (BattleInterface & owner, const CStack * _stack);
-	static ColorTransformAnimation * fadeOutAnimation  (BattleInterface & owner, const CStack * _stack);
+	static ColorTransformAnimation * petrifyAnimation     (BattleInterface & owner, const CStack * _stack, const CSpell * spell);
+	static ColorTransformAnimation * cloneAnimation       (BattleInterface & owner, const CStack * _stack, const CSpell * spell);
+	static ColorTransformAnimation * bloodlustAnimation   (BattleInterface & owner, const CStack * _stack, const CSpell * spell);
+	static ColorTransformAnimation * summonAnimation      (BattleInterface & owner, const CStack * _stack);
+	static ColorTransformAnimation * fadeOutAnimation     (BattleInterface & owner, const CStack * _stack);
+	static ColorTransformAnimation * teleportInAnimation  (BattleInterface & owner, const CStack * _stack);
+	static ColorTransformAnimation * teleportOutAnimation (BattleInterface & owner, const CStack * _stack);
 };
 
 /// Base class for all animations that play during stack movement

+ 5 - 2
client/battle/BattleInterface.cpp

@@ -335,9 +335,12 @@ void BattleInterface::stackActivated(const CStack *stack)
 	stacksController->stackActivated(stack);
 }
 
-void BattleInterface::stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance)
+void BattleInterface::stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance, bool teleport)
 {
-	stacksController->stackMoved(stack, destHex, distance);
+	if (teleport)
+		stacksController->stackTeleported(stack, destHex, distance);
+	else
+		stacksController->stackMoved(stack, destHex, distance);
 }
 
 void BattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos)

+ 1 - 1
client/battle/BattleInterface.h

@@ -197,7 +197,7 @@ public:
 	void stackAdded(const CStack * stack); //new stack appeared on battlefield
 	void stackRemoved(uint32_t stackID); //stack disappeared from batlefiled
 	void stackActivated(const CStack *stack); //active stack has been changed
-	void stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance); //stack with id number moved to destHex
+	void stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance, bool teleport); //stack with id number moved to destHex
 	void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
 	void stackAttacking(const StackAttackInfo & attackInfo); //called when stack with id ID is attacking something on hex dest
 	void newRoundFirst( int round );

+ 25 - 4
client/battle/BattleStacksController.cpp

@@ -223,7 +223,7 @@ void BattleStacksController::stackAdded(const CStack * stack, bool instant)
 
 		owner.executeOnAnimationCondition(EAnimationEvents::HIT, true, [=]()
 		{
-			addNewAnim(ColorTransformAnimation::fadeInAnimation(owner, stack));
+			addNewAnim(ColorTransformAnimation::summonAnimation(owner, stack));
 			if (stack->isClone())
 				addNewAnim(ColorTransformAnimation::cloneAnimation(owner, stack, SpellID(SpellID::CLONE).toSpell()));
 		});
@@ -472,6 +472,23 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
 	executeAttackAnimations();
 }
 
+void BattleStacksController::stackTeleported(const CStack *stack, std::vector<BattleHex> destHex, int distance)
+{
+	assert(destHex.size() > 0);
+	assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
+
+	owner.executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
+		addNewAnim( ColorTransformAnimation::teleportOutAnimation(owner, stack) );
+	});
+
+	owner.executeOnAnimationCondition(EAnimationEvents::AFTER_HIT, true, [=](){
+		stackAnimation[stack->ID]->pos.moveTo(getStackPositionAtHex(destHex.back(), stack));
+		addNewAnim( ColorTransformAnimation::teleportInAnimation(owner, stack) );
+	});
+
+	// animations will be executed by spell
+}
+
 void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance)
 {
 	assert(destHex.size() > 0);
@@ -486,8 +503,12 @@ void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleH
 	addNewAnim(new MovementStartAnimation(owner, stack));
 	owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
 
-	addNewAnim(new MovementAnimation(owner, stack, destHex, distance));
-	owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
+	// if creature can teleport, e.g Devils - skip movement animation
+	if ( !stack->hasBonus(Selector::typeSubtype(Bonus::FLYING, 1)) )
+	{
+		addNewAnim(new MovementAnimation(owner, stack, destHex, distance));
+		owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
+	}
 
 	addNewAnim(new MovementEndAnimation(owner, stack, destHex.back()));
 	owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
@@ -806,7 +827,7 @@ void BattleStacksController::removeExpiredColorFilters()
 			return false;
 		if (filter.effect == ColorFilter::genEmptyShifter())
 			return false;
-		if (filter.target->hasBonus(Selector::source(Bonus::SPELL_EFFECT, filter.source->id)))
+		if (filter.source && filter.target->hasBonus(Selector::source(Bonus::SPELL_EFFECT, filter.source->id)))
 			return false;
 		return true;
 	});

+ 1 - 0
client/battle/BattleStacksController.h

@@ -113,6 +113,7 @@ public:
 	void stackRemoved(uint32_t stackID); //stack disappeared from batlefiled
 	void stackActivated(const CStack *stack); //active stack has been changed
 	void stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance); //stack with id number moved to destHex
+	void stackTeleported(const CStack *stack, std::vector<BattleHex> destHex, int distance); //stack with id number moved to destHex
 	void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
 	void stackAttacking(const StackAttackInfo & info); //called when stack with id ID is attacking something on hex dest
 

+ 2 - 2
lib/CGameInterface.cpp

@@ -204,9 +204,9 @@ void CAdventureAI::battleObstaclesChanged(const std::vector<ObstacleChanges> & o
 	battleAI->battleObstaclesChanged(obstacles);
 }
 
-void CAdventureAI::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance)
+void CAdventureAI::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport)
 {
-	battleAI->battleStackMoved(stack, dest, distance);
+	battleAI->battleStackMoved(stack, dest, distance, teleport);
 }
 
 void CAdventureAI::battleAttack(const BattleAttack * ba)

+ 1 - 1
lib/CGameInterface.h

@@ -160,7 +160,7 @@ public:
 	virtual void actionFinished(const BattleAction &action) override;
 	virtual void battleStacksEffectsSet(const SetStackEffect & sse) override;
 	virtual void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles) override;
-	virtual void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) override;
+	virtual void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport) override;
 	virtual void battleAttack(const BattleAttack *ba) override;
 	virtual void battleSpellCast(const BattleSpellCast *sc) override;
 	virtual void battleEnd(const BattleResult *br) override;

+ 1 - 1
lib/IGameEventsReceiver.h

@@ -63,7 +63,7 @@ public:
 	virtual void battleNewRoundFirst(int round){}; //called at the beginning of each turn before changes are applied;
 	virtual void battleNewRound(int round){}; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
 	virtual void battleLogMessage(const std::vector<MetaString> & lines){};
-	virtual void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance){};
+	virtual void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance, bool teleport){};
 	virtual void battleSpellCast(const BattleSpellCast *sc){};
 	virtual void battleStacksEffectsSet(const SetStackEffect & sse){};//called when a specific effect is set to stacks
 	virtual void battleTriggerEffect(const BattleTriggerEffect & bte){}; //called for various one-shot effects

+ 1 - 0
lib/NetPacks.h

@@ -1545,6 +1545,7 @@ struct BattleStackMoved : public CPackForClient
 		h & stack;
 		h & tilesToMove;
 		h & distance;
+		h & teleporting;
 	}
 };