mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Use ISpellCaster in battle callback
This commit is contained in:
		| @@ -2470,10 +2470,16 @@ bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CSta | ||||
|  | ||||
| 	if (sp) | ||||
| 	{ | ||||
| 		if (creatureCasting) | ||||
| 			isCastingPossible = (curInt->cb->battleCanCreatureCastThisSpell (sp, myNumber) == ESpellCastProblem::OK); | ||||
| 		const ISpellCaster * caster = creatureCasting ? dynamic_cast<const ISpellCaster *>(sactive) : dynamic_cast<const ISpellCaster *>(curInt->cb->battleGetMyHero()); | ||||
| 		if(caster == nullptr) | ||||
| 		{ | ||||
| 			isCastingPossible = false;//just in case | ||||
| 		} | ||||
| 		else | ||||
| 			isCastingPossible = (curInt->cb->battleCanCastThisSpell (sp, myNumber) == ESpellCastProblem::OK); | ||||
| 		{ | ||||
| 			const ECastingMode::ECastingMode mode = creatureCasting ? ECastingMode::CREATURE_ACTIVE_CASTING : ECastingMode::HERO_CASTING; | ||||
| 			isCastingPossible = (curInt->cb->battleCanCastThisSpellHere(caster, sp, mode, myNumber) == ESpellCastProblem::OK); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 		isCastingPossible = false; | ||||
|   | ||||
| @@ -1592,9 +1592,15 @@ std::vector<BattleHex> CBattleInfoCallback::getAttackableBattleHexes() const | ||||
| 	return attackableBattleHexes; | ||||
| } | ||||
|  | ||||
| ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell( PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode ) const | ||||
| ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode) const | ||||
| { | ||||
| 	RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID); | ||||
| 	if(caster == nullptr) | ||||
| 	{ | ||||
| 		logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpell: no spellcaster."; | ||||
| 		return ESpellCastProblem::INVALID; | ||||
| 	} | ||||
| 	const PlayerColor player = caster->getOwner(); | ||||
| 	const ui8 side = playerToSide(player); | ||||
| 	if(!battleDoWeKnowAbout(side)) | ||||
| 		return ESpellCastProblem::INVALID; | ||||
| @@ -1603,16 +1609,11 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell | ||||
| 	if(genProblem != ESpellCastProblem::OK) | ||||
| 		return genProblem; | ||||
|  | ||||
| 	//Casting hero, set only if he is an actual caster. | ||||
| 	const CGHeroInstance *castingHero = mode == ECastingMode::HERO_CASTING | ||||
| 										? battleGetFightingHero(side) | ||||
| 										: nullptr; | ||||
|  | ||||
|  | ||||
| 	switch(mode) | ||||
| 	{ | ||||
| 	case ECastingMode::HERO_CASTING: | ||||
| 		{ | ||||
| 			const CGHeroInstance * castingHero = dynamic_cast<const CGHeroInstance *>(caster);//todo: unify hero|creature spell cost | ||||
| 			assert(castingHero); | ||||
| 			if(!castingHero->canCastThisSpell(spell)) | ||||
| 				return ESpellCastProblem::HERO_DOESNT_KNOW_SPELL; | ||||
| @@ -1622,7 +1623,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	if(!spell->combatSpell) | ||||
| 		return ESpellCastProblem::ADVMAP_SPELL_INSTEAD_OF_BATTLE_SPELL; | ||||
|  | ||||
| @@ -1639,7 +1639,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell | ||||
| 		auto stacks = spell->isNegative() ? battleAliveStacks(!side) : battleAliveStacks(); | ||||
| 		for(auto stack : stacks) | ||||
| 		{ | ||||
| 			if(ESpellCastProblem::OK == spell->isImmuneByStack(castingHero, stack)) | ||||
| 			if(ESpellCastProblem::OK == spell->isImmuneByStack(caster, stack)) | ||||
| 			{ | ||||
| 				allStacksImmune = false; | ||||
| 				break; | ||||
| @@ -1659,7 +1659,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell | ||||
| 	case CSpell::CREATURE: | ||||
| 		if(mode == ECastingMode::HERO_CASTING) | ||||
| 		{ | ||||
| 			const CGHeroInstance * caster = battleGetFightingHero(side); | ||||
| 			const CSpell::TargetInfo ti(spell, caster->getSpellSchoolLevel(spell)); | ||||
| 			bool targetExists = false; | ||||
|  | ||||
| @@ -1777,10 +1776,16 @@ ui32 CBattleInfoCallback::battleGetSpellCost(const CSpell * sp, const CGHeroInst | ||||
| 	return ret - manaReduction + manaIncrease; | ||||
| } | ||||
|  | ||||
| ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpellHere( PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest ) const | ||||
| ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpellHere(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const | ||||
| { | ||||
| 	RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID); | ||||
| 	ESpellCastProblem::ESpellCastProblem moreGeneralProblem = battleCanCastThisSpell(player, spell, mode); | ||||
| 	if(caster == nullptr) | ||||
| 	{ | ||||
| 		logGlobal->errorStream() << "CBattleInfoCallback::battleCanCastThisSpellHere: no spellcaster."; | ||||
| 		return ESpellCastProblem::INVALID; | ||||
| 	}	 | ||||
| 	const PlayerColor player = caster->getOwner(); | ||||
| 	ESpellCastProblem::ESpellCastProblem moreGeneralProblem = battleCanCastThisSpell(caster, spell, mode); | ||||
| 	if(moreGeneralProblem != ESpellCastProblem::OK) | ||||
| 		return moreGeneralProblem; | ||||
|  | ||||
| @@ -1843,11 +1848,6 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell | ||||
| 		if(spell->isPositive() && aliveStack->owner != player) | ||||
| 			return ESpellCastProblem::NO_APPROPRIATE_TARGET; | ||||
| 	} | ||||
|  | ||||
| 	const CGHeroInstance * caster = nullptr; | ||||
| 	if (mode == ECastingMode::HERO_CASTING) | ||||
| 		caster = battleGetFightingHero(playerToSide(player)); | ||||
| 	 | ||||
| 	return spell->isImmuneAt(this, caster, mode, dest); | ||||
| } | ||||
|  | ||||
| @@ -1930,7 +1930,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) co | ||||
| 	{ | ||||
| 		if (subject->hasBonusFrom(Bonus::SPELL_EFFECT, spellID) | ||||
| 			//TODO: this ability has special limitations | ||||
| 			|| battleCanCastThisSpellHere(subject->owner, spellID.toSpell(), ECastingMode::CREATURE_ACTIVE_CASTING, subject->position) != ESpellCastProblem::OK) | ||||
| 			|| battleCanCastThisSpellHere(subject, spellID.toSpell(), ECastingMode::CREATURE_ACTIVE_CASTING, subject->position) != ESpellCastProblem::OK) | ||||
| 			continue; | ||||
|  | ||||
| 		switch (spellID) | ||||
| @@ -2168,21 +2168,12 @@ ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCastThisSpe | ||||
| { | ||||
| 	RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID); | ||||
| 	ASSERT_IF_CALLED_WITH_PLAYER | ||||
| 	return CBattleInfoCallback::battleCanCastThisSpell(*player, spell, ECastingMode::HERO_CASTING); | ||||
| } | ||||
|  | ||||
| ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCastThisSpell(const CSpell * spell, BattleHex destination) const | ||||
| { | ||||
| 	RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID); | ||||
| 	ASSERT_IF_CALLED_WITH_PLAYER | ||||
| 	return battleCanCastThisSpellHere(*player, spell, ECastingMode::HERO_CASTING, destination); | ||||
| } | ||||
|  | ||||
| ESpellCastProblem::ESpellCastProblem CPlayerBattleCallback::battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const | ||||
| { | ||||
| 	RETURN_IF_NOT_BATTLE(ESpellCastProblem::INVALID); | ||||
| 	ASSERT_IF_CALLED_WITH_PLAYER | ||||
| 	return battleCanCastThisSpellHere(*player, spell, ECastingMode::CREATURE_ACTIVE_CASTING, destination); | ||||
| 	const ISpellCaster * hero = battleGetMyHero(); | ||||
| 	if(hero == nullptr) | ||||
| 		return ESpellCastProblem::INVALID; | ||||
| 	else | ||||
| 		return CBattleInfoCallback::battleCanCastThisSpell(hero, spell, ECastingMode::HERO_CASTING); | ||||
| } | ||||
|  | ||||
| bool CPlayerBattleCallback::battleCanFlee() const | ||||
|   | ||||
| @@ -15,6 +15,7 @@ class CGameState; | ||||
| class CGTownInstance; | ||||
| class CGHeroInstance; | ||||
| class CStack; | ||||
| class ISpellCaster; | ||||
| class CSpell; | ||||
| struct BattleInfo; | ||||
| struct CObstacleInstance; | ||||
| @@ -280,9 +281,8 @@ public: | ||||
| 	si8 battleMaxSpellLevel(ui8 side) const; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned | ||||
| 	ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCastSpell(PlayerColor player, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode) const; //checks if given player can cast given spell | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(PlayerColor player, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode) const; //checks if given player can cast given spell | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode | ||||
| 	std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const; | ||||
|  | ||||
| 	SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const; | ||||
| @@ -326,8 +326,7 @@ public: | ||||
| 	bool battleCanFlee() const; //returns true if caller can flee from the battle | ||||
| 	TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true) const; //returns stacks on battlefield | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell) const; //determines if given spell can be cast (and returns problem description) | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const CSpell * spell, BattleHex destination) const; //if hero can cast spell here | ||||
| 	ESpellCastProblem::ESpellCastProblem battleCanCreatureCastThisSpell(const CSpell * spell, BattleHex destination) const; //determines if creature can cast a spell here | ||||
|  | ||||
| 	int battleGetSurrenderCost() const; //returns cost of surrendering battle, -1 if surrendering is not possible | ||||
|  | ||||
| 	bool battleCanCastSpell(ESpellCastProblem::ESpellCastProblem *outProblem = nullptr) const; //returns true, if caller can cast a spell. If not, if pointer is given via arg, the reason will be written. | ||||
|   | ||||
| @@ -139,8 +139,6 @@ ESpellCastProblem::ESpellCastProblem CloneMechanics::isImmuneByStack(const ISpel | ||||
| 		return ESpellCastProblem::STACK_IMMUNE_TO_SPELL; | ||||
| 	if(obj->cloneID != -1) | ||||
| 		return ESpellCastProblem::STACK_IMMUNE_TO_SPELL; | ||||
| 	//TODO: how about stacks casting Clone? | ||||
| 	//currently Clone cast by stack is assumed Expert level | ||||
| 	ui8 schoolLevel; | ||||
| 	if(caster) | ||||
| 	{ | ||||
| @@ -148,7 +146,7 @@ ESpellCastProblem::ESpellCastProblem CloneMechanics::isImmuneByStack(const ISpel | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		schoolLevel = 3; | ||||
| 		schoolLevel = 3;//todo: remove | ||||
| 	} | ||||
|  | ||||
| 	if(schoolLevel < 3) | ||||
|   | ||||
| @@ -23,7 +23,6 @@ | ||||
| #include "../CModHandler.h" | ||||
| #include "../StringConstants.h" | ||||
|  | ||||
| #include "../mapObjects/CGHeroInstance.h" | ||||
| #include "../BattleState.h" | ||||
| #include "../CBattleCallback.h" | ||||
| #include "../CGameState.h" //todo: remove | ||||
| @@ -303,7 +302,7 @@ void CSpell::getEffects(std::vector<Bonus> & lst, const int level) const | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const CGHeroInstance * caster, ECastingMode::ECastingMode mode, BattleHex destination) const | ||||
| ESpellCastProblem::ESpellCastProblem CSpell::isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const | ||||
| { | ||||
| 	// Get all stacks at destination hex. only alive if not rising spell | ||||
| 	TStacks stacks = cb->battleGetStacksIf([=](const CStack * s){ | ||||
| @@ -385,9 +384,8 @@ int CSpell::adjustRawDamage(const ISpellCaster * caster, const CStack * affected | ||||
| 			ret /= 100; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ret = caster->getSpellBonus(this, ret, affectedCreature); | ||||
|  | ||||
| 	if(caster != nullptr) | ||||
| 		ret = caster->getSpellBonus(this, ret, affectedCreature); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -213,8 +213,6 @@ public: | ||||
| 	bool hasEffects() const; | ||||
| 	void getEffects(std::vector<Bonus> &lst, const int level) const; | ||||
|  | ||||
| 	///checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into account general problems such as not having spellbook or mana points etc. | ||||
| 	ESpellCastProblem::ESpellCastProblem isImmuneAt(const CBattleInfoCallback * cb, const CGHeroInstance * caster, ECastingMode::ECastingMode mode, BattleHex destination) const; | ||||
|  | ||||
| 	///calculate spell damage on stack taking caster`s secondary skills and affectedCreature`s bonuses into account | ||||
| 	ui32 calculateDamage(const ISpellCaster * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; | ||||
| @@ -271,6 +269,9 @@ public: | ||||
| 	///Checks general but spell-specific problems for all casting modes. Use only during battle. | ||||
| 	ESpellCastProblem::ESpellCastProblem canBeCast(const CBattleInfoCallback * cb, PlayerColor player) const; | ||||
|  | ||||
| 	///checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into account general problems such as not having spellbook or mana points etc. | ||||
| 	ESpellCastProblem::ESpellCastProblem isImmuneAt(const CBattleInfoCallback * cb, const ISpellCaster * caster, ECastingMode::ECastingMode mode, BattleHex destination) const; | ||||
| 	 | ||||
| 	///checks for creature immunity / anything that prevent casting *at given target* - doesn't take into account general problems such as not having spellbook or mana points etc. | ||||
| 	ESpellCastProblem::ESpellCastProblem isImmuneByStack(const ISpellCaster * caster, const CStack * obj) const; | ||||
| public: | ||||
|   | ||||
| @@ -4073,7 +4073,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) | ||||
| 			parameters.mode = ECastingMode::HERO_CASTING; | ||||
| 			parameters.selectedStack = gs->curB->battleGetStackByID(ba.selectedStack, false);			 | ||||
|  | ||||
| 			ESpellCastProblem::ESpellCastProblem escp = gs->curB->battleCanCastThisSpell(h->tempOwner, s, ECastingMode::HERO_CASTING); | ||||
| 			ESpellCastProblem::ESpellCastProblem escp = gs->curB->battleCanCastThisSpell(h, s, ECastingMode::HERO_CASTING);//todo: should we check aimed cast(battleCanCastThisSpellHere)? | ||||
| 			if(escp != ESpellCastProblem::OK) | ||||
| 			{ | ||||
| 				logGlobal->warnStream() << "Spell cannot be cast!"; | ||||
| @@ -4217,7 +4217,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st) | ||||
| 				const CSpell * spell = SpellID(spellID).toSpell(); | ||||
| 				bl.remove_if([&bonus](Bonus * b){return b==bonus;});					 | ||||
| 				 | ||||
| 				if (gs->curB->battleCanCastThisSpell(st->owner, spell, ECastingMode::ENCHANTER_CASTING) == ESpellCastProblem::OK) | ||||
| 				if (gs->curB->battleCanCastThisSpell(st, spell, ECastingMode::ENCHANTER_CASTING) == ESpellCastProblem::OK) | ||||
| 				{ | ||||
| 					BattleSpellCastParameters parameters(gs->curB, st, spell); | ||||
| 					parameters.spellLvl = bonus->val; | ||||
| @@ -4277,7 +4277,7 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c | ||||
| 	//helper info | ||||
| 	const SpellCreatedObstacle *spellObstacle = dynamic_cast<const SpellCreatedObstacle*>(&obstacle); //not nice but we may need spell params | ||||
| 	const ui8 side = !curStack->attackerOwned; //if enemy is defending (false = 0), side of enemy hero is 1 (true) | ||||
| 	const CGHeroInstance *hero = gs->curB->battleGetFightingHero(side); | ||||
| 	const CGHeroInstance *hero = gs->curB->battleGetFightingHero(side);//FIXME: there may be no hero - landmines in Tower | ||||
|  | ||||
| 	if(obstacle.obstacleType == CObstacleInstance::MOAT) | ||||
| 	{ | ||||
| @@ -4916,7 +4916,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta | ||||
| 			int destination = oneOfAttacked->position; | ||||
|  | ||||
| 			const CSpell * spell = SpellID(spellID).toSpell(); | ||||
| 			if(gs->curB->battleCanCastThisSpellHere(attacker->owner, spell, ECastingMode::AFTER_ATTACK_CASTING, oneOfAttacked->position) != ESpellCastProblem::OK) | ||||
| 			if(gs->curB->battleCanCastThisSpellHere(attacker, spell, ECastingMode::AFTER_ATTACK_CASTING, oneOfAttacked->position) != ESpellCastProblem::OK) | ||||
| 				continue; | ||||
|  | ||||
| 			//check if spell should be cast (probability handling) | ||||
| @@ -4926,8 +4926,6 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta | ||||
| 			//casting | ||||
| 			if (castMe) //stacks use 0 spell power. If needed, default = 3 or custom value is used | ||||
| 			{ | ||||
| 				const CSpell * spell = SpellID(spellID).toSpell(); | ||||
|  | ||||
| 				BattleSpellCastParameters parameters(gs->curB, attacker, spell); | ||||
| 				parameters.spellLvl = spellLevel; | ||||
| 				parameters.effectLevel = spellLevel; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user