Przeglądaj źródła

All battle effects are now fully client sided

Ivan Savenko 3 lat temu
rodzic
commit
deffba01b9

+ 2 - 7
client/CPlayerInterface.cpp

@@ -707,7 +707,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
 	BATTLE_EVENT_POSSIBLE_RETURN;
 }
 
-void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects)
+void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	BATTLE_EVENT_POSSIBLE_RETURN;
@@ -747,8 +747,6 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units
 			break;
 		}
 	}
-
-	battleInt->effectsController->displayCustomEffects(customEffects);
 }
 
 void CPlayerInterface::battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles)
@@ -962,15 +960,12 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
 		info.attacker       = attacker;
 		info.damageDealt    = elem.damageAmount;
 		info.amountKilled   = elem.killedAmount;
-		info.battleEffect   = EBattleEffect::INVALID;
 		info.spellEffect    = SpellID::NONE;
 		info.indirectAttack = ranged;
 		info.killed         = elem.killed();
 		info.rebirth        = elem.willRebirth();
 		info.cloneKilled    = elem.cloneKilled();
-
-		if(elem.isEffect() && !elem.isSecondary())
-			info.battleEffect = EBattleEffect::EBattleEffect(elem.effect);
+		info.fireShield    = elem.fireShield();
 
 		if (elem.isSpell())
 			info.spellEffect = elem.spellID;

+ 1 - 1
client/CPlayerInterface.h

@@ -200,7 +200,7 @@ public:
 	void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged) override;
 	void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) override; //called by engine just before battle starts; side=0 - left, side=1 - right
 	void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right
-	void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects) override;
+	void battleUnitsChanged(const std::vector<UnitChanges> & units) override;
 	void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles) override;
 	void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
 	void battleGateStateChanged(const EGateState state) override;

+ 1 - 1
client/NetPacksClient.cpp

@@ -782,7 +782,7 @@ void BattleResultsApplied::applyCl(CClient *cl)
 
 void BattleUnitsChanged::applyCl(CClient * cl)
 {
-	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, changedStacks, customEffects);
+	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, changedStacks);
 }
 
 void BattleObstaclesChanged::applyCl(CClient *cl)

+ 21 - 21
client/battle/BattleConstants.h

@@ -9,6 +9,27 @@
  */
 #pragma once
 
