mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	| @@ -1750,25 +1750,14 @@ void CBattleInterface::getPossibleActionsForStack(const CStack * stack) | ||||
| 				for (Bonus * spellBonus : spellBonuses) | ||||
| 				{ | ||||
| 					spell = CGI->spellh->spells[spellBonus->subtype]; | ||||
| 					if (spell->isRisingSpell()) | ||||
| 					switch (spellBonus->subtype) | ||||
| 					{ | ||||
| 						possibleActions.push_back (RISING_SPELL); | ||||
| 					} | ||||
| 					//possibleActions.push_back (NO_LOCATION); | ||||
| 					//possibleActions.push_back (ANY_LOCATION); | ||||
| 					//TODO: allow stacks cast aimed spells | ||||
| 					//possibleActions.push_back (OTHER_SPELL); | ||||
| 					else | ||||
| 					{ | ||||
| 						switch (spellBonus->subtype) | ||||
| 						{ | ||||
| 							case SpellID::REMOVE_OBSTACLE: | ||||
| 								possibleActions.push_back (OBSTACLE); | ||||
| 								break; | ||||
| 							default: | ||||
| 								possibleActions.push_back (selectionTypeByPositiveness (*spell)); | ||||
| 								break; | ||||
| 						} | ||||
| 						case SpellID::REMOVE_OBSTACLE: | ||||
| 							possibleActions.push_back (OBSTACLE); | ||||
| 							break; | ||||
| 						default: | ||||
| 							possibleActions.push_back (selectionTypeByPositiveness (*spell)); | ||||
| 							break; | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
| @@ -2194,13 +2183,18 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) | ||||
| 					legalAction = true; | ||||
| 				break; | ||||
| 			case FRIENDLY_CREATURE_SPELL: | ||||
| 				if (shere && shere->alive() && ourStack && isCastingPossibleHere (sactive, shere, myNumber)) | ||||
| 					legalAction = true; | ||||
| 				break; | ||||
| 			case RISING_SPELL: | ||||
| 				if (shere && shere->canBeHealed() && ourStack && isCastingPossibleHere (sactive, shere, myNumber)) //TODO: at least one stack has to be raised by resurrection / animate dead | ||||
| 					legalAction = true; | ||||
| 			{ | ||||
| 				if (isCastingPossibleHere (sactive, shere, myNumber)); //need to be called before sp is determined | ||||
| 				{ | ||||
| 					bool rise = false; //TODO: can you imagine rising hostile creatures? | ||||
| 					sp = CGI->spellh->spells[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo]; | ||||
| 					if (sp && sp->isRisingSpell()) | ||||
| 							rise = true; | ||||
| 					if (shere && (shere->alive() || rise) && ourStack) | ||||
| 						legalAction = true; | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 			case RANDOM_GENIE_SPELL: | ||||
| 			{ | ||||
| 				if (shere && ourStack && shere != sactive) //only positive spells for other allied creatures | ||||
| @@ -2379,7 +2373,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) | ||||
| 				break; | ||||
| 			case HOSTILE_CREATURE_SPELL: | ||||
| 			case FRIENDLY_CREATURE_SPELL: | ||||
| 			case RISING_SPELL: | ||||
| 				sp = CGI->spellh->spells[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo]; //necessary if creature has random Genie spell at same time | ||||
| 				consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s | ||||
| 				switch (sp->id) | ||||
| @@ -2452,7 +2445,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType) | ||||
| 		{ | ||||
| 			case HOSTILE_CREATURE_SPELL: | ||||
| 			case FRIENDLY_CREATURE_SPELL: | ||||
| 			case RISING_SPELL: | ||||
| 			case RANDOM_GENIE_SPELL: | ||||
| 				cursorFrame = ECursor::COMBAT_BLOCKED; | ||||
| 				consoleMsg = CGI->generaltexth->allTexts[23]; | ||||
|   | ||||
| @@ -112,7 +112,7 @@ void BattleInfo::calculateCasualties( std::map<ui32,si32> *casualties ) const | ||||
| 	for(auto & elem : stacks)//setting casualties | ||||
| 	{ | ||||
| 		const CStack * const st = elem; | ||||
| 		si32 killed = (st->alive() ? st->baseAmount - st->count : st->baseAmount); | ||||
| 		si32 killed = (st->alive() ? (st->baseAmount - st->count + st->resurrected) : st->baseAmount); | ||||
| 		vstd::amax(killed, 0); | ||||
| 		if(killed) | ||||
| 			casualties[!st->attackerOwned][st->getCreature()->idNumber] += killed; | ||||
| @@ -161,9 +161,9 @@ CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool at | ||||
| } | ||||
|  | ||||
| //All spells casted by hero 9resurrection, cure, sacrifice) | ||||
| ui32 BattleInfo::calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack) const | ||||
| ui32 CBattleInfoCallback::calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack) const | ||||
| { | ||||
| 	bool resurrect = resurrects(spell->id); | ||||
| 	bool resurrect = spell->isRisingSpell(); | ||||
| 	int healedHealth; | ||||
| 	if (spell->id == SpellID::SACRIFICE && sacrificedStack) | ||||
| 		healedHealth = (caster->getPrimSkillLevel(PrimarySkill::SPELL_POWER) + sacrificedStack->MaxHealth() + spell->powers[caster->getSpellSchoolLevel(spell)]) * sacrificedStack->count; | ||||
| @@ -173,15 +173,15 @@ ui32 BattleInfo::calculateHealedHP(const CGHeroInstance * caster, const CSpell * | ||||
| 	return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0)); | ||||
| } | ||||
| //Archangel | ||||
| ui32 BattleInfo::calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const | ||||
| ui32 CBattleInfoCallback::calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const | ||||
| { | ||||
| 	bool resurrect = resurrects(spell->id); | ||||
| 	bool resurrect = spell->isRisingSpell(); | ||||
| 	return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0)); | ||||
| } | ||||
| //Casted by stack, no hero bonus applied | ||||
| ui32 BattleInfo::calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const | ||||
| ui32 CBattleInfoCallback::calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const | ||||
| { | ||||
| 	bool resurrect = resurrects(spell->id); | ||||
| 	bool resurrect = spell->isRisingSpell(); | ||||
| 	int healedHealth = usedSpellPower * spell->power + spell->powers[spellSchoolLevel]; | ||||
| 	return std::min<ui32>(healedHealth, stack->MaxHealth() - stack->firstHPleft + (resurrect ? stack->baseAmount * stack->MaxHealth() : 0)); | ||||
| } | ||||
| @@ -893,6 +893,7 @@ void CStack::postInit() | ||||
| 	shots = getCreature()->valOfBonuses(Bonus::SHOTS); | ||||
| 	counterAttacks = 1 + valOfBonuses(Bonus::ADDITIONAL_RETALIATION); | ||||
| 	casts = valOfBonuses(Bonus::CASTS); | ||||
| 	resurrected = 0; | ||||
| } | ||||
|  | ||||
| ui32 CStack::level() const | ||||
|   | ||||
| @@ -125,14 +125,10 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb | ||||
| 	CStack * generateNewStack(const CStackBasicDescriptor &base, bool attackerOwned, SlotID slot, BattleHex position) const; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield | ||||
| 	int getIdForNewStack() const; //suggest a currently unused ID that'd suitable for generating a new stack | ||||
| 	//std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex) | ||||
| 	ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack = nullptr) const; //Sacrifice | ||||
| 	ui32 calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const; //for Archangel | ||||
| 	ui32 calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const; //healing spells casted by stacks | ||||
| 	bool resurrects(SpellID spellid) const; //TODO: move it to spellHandler? | ||||
|  | ||||
| 	const CGHeroInstance * getHero(PlayerColor player) const; //returns fighting hero that belongs to given player | ||||
|  | ||||
|  | ||||
| 	std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const CGHeroInstance * hero2, const std::vector<const CStack*> affectedCreatures, PlayerColor casterSideOwner, ECastingMode::ECastingMode mode, int usedSpellPower, int spellLevel) const; | ||||
|  | ||||
| 	const CStack * battleGetStack(BattleHex pos, bool onlyAlive); //returns stack at given tile | ||||
| @@ -165,6 +161,7 @@ public: | ||||
| 	ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1) | ||||
| 	si16 shots; //how many shots left | ||||
| 	ui8 casts; //how many casts left | ||||
| 	TQuantity resurrected; // these units will be taken back after battle is over | ||||
|  | ||||
| 	std::set<EBattleStackState::EBattleStackState> state; | ||||
| 	//overrides | ||||
| @@ -218,7 +215,7 @@ public: | ||||
| 		h & static_cast<CBonusSystemNode&>(*this); | ||||
| 		h & static_cast<CStackBasicDescriptor&>(*this); | ||||
| 		h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks | ||||
| 			& shots & casts & count; | ||||
| 			& shots & casts & count & resurrected; | ||||
|  | ||||
| 		const CArmedInstance *army = (base ? base->armyObj : nullptr); | ||||
| 		SlotID slot = (base ? base->armyObj->findStack(base) : SlotID()); | ||||
|   | ||||
| @@ -503,8 +503,8 @@ const CStack* CBattleInfoCallback::battleGetStackByPos(BattleHex pos, bool onlyA | ||||
| { | ||||
| 	RETURN_IF_NOT_BATTLE(nullptr); | ||||
| 	for(auto s : battleGetAllStacks()) | ||||
| 		if(vstd::contains(s->getHexes(), pos)  &&  (!onlyAlive || s->alive())) | ||||
| 			return s; | ||||
| 		if(vstd::contains(s->getHexes(), pos) && (!onlyAlive || s->alive())) | ||||
| 				return s; | ||||
|  | ||||
| 	return nullptr; | ||||
| } | ||||
| @@ -1562,7 +1562,8 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleIsImmune(const C | ||||
|  | ||||
| 		if (spell->isRisingSpell()) | ||||
| 		{ | ||||
| 			if (subject->count >= subject->baseAmount) //TODO: calculate potential hp raised | ||||
| 			auto maxHealth = calculateHealedHP (caster, spell, subject); | ||||
| 			if (subject->count >= subject->baseAmount || maxHealth < subject->MaxHealth()) //must be able to rise at least one full creature | ||||
| 				return ESpellCastProblem::STACK_IMMUNE_TO_SPELL; | ||||
| 		} | ||||
|  | ||||
| @@ -1663,7 +1664,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell | ||||
| 		{ | ||||
| 			const CGHeroInstance * caster = battleGetFightingHero(side); | ||||
| 			bool targetExists = false; | ||||
| 			for(const CStack * stack : battleAliveStacks()) | ||||
| 			for(const CStack * stack : battleGetAllStacks()) //dead stacks will be immune anyway | ||||
| 			{ | ||||
| 				switch (spell->positiveness) | ||||
| 				{ | ||||
| @@ -1941,8 +1942,9 @@ std::set<const CStack*> CBattleInfoCallback::getAffectedCreatures(const CSpell * | ||||
|  | ||||
| 	const ui8 attackerSide = playerToSide(attackerOwner) == 1; | ||||
| 	const auto attackedHexes = spell->rangeInHexes(destinationTile, skillLevel, attackerSide); | ||||
| 	const bool onlyAlive = spell->id != SpellID::RESURRECTION && spell->id != SpellID::ANIMATE_DEAD; //when casting resurrection or animate dead we should be allow to select dead stack | ||||
| 	//fixme: what about other rising spells (Sacrifice) ? | ||||
| 	const bool onlyAlive = !spell->isRisingSpell(); //when casting resurrection or animate dead we should be allow to select dead stack | ||||
|  | ||||
| 	//TODO: more generic solution for mass spells | ||||
| 	if(spell->id == SpellID::DEATH_RIPPLE || spell->id == SpellID::DESTROY_UNDEAD || spell->id == SpellID::ARMAGEDDON) | ||||
| 	{ | ||||
| 		for(const CStack *stack : battleGetAllStacks()) | ||||
|   | ||||
| @@ -260,6 +260,9 @@ public: | ||||
| 	std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const; | ||||
| 	ui32 calculateSpellBonus(ui32 baseDamage, const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const; | ||||
| 	ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature, int spellSchoolLevel, int usedSpellPower) const; //calculates damage inflicted by spell | ||||
| 	ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack, const CStack * sacrificedStack = nullptr) const; //Sacrifice | ||||
| 	ui32 calculateHealedHP(int healedHealth, const CSpell * spell, const CStack * stack) const; //for Archangel | ||||
| 	ui32 calculateHealedHP(const CSpell * spell, int usedSpellPower, int spellSchoolLevel, const CStack * stack) const; //healing spells casted by stacks | ||||
| 	std::set<const CStack*> getAffectedCreatures(const CSpell * s, int skillLevel, PlayerColor attackerOwner, BattleHex destinationTile); //calculates stack affected by given spell | ||||
|  | ||||
| 	SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const; | ||||
|   | ||||
| @@ -1403,12 +1403,12 @@ DLL_LINKAGE void StacksHealedOrResurrected::applyGs( CGameState *gs ) | ||||
| 		if(resurrected) | ||||
| 		{ | ||||
| 			changedStack->state.insert(EBattleStackState::ALIVE); | ||||
| 			if(elem.lowLevelResurrection) | ||||
| 				changedStack->state.insert(EBattleStackState::SUMMONED); //TODO: different counter for rised units | ||||
| 		} | ||||
| 		//int missingHPfirst = changedStack->MaxHealth() - changedStack->firstHPleft; | ||||
| 		int res = std::min( elem.healedHP / changedStack->MaxHealth() , changedStack->baseAmount - changedStack->count ); | ||||
| 		changedStack->count += res; | ||||
| 		if(elem.lowLevelResurrection) | ||||
| 			changedStack->resurrected += res; | ||||
| 		changedStack->firstHPleft += elem.healedHP - res * changedStack->MaxHealth(); | ||||
| 		if(changedStack->firstHPleft > changedStack->MaxHealth()) | ||||
| 		{ | ||||
|   | ||||
| @@ -6266,6 +6266,9 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CArmedInstance *army, BattleI | ||||
| 		if(vstd::contains(st->state, EBattleStackState::SUMMONED)) //don't take into account summoned stacks | ||||
| 			continue; | ||||
|  | ||||
| 		//FIXME: this info is also used in BattleInfo::calculateCasualties, refactor | ||||
| 		st->count = std::max (0, st->count - st->resurrected); | ||||
|  | ||||
| 		if(st->owner==color && !army->slotEmpty(st->slot) && st->count < army->getStackCount(st->slot)) | ||||
| 		{ | ||||
| 			StackLocation sl(army, st->slot); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user