mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Merge pull request #678 from MikeLodz/develop
Fixes mantis tickets 2899 and 2984 (bugged hero spell specialties)
This commit is contained in:
		| @@ -325,6 +325,11 @@ | ||||
| 		"class" : "elementalist", | ||||
| 		"female": true, | ||||
| 		"spellbook": [ "stoneSkin" ], | ||||
| 		"texts" : { | ||||
| 			"specialty" : { | ||||
| 				"description" : "{Stone Skin}\r\n\r\nCasts Stone Skin with increased effect, based on the level of the target unit. (The bonus is greater when used on weaker units)" | ||||
| 			} | ||||
| 		}, | ||||
| 		"skills": | ||||
| 		[ | ||||
| 			{ "skill" : "wisdom", "level": "basic" }, | ||||
| @@ -375,9 +380,9 @@ | ||||
| 		"specialty" : { | ||||
| 			"bonuses" : { | ||||
| 				"disruptingRay" : { | ||||
| 					"addInfo" : 0, | ||||
| 					"addInfo" : -2, | ||||
| 					"subtype" : "spell.disruptingRay", | ||||
| 					"type" : "SPECIAL_PECULIAR_ENCHANT" | ||||
| 					"type" : "SPECIAL_ADD_VALUE_ENCHANT" | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -265,8 +265,9 @@ | ||||
| 		"specialty" : { | ||||
| 			"bonuses" : { | ||||
| 				"fortune" : { | ||||
| 					"addInfo" : 3, | ||||
| 					"subtype" : "spell.fortune", | ||||
| 					"type" : "MAXED_SPELL" | ||||
| 					"type" : "SPECIAL_FIXED_VALUE_ENCHANT" | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -1468,6 +1468,8 @@ JsonNode subtypeToJson(Bonus::BonusType type, int subtype) | ||||
| 	case Bonus::SPECIAL_BLESS_DAMAGE: | ||||
| 	case Bonus::MAXED_SPELL: | ||||
| 	case Bonus::SPECIAL_PECULIAR_ENCHANT: | ||||
| 	case Bonus::SPECIAL_ADD_VALUE_ENCHANT: | ||||
| 	case Bonus::SPECIAL_FIXED_VALUE_ENCHANT: | ||||
| 		return JsonUtils::stringNode("spell." + (*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier); | ||||
| 	case Bonus::IMPROVED_NECROMANCY: | ||||
| 	case Bonus::SPECIAL_UPGRADE: | ||||
| @@ -1556,6 +1558,8 @@ std::string Bonus::nameForBonus() const | ||||
| 	case Bonus::SPECIAL_BLESS_DAMAGE: | ||||
| 	case Bonus::MAXED_SPELL: | ||||
| 	case Bonus::SPECIAL_PECULIAR_ENCHANT: | ||||
| 	case Bonus::SPECIAL_ADD_VALUE_ENCHANT: | ||||
| 	case Bonus::SPECIAL_FIXED_VALUE_ENCHANT: | ||||
| 		return (*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier; | ||||
| 	case Bonus::SPECIAL_UPGRADE: | ||||
| 		return CreatureID::encode(subtype) + "2" + CreatureID::encode(additionalInfo[0]); | ||||
|   | ||||
| @@ -321,6 +321,8 @@ public: | ||||
| 	BONUS_NAME(SPECIAL_CRYSTAL_GENERATION) /*crystal dragon crystal generation*/ \ | ||||
| 	BONUS_NAME(NO_SPELLCAST_BY_DEFAULT) /*spellcast will not be default attack option for this creature*/ \ | ||||
| 	BONUS_NAME(GARGOYLE) /* gargoyle is special than NON_LIVING, cannot be rised or healed */ \ | ||||
| 	BONUS_NAME(SPECIAL_ADD_VALUE_ENCHANT) /*specialty spell like Aenin has, increased effect of spell, additionalInfo = value to add*/\ | ||||
| 	BONUS_NAME(SPECIAL_FIXED_VALUE_ENCHANT) /*specialty spell like Melody has, constant spell effect (i.e. 3 luck), additionalInfo = value to fix.*/\ | ||||
|  | ||||
| 	/* end of list */ | ||||
|  | ||||
|   | ||||
| @@ -791,7 +791,15 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info) | ||||
| 		} | ||||
|  | ||||
| 		if(isAffected) | ||||
| 		{  | ||||
| 			attackDefenceDifference += SpellID(SpellID::SLAYER).toSpell()->getPower(spLevel); | ||||
| 			if(info.attacker->hasBonusOfType(Bonus::SPECIAL_PECULIAR_ENCHANT, SpellID::SLAYER)) | ||||
| 			{ | ||||
| 				ui8 attackerTier = info.attacker->unitType()->level; | ||||
| 				ui8 specialtyBonus = std::max(5 - attackerTier, 0); | ||||
| 				attackDefenceDifference += specialtyBonus; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//bonus from attack/defense skills | ||||
|   | ||||
| @@ -151,10 +151,16 @@ void Timed::prepareEffects(SetStackEffect & sse, const Mechanics * m, const Effe | ||||
| 	std::vector<Bonus> converted; | ||||
|     convertBonus(m, duration, converted); | ||||
|  | ||||
| 	std::shared_ptr<const Bonus> bonus = nullptr; | ||||
| 	std::shared_ptr<const Bonus> peculiarBonus = nullptr; | ||||
| 	std::shared_ptr<const Bonus> addedValueBonus = nullptr; | ||||
| 	std::shared_ptr<const Bonus> fixedValueBonus = nullptr;  | ||||
| 	auto casterHero = dynamic_cast<const CGHeroInstance *>(m->caster); | ||||
| 	if(casterHero) | ||||
| 		bonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_PECULIAR_ENCHANT, m->getSpellIndex())); | ||||
| 	{  | ||||
| 		peculiarBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_PECULIAR_ENCHANT, m->getSpellIndex())); | ||||
| 		addedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_ADD_VALUE_ENCHANT, m->getSpellIndex())); | ||||
| 		fixedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_FIXED_VALUE_ENCHANT, m->getSpellIndex())); | ||||
| 	} | ||||
| 	//TODO: does hero specialty should affects his stack casting spells? | ||||
|  | ||||
| 	for(auto & t : target) | ||||
| @@ -175,16 +181,17 @@ void Timed::prepareEffects(SetStackEffect & sse, const Mechanics * m, const Effe | ||||
| 		if(describe) | ||||
| 			describeEffect(sse.battleLog, m, converted, affected); | ||||
|  | ||||
| 		si32 power = 0; | ||||
| 		const auto tier = std::max(affected->creatureLevel(), 1); //don't divide by 0 for certain creatures (commanders, war machines) | ||||
|  | ||||
| 		//Apply hero specials - peculiar enchants | ||||
| 		const auto tier = std::max(affected->creatureLevel(), 1); //don't divide by 0 for certain creatures (commanders, war machines) | ||||
| 		if(bonus) | ||||
| 		if(peculiarBonus) | ||||
| 		{ | ||||
| 			switch(bonus->additionalInfo[0]) | ||||
|  | ||||
| 			si32 power = 0; | ||||
| 			switch (peculiarBonus->additionalInfo[0]) | ||||
| 			{ | ||||
| 			case 0: //normal | ||||
| 				switch(tier) | ||||
| 				switch (tier) | ||||
| 				{ | ||||
| 				case 1: | ||||
| 				case 2: | ||||
| @@ -199,23 +206,36 @@ void Timed::prepareEffects(SetStackEffect & sse, const Mechanics * m, const Effe | ||||
| 					power = 1; | ||||
| 					break; | ||||
| 				} | ||||
| 				for(const Bonus & b : converted) | ||||
| 				{ | ||||
| 					Bonus specialBonus(b); | ||||
| 					specialBonus.val = power; //it doesn't necessarily make sense for some spells, use it wisely | ||||
| 					specialBonus.turnsRemain = duration; | ||||
|  | ||||
| 					//additional premy to given effect | ||||
| 					buffer.push_back(specialBonus); | ||||
| 				} | ||||
| 				break; | ||||
| 			case 1: //only Coronius as yet | ||||
| 			case 1:  | ||||
| 				//Coronius style specialty bonus. | ||||
| 				//Please note that actual Coronius isnt here, because Slayer is a spell that doesnt affect monster stats and is used only in calculateDmgRange | ||||
| 				power = std::max(5 - tier, 0); | ||||
| 				Bonus specialBonus(Bonus::N_TURNS, Bonus::PRIMARY_SKILL, Bonus::SPELL_EFFECT, power, m->getSpellIndex(), PrimarySkill::ATTACK); | ||||
| 				specialBonus.turnsRemain = duration; | ||||
| 				buffer.push_back(specialBonus); | ||||
| 				break; | ||||
| 			} | ||||
| 			if(m->isNegativeSpell()) | ||||
| 			{ | ||||
| 				//negative spells like weakness are defined in json with negative numbers, so we need do same here | ||||
| 				power = -1 * power; | ||||
| 			} | ||||
| 			for(Bonus& b : buffer) | ||||
| 			{ | ||||
| 				b.val += power; | ||||
| 			} | ||||
| 		} | ||||
| 		if(addedValueBonus) | ||||
| 		{ | ||||
| 			for(Bonus& b : buffer) | ||||
| 			{ | ||||
| 				b.val += addedValueBonus->additionalInfo[0]; | ||||
| 			} | ||||
| 		} | ||||
| 		if(fixedValueBonus) | ||||
| 		{ | ||||
| 			for(Bonus& b : buffer) | ||||
| 			{ | ||||
| 				b.val = fixedValueBonus->additionalInfo[0]; | ||||
| 			} | ||||
| 		} | ||||
| 		if(casterHero && casterHero->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, m->getSpellIndex())) //TODO: better handling of bonus percentages | ||||
| 		{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user