+enum class EBattleEffect
+{
+	// list of battle effects that have hardcoded triggers
+	MAGIC_MIRROR = 3,
+	FIRE_SHIELD  = 11,
+	FEAR         = 15,
+	GOOD_LUCK    = 18,
+	GOOD_MORALE  = 20,
+	BAD_MORALE   = 30,
+	BAD_LUCK     = 48,
+	RESURRECT    = 50,
+	DRAIN_LIFE   = 52,
+	POISON       = 67,
+	DEATH_BLOW   = 73,
+	REGENERATION = 74,
+	MANA_DRAIN   = 77,
+	RESISTANCE   = 78,
+
+	INVALID      = -1,
+};
+
 enum class EAnimationEvents {
 	OPENING     = 0, // TODO battle opening sound is playing
 	ACTION      = 1, // there are any ongoing animations
@@ -22,27 +43,6 @@ enum class EAnimationEvents {
 	COUNT
 };
 
-namespace EBattleEffect
-{
-	enum EBattleEffect
-	{
-		// list of battle effects that have hardcoded triggers
-		FEAR         = 15,
-		GOOD_LUCK    = 18,
-		GOOD_MORALE  = 20,
-		BAD_MORALE   = 30,
-		BAD_LUCK     = 48,
-		RESURRECT    = 50,
-		DRAIN_LIFE   = 52,
-		POISON       = 67,
-		DEATH_BLOW   = 73,
-		REGENERATION = 74,
-		MANA_DRAIN   = 77,
-
-		INVALID      = -1,
-	};
-}
-
 enum class EHeroAnimType
 {
 	HOLDING    = 0,

+ 5 - 16
client/battle/BattleEffectsController.cpp

@@ -35,29 +35,18 @@ BattleEffectsController::BattleEffectsController(BattleInterface & owner):
 	owner(owner)
 {}
 
-void BattleEffectsController::displayEffect(EBattleEffect::EBattleEffect effect, const BattleHex & destTile)
+void BattleEffectsController::displayEffect(EBattleEffect effect, const BattleHex & destTile)
 {
 	displayEffect(effect, soundBase::invalid, destTile);
 }
 
-void BattleEffectsController::displayEffect(EBattleEffect::EBattleEffect effect, uint32_t soundID, const BattleHex & destTile)
+void BattleEffectsController::displayEffect(EBattleEffect effect, uint32_t soundID, const BattleHex & destTile)
 {
-	std::string customAnim = graphics->battleACToDef[effect][0];
+	size_t effectID = static_cast<size_t>(effect);
 
-	owner.stacksController->addNewAnim(new PointEffectAnimation(owner, soundBase::stringsList()[soundID], customAnim, destTile));
-}
-
-void BattleEffectsController::displayCustomEffects(const std::vector<CustomEffectInfo> & customEffects)
-{
-	for(const CustomEffectInfo & one : customEffects)
-	{
-		const CStack * s = owner.curInt->cb->battleGetStackByID(one.stack, false);
-
-		assert(s);
-		assert(one.effect != 0);
+	std::string customAnim = graphics->battleACToDef[effectID][0];
 
-		displayEffect(EBattleEffect::EBattleEffect(one.effect), soundBase::soundID(one.sound), s->getPosition());
-	}
+	owner.stacksController->addNewAnim(new PointEffectAnimation(owner, soundBase::stringsList()[soundID], customAnim, destTile));
 }
 
 void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte)

+ 2 - 5
client/battle/BattleEffectsController.h

@@ -15,7 +15,6 @@
 VCMI_LIB_NAMESPACE_BEGIN
 
 class BattleAction;
-struct CustomEffectInfo;
 struct BattleTriggerEffect;
 
 VCMI_LIB_NAMESPACE_END
@@ -49,11 +48,9 @@ public:
 
 	void startAction(const BattleAction* action);
 
-	void displayCustomEffects(const std::vector<CustomEffectInfo> & customEffects);
-
 	//displays custom effect on the battlefield
-	void displayEffect(EBattleEffect::EBattleEffect effect, const BattleHex & destTile);
-	void displayEffect(EBattleEffect::EBattleEffect effect, uint32_t soundID, const BattleHex & destTile);
+	void displayEffect(EBattleEffect effect, const BattleHex & destTile);
+	void displayEffect(EBattleEffect effect, uint32_t soundID, const BattleHex & destTile);
 
 	void battleTriggerEffect(const BattleTriggerEffect & bte);
 

+ 14 - 9
client/battle/BattleInterface.cpp

@@ -550,17 +550,22 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
 		}
 	}
 
-	//queuing additional animation (magic mirror / resistance)
-	for(auto & elem : sc->customEffects)
+	for(auto & elem : sc->reflectedCres)
 	{
-		auto stack = curInt->cb->battleGetStackByID(elem.stack, false);
+		auto stack = curInt->cb->battleGetStackByID(elem, false);
 		assert(stack);
-		if(stack)
-		{
-			executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
-				effectsController->displayEffect(EBattleEffect::EBattleEffect(elem.effect), stack->getPosition());
-			});
-		}
+		executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
+			effectsController->displayEffect(EBattleEffect::MAGIC_MIRROR, stack->getPosition());
+		});
+	}
+
+	for(auto & elem : sc->resistedCres)
+	{
+		auto stack = curInt->cb->battleGetStackByID(elem, false);
+		assert(stack);
+		executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
+			effectsController->displayEffect(EBattleEffect::RESISTANCE, stack->getPosition());
+		});
 	}
 
 	//mana absorption

+ 1 - 4
client/battle/BattleInterface.h

@@ -29,7 +29,6 @@ struct CatapultAttack;
 struct BattleTriggerEffect;
 struct BattleHex;
 struct InfoAboutHero;
