Przeglądaj źródła

First version of sea witch / sorceress ability

Dydzio 1 rok temu
rodzic
commit
bb925e4cb0

+ 1 - 1
client/battle/BattleInterface.cpp

@@ -791,7 +791,7 @@ void BattleInterface::waitForAnimations()
 	}
 
 	assert(!hasAnimations());
-	assert(awaitingEvents.empty());
+	//assert(awaitingEvents.empty());
 
 	if (!awaitingEvents.empty())
 	{

+ 1 - 1
lib/bonuses/BonusEnum.h

@@ -57,7 +57,7 @@ class JsonNode;
 	BONUS_NAME(MAGIC_RESISTANCE) /*in % (value)*/		\
 	BONUS_NAME(CHANGES_SPELL_COST_FOR_ALLY) /*in mana points (value) , eg. mage*/ \
 	BONUS_NAME(CHANGES_SPELL_COST_FOR_ENEMY) /*in mana points (value) , eg. pegasus */ \
-	BONUS_NAME(SPELL_AFTER_ATTACK) /* subtype - spell id, value - chance %, addInfo[0] - level, addInfo[1] -> [0 - all attacks, 1 - shot only, 2 - melee only] */ \
+	BONUS_NAME(SPELL_AFTER_ATTACK) /* subtype - spell id, value - chance %, addInfo[0] - level, addInfo[1] -> [0 - all attacks, 1 - shot only, 2 - melee only], addInfo[2] -> backup spell layer (default none [-1]) */ \
 	BONUS_NAME(SPELL_BEFORE_ATTACK) /* subtype - spell id, value - chance %, addInfo[0] - level, addInfo[1] -> [0 - all attacks, 1 - shot only, 2 - melee only] */ \
 	BONUS_NAME(SPELL_RESISTANCE_AURA) /*eg. unicorns, value - resistance bonus in % for adjacent creatures*/ \
 	BONUS_NAME(LEVEL_SPELL_IMMUNITY) /*creature is immune to all spell with level below or equal to value of this bonus */ \

+ 68 - 6
server/battles/BattleActionProcessor.cpp

@@ -1119,19 +1119,81 @@ void BattleActionProcessor::makeAttack(const CBattleInfoCallback & battle, const
 	handleAfterAttackCasting(battle, ranged, attacker, defender);
 }
 
-void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bool ranged, BonusType attackMode, const battle::Unit * attacker, const battle::Unit * defender)
+void BattleActionProcessor::attackCasting(const CBattleInfoCallback & battle, bool ranged, BonusType attackMode, const battle::Unit * attacker, const CStack * defender)
 {
 	if(attacker->hasBonusOfType(attackMode))
 	{
 		std::set<SpellID> spellsToCast;
+
 		TConstBonusListPtr spells = attacker->getBonuses(Selector::type()(attackMode));
-		for(const auto & sf : *spells)
+
+		std::array<std::vector<std::shared_ptr<Bonus>>, 6> spellsWithBackupLayers =
 		{
-			if (sf->subtype.as<SpellID>() != SpellID())
-				spellsToCast.insert(sf->subtype.as<SpellID>());
-			else
-				logMod->error("Invalid spell to cast during attack!");
+			{
+				std::vector<std::shared_ptr<Bonus>>(),
+				std::vector<std::shared_ptr<Bonus>>(),
+				std::vector<std::shared_ptr<Bonus>>(),
+				std::vector<std::shared_ptr<Bonus>>(),
+				std::vector<std::shared_ptr<Bonus>>(),
+				std::vector<std::shared_ptr<Bonus>>()
+			}
+		};
+
+		int lastBackupLayer = -1;
+		for(int i = 0; i < spells->size(); i++)
+		{
+			std::shared_ptr<Bonus> bonus = spells->operator[](i);
+			int layer = bonus->additionalInfo[2];
+			vstd::abetween(layer, -1, 4);
+			spellsWithBackupLayers[layer+1].push_back(bonus);
+
+			if(layer > lastBackupLayer)
+				lastBackupLayer = layer;
+		}
+
+		auto addSpellsFromLayer = [&](int layer) -> void
+		{
+			if(layer + 1 >= spellsWithBackupLayers.size() )
+			{
+				logMod->error(std::string("Wrong layer in addSpellsFromLayer: ") + std::to_string(layer));
+				return;
+			}
+
+			for(const auto & spell : spellsWithBackupLayers[layer+1])
+			{
+				if (spell->subtype.as<SpellID>() != SpellID())
+					spellsToCast.insert(spell->subtype.as<SpellID>());
+				else
+					logMod->error("Invalid spell to cast during attack!");
+			}
+		};
+
+		addSpellsFromLayer(-1);
+
+		for(int spellLayer = 0; spellLayer <= lastBackupLayer; spellLayer++)
+		{
+			if(spellsWithBackupLayers[spellLayer+1].empty())
+				continue;
+
+			if(spellLayer < lastBackupLayer)
+			{
+				bool areCurrentLayerSpellsApplied = std::all_of(spellsWithBackupLayers[spellLayer+1].begin(), spellsWithBackupLayers[spellLayer+1].end(),
+					[&](const std::shared_ptr<Bonus> spell)
+					{
+						std::vector<SpellID> activeSpells = defender->activeSpells();
+						auto spellIterator = vstd::find(activeSpells, spell->subtype.as<SpellID>());
+						bool value = spellIterator != activeSpells.end();
+						return value;
+					});
+
+				if(areCurrentLayerSpellsApplied)
+					continue;
+			}
+
+			addSpellsFromLayer(spellLayer);
+			break;
 		}
+
 		for(SpellID spellID : spellsToCast)
 		{
 			bool castMe = false;

+ 1 - 1
server/battles/BattleActionProcessor.h

@@ -44,7 +44,7 @@ class BattleActionProcessor : boost::noncopyable
 
 	void handleAttackBeforeCasting(const CBattleInfoCallback & battle, bool ranged, const CStack * attacker, const CStack * defender);
 	void handleAfterAttackCasting(const CBattleInfoCallback & battle, bool ranged, const CStack * attacker, const CStack * defender);
-	void attackCasting(const CBattleInfoCallback & battle, bool ranged, BonusType attackMode, const battle::Unit * attacker, const battle::Unit * defender);
+	void attackCasting(const CBattleInfoCallback & battle, bool ranged, BonusType attackMode, const battle::Unit * attacker, const CStack * defender);
 
 	// damage, drain life & fire shield; returns amount of drained life
 	int64_t applyBattleEffects(const CBattleInfoCallback & battle, BattleAttack & bat, std::shared_ptr<battle::CUnitState> attackerState, FireShieldInfo & fireShield, const CStack * def, int distance, bool secondary);