mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Imprisoned heroes as well as their commanders will get full level ups, with updated specialty, mana and movement.
This commit is contained in:
		
							
								
								
									
										13
									
								
								Global.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Global.h
									
									
									
									
									
								
							| @@ -481,6 +481,19 @@ namespace vstd | |||||||
| 			return vf(lhs) < vf(rhs); | 			return vf(lhs) < vf(rhs); | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	static int retreiveRandNum(const boost::function<int()> &randGen) | ||||||
|  | 	{ | ||||||
|  | 		if (randGen) | ||||||
|  | 			return randGen(); | ||||||
|  | 		else | ||||||
|  | 			return rand(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	template <typename T> const T & pickRandomElementOf(const std::vector<T> &v, const boost::function<int()> &randGen) | ||||||
|  | 	{ | ||||||
|  | 		return v.at(retreiveRandNum(randGen) % v.size()); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| using std::shared_ptr; | using std::shared_ptr; | ||||||
|   | |||||||
| @@ -537,6 +537,8 @@ void HeroLevelUp::applyCl( CClient *cl ) | |||||||
| 	{ | 	{ | ||||||
| 		cl->playerint[h->tempOwner]->heroGotLevel(h, static_cast<int>(primskill), skills, queryID); | 		cl->playerint[h->tempOwner]->heroGotLevel(h, static_cast<int>(primskill), skills, queryID); | ||||||
| 	} | 	} | ||||||
|  | 	//else | ||||||
|  | 	//	cb->selectionMade(0, queryID); | ||||||
| } | } | ||||||
|  |  | ||||||
| void CommanderLevelUp::applyCl( CClient *cl ) | void CommanderLevelUp::applyCl( CClient *cl ) | ||||||
|   | |||||||
| @@ -1011,19 +1011,6 @@ CCreatureHandler::~CCreatureHandler() | |||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| static int retreiveRandNum(const boost::function<int()> &randGen) |  | ||||||
| { |  | ||||||
| 	if(randGen) |  | ||||||
| 		return randGen(); |  | ||||||
| 	else |  | ||||||
| 		return rand(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> const T & pickRandomElementOf(const std::vector<T> &v, const boost::function<int()> &randGen) |  | ||||||
| { |  | ||||||
| 	return v.at(retreiveRandNum(randGen) % v.size()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, int tier) const | int CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, int tier) const | ||||||
| { | { | ||||||
| 	int r = 0; | 	int r = 0; | ||||||
| @@ -1031,7 +1018,7 @@ int CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, i | |||||||
| 	{ | 	{ | ||||||
| 		do  | 		do  | ||||||
| 		{ | 		{ | ||||||
| 			r = pickRandomElementOf(creatures, randGen)->idNumber; | 			r = vstd::pickRandomElementOf(creatures, randGen)->idNumber; | ||||||
| 		} while (vstd::contains(VLC->creh->notUsedMonsters,r)); | 		} while (vstd::contains(VLC->creh->notUsedMonsters,r)); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| @@ -1052,7 +1039,7 @@ int CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, i | |||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		return pickRandomElementOf(allowed, randGen); | 		return vstd::pickRandomElementOf(allowed, randGen); | ||||||
| 	} | 	} | ||||||
| 	return r; | 	return r; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1317,7 +1317,7 @@ void CGameState::init(StartInfo * si) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/*************************FOG**OF**WAR******************************************/ | 	/*************************FOG**OF**WAR******************************************/ | ||||||
| 	tlog4 << "\tFog of war"; | 	tlog4 << "\tFog of war"; //FIXME: should be initialized after all bonuses are set | ||||||
| 	for(auto k=teams.begin(); k!=teams.end(); ++k) | 	for(auto k=teams.begin(); k!=teams.end(); ++k) | ||||||
| 	{ | 	{ | ||||||
| 		k->second.fogOfWarMap.resize(map->width); | 		k->second.fogOfWarMap.resize(map->width); | ||||||
| @@ -1520,8 +1520,6 @@ void CGameState::init(StartInfo * si) | |||||||
| 	BOOST_FOREACH(CGObjectInstance *obj, map->objects) | 	BOOST_FOREACH(CGObjectInstance *obj, map->objects) | ||||||
| 	{ | 	{ | ||||||
| 		obj->initObj(); | 		obj->initObj(); | ||||||
| 		if(obj->ID == Obj::PRISON) //prison also needs to initialize hero |  | ||||||
| 			static_cast<CGHeroInstance*>(obj)->initHero(); |  | ||||||
| 	} | 	} | ||||||
| 	BOOST_FOREACH(CGObjectInstance *obj, map->objects) | 	BOOST_FOREACH(CGObjectInstance *obj, map->objects) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -758,14 +758,6 @@ void CGHeroInstance::initHero() | |||||||
| 		secSkills = type->secSkillsInit; | 		secSkills = type->secSkillsInit; | ||||||
| 	if (!name.length()) | 	if (!name.length()) | ||||||
| 		name = type->name; | 		name = type->name; | ||||||
| 	if (exp == 0xffffffff) |  | ||||||
| 	{ |  | ||||||
| 		initExp(); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		level = VLC->heroh->level(exp); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (sex == 0xFF)//sex is default | 	if (sex == 0xFF)//sex is default | ||||||
| 		sex = type->sex; | 		sex = type->sex; | ||||||
| @@ -781,6 +773,20 @@ void CGHeroInstance::initHero() | |||||||
| 	{ | 	{ | ||||||
| 		commander = new CCommanderInstance (VLC->townh->factions[type->heroClass->faction].commander); | 		commander = new CCommanderInstance (VLC->townh->factions[type->heroClass->faction].commander); | ||||||
| 		commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders | 		commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders | ||||||
|  | 		commander->giveStackExp (exp); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (exp == 0xffffffff) | ||||||
|  | 	{ | ||||||
|  | 		initExp(); | ||||||
|  | 	} | ||||||
|  | 	else if (ID != Obj::PRISON) | ||||||
|  | 	{ | ||||||
|  | 		level = VLC->heroh->level(exp); | ||||||
|  | 	} | ||||||
|  | 	else //warp hero at the beginning of next turn | ||||||
|  | 	{ | ||||||
|  | 		level = 1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hoverName = VLC->generaltexth->allTexts[15]; | 	hoverName = VLC->generaltexth->allTexts[15]; | ||||||
| @@ -897,9 +903,16 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const | |||||||
| 	{ | 	{ | ||||||
| 		int txt_id; | 		int txt_id; | ||||||
|  |  | ||||||
| 		if(cb->getHeroCount(h->tempOwner,false) < 8) //free hero slot | 		if(cb->getHeroCount(h->tempOwner,false) < GameConstants::MAX_HEROES_PER_PLAYER) //free hero slot | ||||||
| 		{ | 		{ | ||||||
| 			cb->changeObjPos(id,pos+int3(1,0,0),0); | 			cb->changeObjPos(id,pos+int3(1,0,0),0); | ||||||
|  | 			//update hero parameters | ||||||
|  | 			SetMovePoints smp; | ||||||
|  | 			smp.hid = id; | ||||||
|  | 			smp.val = maxMovePoints (true); //TODO: hota prison on water? | ||||||
|  | 			cb->setMovePoints (&smp); | ||||||
|  | 			cb->setManaPoints (id, manaLimit()); | ||||||
|  |  | ||||||
| 			cb->setObjProperty(id, ObjProperty::ID, Obj::HERO); //set ID to 34 | 			cb->setObjProperty(id, ObjProperty::ID, Obj::HERO); //set ID to 34 | ||||||
| 			cb->giveHero(id,h->tempOwner); //recreates def and adds hero to player | 			cb->giveHero(id,h->tempOwner); //recreates def and adds hero to player | ||||||
|  |  | ||||||
| @@ -928,7 +941,7 @@ void CGHeroInstance::initObj() //TODO: use bonus system | |||||||
| 	attachTo(hs); //do we ever need to detach it? | 	attachTo(hs); //do we ever need to detach it? | ||||||
|  |  | ||||||
| 	if(!type) | 	if(!type) | ||||||
| 		return; //TODO: support prison | 		initHero(); //TODO: set up everything for prison before specialties are configured | ||||||
|  |  | ||||||
| 	BOOST_FOREACH(const auto &spec, type->spec) //TODO: unfity with bonus system | 	BOOST_FOREACH(const auto &spec, type->spec) //TODO: unfity with bonus system | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -94,7 +94,8 @@ namespace GameConstants | |||||||
| // Enum declarations | // Enum declarations | ||||||
| namespace PrimarySkill | namespace PrimarySkill | ||||||
| { | { | ||||||
| 	enum PrimarySkill { ATTACK, DEFENSE, SPELL_POWER, KNOWLEDGE}; | 	enum PrimarySkill { ATTACK, DEFENSE, SPELL_POWER, KNOWLEDGE, | ||||||
|  | 				EXPERIENCE = 4}; //for some reason changePrimSkill uses it | ||||||
| } | } | ||||||
|  |  | ||||||
| namespace EVictoryConditionType | namespace EVictoryConditionType | ||||||
|   | |||||||
| @@ -275,20 +275,37 @@ void CGameHandler::levelUpHero(int ID) | |||||||
| 		hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(basicAndAdv)); //upgrade existing | 		hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(basicAndAdv)); //upgrade existing | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if(hlu.skills.size() > 1) //apply and ask for secondary skill | 	if (hero->tempOwner == GameConstants::NEUTRAL_PLAYER) //choose skill automatically | ||||||
| 	{ | 	{ | ||||||
| 		boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind(callWith<ui16>,hlu.skills,boost::function<void(ui16)>(boost::bind(&CGameHandler::levelUpHero,this,ID,_1)),_1)); | 		sendAndApply (&hlu); | ||||||
| 		applyAndAsk(&hlu,hero->tempOwner,callback); //call levelUpHero when client responds | 		if (hlu.skills.size()) | ||||||
|  | 		{ | ||||||
|  | 			levelUpHero (ID, vstd::pickRandomElementOf (hlu.skills, rand)); | ||||||
|  | 		} | ||||||
|  | 		else //apply and send info | ||||||
|  | 		{ | ||||||
|  | 			levelUpHero(ID); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	else if(hlu.skills.size() == 1) //apply, give only possible skill  and send info | 	else | ||||||
| 	{ | 	{ | ||||||
| 		sendAndApply(&hlu); | 		if(hlu.skills.size() > 1) //apply and ask for secondary skill | ||||||
| 		levelUpHero(ID, hlu.skills.back()); | 		{ | ||||||
| 	} | 			boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind  | ||||||
| 	else //apply and send info | 					(callWith<ui16>, hlu.skills, boost::function<void(ui16)>(boost::bind | ||||||
| 	{ | 					(&CGameHandler::levelUpHero, this, ID,_1) ), _1)); | ||||||
| 		sendAndApply(&hlu); | 			applyAndAsk(&hlu,hero->tempOwner,callback); //call levelUpHero when client responds | ||||||
| 		levelUpHero(ID); | 		} | ||||||
|  | 		else if(hlu.skills.size() == 1) //apply, give only possible skill  and send info | ||||||
|  | 		{ | ||||||
|  | 			sendAndApply(&hlu); | ||||||
|  | 			levelUpHero(ID, hlu.skills.back()); | ||||||
|  | 		} | ||||||
|  | 		else //apply and send info | ||||||
|  | 		{ | ||||||
|  | 			sendAndApply(&hlu); | ||||||
|  | 			levelUpHero(ID); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -407,20 +424,35 @@ void CGameHandler::levelUpCommander(const CCommanderInstance * c) | |||||||
| 	} | 	} | ||||||
| 	int skillAmount = clu.skills.size(); | 	int skillAmount = clu.skills.size(); | ||||||
|  |  | ||||||
| 	if (skillAmount > 1) //apply and ask for secondary skill | 	if (hero->tempOwner == GameConstants::NEUTRAL_PLAYER) //choose skill automatically | ||||||
| 	{ |  | ||||||
| 		auto callback = boost::function<void(ui32)>(boost::bind(callWith<ui32>, clu.skills, boost::function<void(ui32)>(boost::bind(&CGameHandler::levelUpCommander, this, c, _1)), _1)); |  | ||||||
| 		applyAndAsk (&clu, c->armyObj->tempOwner, callback); //call levelUpCommander when client responds |  | ||||||
| 	} |  | ||||||
| 	else if (skillAmount == 1) //apply, give only possible skill and send info |  | ||||||
| 	{ | 	{ | ||||||
| 		sendAndApply(&clu); | 		sendAndApply(&clu); | ||||||
| 		levelUpCommander(c, clu.skills.back()); | 		if (clu.skills.size()) | ||||||
|  | 		{ | ||||||
|  | 			levelUpCommander(c, vstd::pickRandomElementOf (clu.skills, rand)); | ||||||
|  | 		} | ||||||
|  | 		else //apply and send info | ||||||
|  | 		{ | ||||||
|  | 			levelUpCommander(c); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	else //apply and send info | 	else | ||||||
| 	{ | 	{ | ||||||
| 		sendAndApply(&clu); | 		if (skillAmount > 1) //apply and ask for secondary skill | ||||||
| 		levelUpCommander(c); | 		{ | ||||||
|  | 			auto callback = boost::function<void(ui32)>(boost::bind(callWith<ui32>, clu.skills, boost::function<void(ui32)>(boost::bind(&CGameHandler::levelUpCommander, this, c, _1)), _1)); | ||||||
|  | 			applyAndAsk (&clu, c->armyObj->tempOwner, callback); //call levelUpCommander when client responds | ||||||
|  | 		} | ||||||
|  | 		else if (skillAmount == 1) //apply, give only possible skill and send info | ||||||
|  | 		{ | ||||||
|  | 			sendAndApply(&clu); | ||||||
|  | 			levelUpCommander(c, clu.skills.back()); | ||||||
|  | 		} | ||||||
|  | 		else //apply and send info | ||||||
|  | 		{ | ||||||
|  | 			sendAndApply(&clu); | ||||||
|  | 			levelUpCommander(c); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1133,6 +1165,17 @@ void CGameHandler::newTurn() | |||||||
| 	std::map<ui8, si32> hadGold;//starting gold - for buildings like dwarven treasury | 	std::map<ui8, si32> hadGold;//starting gold - for buildings like dwarven treasury | ||||||
| 	srand(time(NULL)); | 	srand(time(NULL)); | ||||||
|  |  | ||||||
|  | 	if (firstTurn) | ||||||
|  | 	{ | ||||||
|  | 		BOOST_FOREACH (auto obj, gs->map->objects) | ||||||
|  | 		{ | ||||||
|  | 			if (obj->ID == Obj::PRISON) //give imprisoned hero 0 exp to level him up. easiest to do at this point | ||||||
|  | 			{ | ||||||
|  | 				changePrimSkill (obj->id, PrimarySkill::EXPERIENCE, 0); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if (newWeek && !firstTurn) | 	if (newWeek && !firstTurn) | ||||||
| 	{ | 	{ | ||||||
| 		n.specialWeek = NewTurn::NORMAL; | 		n.specialWeek = NewTurn::NORMAL; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user