-struct CustomEffectInfo;
 
 VCMI_LIB_NAMESPACE_END
 
@@ -62,14 +61,13 @@ struct StackAttackedInfo
 
 	int64_t  damageDealt;
 	uint32_t amountKilled;
-
-	EBattleEffect::EBattleEffect battleEffect;
 	SpellID spellEffect;
 
 	bool indirectAttack; //if true, stack was attacked indirectly - spell or ranged attack
 	bool killed; //if true, stack has been killed
 	bool rebirth; //if true, play rebirth animation after all
 	bool cloneKilled;
+	bool fireShield;
 };
 
 struct StackAttackInfo
@@ -78,7 +76,6 @@ struct StackAttackInfo
 	const CStack *defender;
 	std::vector< const CStack *> secondaryDefender;
 
-	//EBattleEffect::EBattleEffect battleEffect;
 	SpellID spellEffect;
 	BattleHex tile;
 

+ 2 - 2
client/battle/BattleStacksController.cpp

@@ -444,8 +444,8 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
 			else
 				addNewAnim(new HittedAnimation(owner, attackedInfo.defender));
 
-			if (attackedInfo.battleEffect != EBattleEffect::INVALID)
-				owner.effectsController->displayEffect(EBattleEffect::EBattleEffect(attackedInfo.battleEffect), attackedInfo.defender->getPosition());
+			if (attackedInfo.fireShield)
+				owner.effectsController->displayEffect(EBattleEffect::FIRE_SHIELD, attackedInfo.attacker->getPosition());
 
 			if (attackedInfo.spellEffect != SpellID::NONE)
 				owner.displaySpellEffect(attackedInfo.spellEffect, attackedInfo.defender->getPosition());

+ 2 - 2
lib/CGameInterface.cpp

@@ -225,9 +225,9 @@ void CAdventureAI::battleEnd(const BattleResult * br)
 	battleAI.reset();
 }
 
-void CAdventureAI::battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects)
+void CAdventureAI::battleUnitsChanged(const std::vector<UnitChanges> & units)
 {
-	battleAI->battleUnitsChanged(units, customEffects);
+	battleAI->battleUnitsChanged(units);
 }
 
 BattleAction CAdventureAI::activeStack(const CStack * stack)

+ 1 - 1
lib/CGameInterface.h

@@ -164,7 +164,7 @@ public:
 	virtual void battleAttack(const BattleAttack *ba) override;
 	virtual void battleSpellCast(const BattleSpellCast *sc) override;
 	virtual void battleEnd(const BattleResult *br) override;
-	virtual void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects) override;
+	virtual void battleUnitsChanged(const std::vector<UnitChanges> & units) override;
 
 	virtual void saveGame(BinarySerializer & h, const int version) override;
 	virtual void loadGame(BinaryDeserializer & h, const int version) override;

+ 1 - 2
lib/IGameEventsReceiver.h

@@ -49,7 +49,6 @@ struct CObstacleInstance;
 struct CPackForServer;
 class EVictoryLossCheckResult;
 struct MetaString;
-struct CustomEffectInfo;
 class ObstacleChanges;
 class UnitChanges;
 
@@ -70,7 +69,7 @@ public:
 	virtual void battleTriggerEffect(const BattleTriggerEffect & bte){}; //called for various one-shot effects
 	virtual void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) {}; //called just before battle start
 	virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
-	virtual void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects){};
+	virtual void battleUnitsChanged(const std::vector<UnitChanges> & units){};
 	virtual void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles){};
 	virtual void battleCatapultAttacked(const CatapultAttack & ca){}; //called when catapult makes an attack
 	virtual void battleGateStateChanged(const EGateState state){};

+ 9 - 12
lib/NetPacks.h

@@ -1557,12 +1557,10 @@ struct BattleUnitsChanged : public CPackForClient
 	void applyCl(CClient *cl);
 
 	std::vector<UnitChanges> changedStacks;
-	std::vector<CustomEffectInfo> customEffects;
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & changedStacks;
-		h & customEffects;
 	}
 };
 
