mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	* Necromancy implemented. Not sure if they client/server communication is right, but it works.
* Cloak of the Undead King implemented as well.
This commit is contained in:
		| @@ -1013,6 +1013,79 @@ bool CGHeroInstance::canCastThisSpell(const CSpell * spell) const | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Calculates what creatures and how many to be raised from a battle. | ||||
|  * @param battleResult The results of the battle. | ||||
|  * @return Returns a pair with the first value indicating the ID of the creature | ||||
|  * type and second value the amount. Both values are returned as -1 if necromancy | ||||
|  * could not be applied. | ||||
|  */ | ||||
| std::pair<ui32, si32> CGHeroInstance::calculateNecromancy (BattleResult &battleResult) const | ||||
| { | ||||
| 	const ui8 necromancyLevel = getSecSkillLevel(12); | ||||
|  | ||||
| 	// Hero knows necromancy. | ||||
| 	if (necromancyLevel > 0) { | ||||
| 		double necromancySkill = necromancyLevel*0.1 | ||||
| 			+ valOfBonuses(HeroBonus::SECONDARY_SKILL_PREMY, 12)/100.0; | ||||
| 		const std::set<std::pair<ui32, si32> > &casualties = battleResult.casualties[!battleResult.winner]; | ||||
| 		ui32 raisedUnits = 0; | ||||
|  | ||||
| 		// Get lost enemy hit points convertible to units. | ||||
| 		for (std::set<std::pair<ui32, si32> >::const_iterator it = casualties.begin(); it != casualties.end(); it++) | ||||
| 			raisedUnits += VLC->creh->creatures[it->first].hitPoints*it->second; | ||||
| 		raisedUnits *= necromancySkill; | ||||
|  | ||||
| 		// Figure out what to raise and how many. | ||||
| 		const ui32 creatureTypes[] = {56, 58, 60, 64}; // IDs for Skeletons, Walking Dead, Wights and Liches respectively. | ||||
| 		const bool improvedNecromancy = hasBonusOfType(HeroBonus::IMPROVED_NECROMANCY); | ||||
| 		CCreature *raisedUnitType = &VLC->creh->creatures[creatureTypes[improvedNecromancy ? necromancyLevel : 0]]; | ||||
|  | ||||
| 		raisedUnits /= raisedUnitType->hitPoints; | ||||
|  | ||||
| 		// Make room for new units. | ||||
| 		int slot = army.getSlotFor(raisedUnitType->idNumber); | ||||
| 		if (slot == -1) { | ||||
| 			// If there's no room for unit, try it's upgraded version 2/3rds the size. | ||||
| 			raisedUnitType = &VLC->creh->creatures[*raisedUnitType->upgrades.begin()]; | ||||
| 			raisedUnits = (raisedUnits*2)/3; | ||||
|  | ||||
| 			slot = army.getSlotFor(raisedUnitType->idNumber); | ||||
| 		} | ||||
| 		if (raisedUnits <= 0) | ||||
| 			raisedUnits = 1; | ||||
|  | ||||
| 		return std::pair<ui32, si32>(raisedUnitType->idNumber, raisedUnits); | ||||
| 	} | ||||
|  | ||||
| 	return std::pair<ui32, si32>(-1, -1); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Show the necromancy dialog with information about units raised. | ||||
|  * @param raisedStack Pair where the first element represents ID of the raised creature | ||||
|  * and the second element the amount. | ||||
|  */ | ||||
| void CGHeroInstance::showNecromancyDialog (std::pair<ui32, si32> raisedStack) const | ||||
| { | ||||
| 	const CCreature &unitType = VLC->creh->creatures[raisedStack.first]; | ||||
| 	InfoWindow iw; | ||||
| 	iw.soundID = soundBase::GENIE; | ||||
| 	iw.player = tempOwner; | ||||
| 	iw.components.push_back(Component(3, unitType.idNumber, raisedStack.second, 0)); | ||||
|  | ||||
| 	if (raisedStack.second > 1) { // Practicing the dark arts of necromancy, ... (plural) | ||||
| 		iw.text.addTxt(MetaString::GENERAL_TXT, 145); | ||||
| 		iw.text.addReplacement(raisedStack.second); | ||||
| 		iw.text.addReplacement(MetaString::CRE_PL_NAMES, unitType.idNumber); | ||||
| 	} else { // Practicing the dark arts of necromancy, ... (singular) | ||||
| 		iw.text.addTxt(MetaString::GENERAL_TXT, 146); | ||||
| 		iw.text.addReplacement(MetaString::CRE_SING_NAMES, unitType.idNumber); | ||||
| 	} | ||||
|  | ||||
| 	cb->showInfoDialog(&iw); | ||||
| } | ||||
|  | ||||
| int3 CGHeroInstance::getSightCenter() const | ||||
| { | ||||
| 	return getPosition(false); | ||||
|   | ||||
| @@ -293,6 +293,8 @@ public: | ||||
| 	int getTotalStrength() const; | ||||
| 	ui8 getSpellSchoolLevel(const CSpell * spell) const; //returns level on which given spell would be cast by this hero | ||||
| 	bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses | ||||
| 	std::pair<ui32, si32> calculateNecromancy (BattleResult &battleResult) const; | ||||
| 	void showNecromancyDialog (std::pair<ui32, si32> raisedStack) const; | ||||
|  | ||||
| 	////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|   | ||||
| @@ -450,9 +450,32 @@ askInterfaceForMove: | ||||
| 	if(cb) | ||||
| 		cb(battleResult.data); | ||||
|  | ||||
| 	delete battleResult.data; | ||||
| 	 | ||||
| 	sendAndApply(&resultsApplied); | ||||
|  | ||||
| 	// Necromancy if applicable. | ||||
| 	const CGHeroInstance *winnerHero = battleResult.data->winner != 0 ? hero2 : hero1; | ||||
| 	if (winnerHero) { | ||||
| 		std::pair<ui32, si32> raisedStack = winnerHero->calculateNecromancy(*battleResult.data); | ||||
|  | ||||
| 		// Give raised units to winner and show dialog, if any were raised. | ||||
| 		if (raisedStack.first != -1) { | ||||
| 			int slot = winnerHero->army.getSlotFor(raisedStack.first); | ||||
|  | ||||
| 			if (slot != -1) { | ||||
| 				SetGarrisons sg; | ||||
|  | ||||
| 				sg.garrs[winnerHero->id] = winnerHero->army; | ||||
| 				if (vstd::contains(winnerHero->army.slots, slot)) // Add to existing stack. | ||||
| 					sg.garrs[winnerHero->id].slots[slot].second += raisedStack.second; | ||||
| 				else // Create a new stack. | ||||
| 					sg.garrs[winnerHero->id].slots[slot] = raisedStack; | ||||
| 				winnerHero->showNecromancyDialog(raisedStack); | ||||
| 				sendAndApply(&sg); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	delete battleResult.data; | ||||
| } | ||||
|  | ||||
| void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, CStack *def) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user