@@ -1575,7 +1573,6 @@ struct BattleStackAttacked
 		damageAmount(0),
 		newState(),
 		flags(0),
-		effect(0),
 		spellID(SpellID::NONE)
 	{};
 
@@ -1586,9 +1583,8 @@ struct BattleStackAttacked
 	ui32 killedAmount;
 	int64_t damageAmount;
 	UnitChanges newState;
-	enum EFlags {KILLED = 1, EFFECT = 2/*deprecated */, SECONDARY = 4, REBIRTH = 8, CLONE_KILLED = 16, SPELL_EFFECT = 32 /*, BONUS_EFFECT = 64 */};
+	enum EFlags {KILLED = 1, SECONDARY = 2, REBIRTH = 4, CLONE_KILLED = 8, SPELL_EFFECT = 16, FIRE_SHIELD = 32, };
 	ui32 flags; //uses EFlags (above)
-	ui32 effect; //set only if flag EFFECT is set
 	SpellID spellID; //only if flag SPELL_EFFECT is set
 
 	bool killed() const//if target stack was killed
@@ -1599,10 +1595,6 @@ struct BattleStackAttacked
 	{
 		return flags & CLONE_KILLED;
 	}
-	bool isEffect() const//if stack has been attacked by a spell
-	{
-		return flags & EFFECT;
-	}
 	bool isSecondary() const//if stack was not a primary target (receives no spell effects)
 	{
 		return flags & SECONDARY;
@@ -1616,6 +1608,10 @@ struct BattleStackAttacked
 	{
 		return flags & REBIRTH;
 	}
+	bool fireShield() const
+	{
+		return flags & FIRE_SHIELD;
+	}
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & stackAttacked;
@@ -1624,7 +1620,6 @@ struct BattleStackAttacked
 		h & flags;
 		h & killedAmount;
 		h & damageAmount;
-		h & effect;
 		h & spellID;
 	}
 	bool operator<(const BattleStackAttacked &b) const
@@ -1737,8 +1732,9 @@ struct BattleSpellCast : public CPackForClient
 	SpellID spellID; //id of spell
 	ui8 manaGained; //mana channeling ability
 	BattleHex tile; //destination tile (may not be set in some global/mass spells
-	std::vector<CustomEffectInfo> customEffects;
 	std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
+	std::set<ui32> resistedCres; // creatures that resisted the spell (e.g. Dwarves)
+	std::set<ui32> reflectedCres; // creatures that reflected the spell (e.g. Magic Mirror spell)
 	si32 casterStack;// -1 if not cated by creature, >=0 caster stack ID
 	bool castByHero; //if true - spell has been cast by hero, otherwise by a creature
 
@@ -1748,8 +1744,9 @@ struct BattleSpellCast : public CPackForClient
 		h & spellID;
 		h & manaGained;
 		h & tile;
-		h & customEffects;
 		h & affectedCres;
+		h & resistedCres;
+		h & reflectedCres;
 		h & casterStack;
 		h & castByHero;
 		h & activeCast;

+ 0 - 21
lib/NetPacksBase.h

@@ -250,27 +250,6 @@ struct ArtifactLocation
 	}
 };
 
-///custom effect (resistance, reflection, etc)
-struct CustomEffectInfo
-{
-	CustomEffectInfo()
-		:effect(0),
-		sound(0),
-		stack(0)
-	{
-	}
-	/// WoG AC format
-	ui32 effect;
-	ui32 sound;
-	ui32 stack;
-	template <typename Handler> void serialize(Handler & h, const int version)
-	{
-		h & effect;
-		h & sound;
-		h & stack;
-	}
-};
-
 class EntityChanges
 {
 public:

+ 2 - 15
lib/spells/BattleSpellMechanics.cpp

@@ -401,12 +401,12 @@ void BattleSpellMechanics::beforeCast(BattleSpellCast & sc, vstd::RNG & rng, con
 	{
 		if(caster->getCasterUnitId() >= 0)
 		{
-			addCustomEffect(sc, caster->getCasterUnitId(), 3);
+			sc.reflectedCres.insert(caster->getCasterUnitId());
 		}
 	}
 
 	for(auto unit : resisted)
-		addCustomEffect(sc, unit, 78);
+		sc.resistedCres.insert(unit->unitId());
 }
 
 void BattleSpellMechanics::castEval(ServerCallback * server, const Target & target)
@@ -430,19 +430,6 @@ void BattleSpellMechanics::castEval(ServerCallback * server, const Target & targ
 		p.first->apply(server, this, p.second);
 }
 
-void BattleSpellMechanics::addCustomEffect(BattleSpellCast & sc, const battle::Unit * target, ui32 effect)
-{
-	addCustomEffect(sc, target->unitId(), effect);
-}
-
-void BattleSpellMechanics::addCustomEffect(BattleSpellCast & sc, ui32 targetId, ui32 effect)
-{
-	CustomEffectInfo customEffect;
-	customEffect.effect = effect;
-	customEffect.stack = targetId;
-	sc.customEffects.push_back(customEffect);
-}
-
 std::set<const battle::Unit *> BattleSpellMechanics::collectTargets() const
 {
 	std::set<const battle::Unit *> result;

+ 0 - 3
lib/spells/BattleSpellMechanics.h

@@ -57,9 +57,6 @@ private:
 
 	void beforeCast(BattleSpellCast & sc, vstd::RNG & rng, const Target & target);
 
-	void addCustomEffect(BattleSpellCast & sc, const battle::Unit * target, ui32 effect);
-	void addCustomEffect(BattleSpellCast & sc, ui32 targetId, ui32 effect);
-
 	std::set<const battle::Unit *> collectTargets() const;
 
 	static void doRemoveEffects(ServerCallback * server, const std::vector<const battle::Unit *> & targets, const CSelector & selector);

+ 0 - 8
lib/spells/effects/Damage.cpp

@@ -33,7 +33,6 @@ VCMI_REGISTER_SPELL_EFFECT(Damage, EFFECT_NAME);
 
 Damage::Damage()
 	: UnitEffect(),
-	customEffectId(-1),
 	killByPercentage(false),
 	killByCount(false)
 {
@@ -74,12 +73,6 @@ void Damage::apply(ServerCallback * server, const Mechanics * m, const EffectTar
 				damageToDisplay += bsa.damageAmount;
 				killed += bsa.killedAmount;
 			}
-			if(customEffectId >= 0)
-			{
-				bsa.effect = 82;
-				bsa.flags |= BattleStackAttacked::EFFECT;
-			}
-
 			stacksInjured.stacks.push_back(bsa);
 		}
 		targetIndex++;
@@ -116,7 +109,6 @@ bool Damage::isReceptive(const Mechanics * m, const battle::Unit * unit) const
 
 void Damage::serializeJsonUnitEffect(JsonSerializeFormat & handler)
 {
-	handler.serializeInt("customEffectId", customEffectId, -1);
 	handler.serializeBool("killByPercentage", killByPercentage);
 	handler.serializeBool("killByCount", killByCount);
 }

+ 0 - 1
lib/spells/effects/Damage.h

@@ -39,7 +39,6 @@ protected:
 	virtual void describeEffect(std::vector<MetaString> & log, const Mechanics * m, const battle::Unit * firstTarget, uint32_t kills, int64_t damage, bool multiple) const;
 
 private:
-	int32_t customEffectId;
 	bool killByPercentage;
 	bool killByCount;
 };

+ 2 - 3
server/CGameHandler.cpp

@@ -1182,10 +1182,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
 
 		BattleStackAttacked bsa;
 
+		bsa.flags |= BattleStackAttacked::FIRE_SHIELD;
 		bsa.stackAttacked = attacker->ID; //invert
-		bsa.attackerID = uint32_t(-1);
-		bsa.flags |= BattleStackAttacked::EFFECT;
-		bsa.effect = 11;
+		bsa.attackerID = defender->ID;
 		bsa.damageAmount = totalDamage;
 		attacker->prepareAttacked(bsa, getRandomGenerator());