فهرست منبع

Fixed #860 and #1169
Imprisoned heroes as well as their commanders will get full level ups, with updated specialty, mana and movement.

DjWarmonger 13 سال پیش
والد
کامیت
e63747d2d2
7فایلهای تغییر یافته به همراه107 افزوده شده و 50 حذف شده
  1. 13 0
      Global.h
  2. 2 0
      client/NetPacksClient.cpp
  3. 2 15
      lib/CCreatureHandler.cpp
  4. 1 3
      lib/CGameState.cpp
  5. 23 10
      lib/CObjectHandler.cpp
  6. 2 1
      lib/GameConstants.h
  7. 64 21
      server/CGameHandler.cpp

+ 13 - 0
Global.h

@@ -481,6 +481,19 @@ namespace vstd
 			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;

+ 2 - 0
client/NetPacksClient.cpp

@@ -537,6 +537,8 @@ void HeroLevelUp::applyCl( CClient *cl )
 	{
 		cl->playerint[h->tempOwner]->heroGotLevel(h, static_cast<int>(primskill), skills, queryID);
 	}
+	//else
+	//	cb->selectionMade(0, queryID);
 }
 
 void CommanderLevelUp::applyCl( CClient *cl )

+ 2 - 15
lib/CCreatureHandler.cpp

@@ -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 r = 0;
@@ -1031,7 +1018,7 @@ int CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, i
 	{
 		do 
 		{
-			r = pickRandomElementOf(creatures, randGen)->idNumber;
+			r = vstd::pickRandomElementOf(creatures, randGen)->idNumber;
 		} while (vstd::contains(VLC->creh->notUsedMonsters,r));
 	}
 	else
@@ -1052,7 +1039,7 @@ int CCreatureHandler::pickRandomMonster(const boost::function<int()> &randGen, i
 			return 0;
 		}
 
-		return pickRandomElementOf(allowed, randGen);
+		return vstd::pickRandomElementOf(allowed, randGen);
 	}
 	return r;
 }

+ 1 - 3
lib/CGameState.cpp

@@ -1317,7 +1317,7 @@ void CGameState::init(StartInfo * si)
 	}
 
 	/*************************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)
 	{
 		k->second.fogOfWarMap.resize(map->width);
@@ -1520,8 +1520,6 @@ void CGameState::init(StartInfo * si)
 	BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 	{
 		obj->initObj();
-		if(obj->ID == Obj::PRISON) //prison also needs to initialize hero
-			static_cast<CGHeroInstance*>(obj)->initHero();
 	}
 	BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 	{

+ 23 - 10
lib/CObjectHandler.cpp

@@ -758,14 +758,6 @@ void CGHeroInstance::initHero()
 		secSkills = type->secSkillsInit;
 	if (!name.length())
 		name = type->name;
-	if (exp == 0xffffffff)
-	{
-		initExp();
-	}
-	else
-	{
-		level = VLC->heroh->level(exp);
-	}
 
 	if (sex == 0xFF)//sex is default
 		sex = type->sex;
@@ -781,6 +773,20 @@ void CGHeroInstance::initHero()
 	{
 		commander = new CCommanderInstance (VLC->townh->factions[type->heroClass->faction].commander);
 		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];
@@ -897,9 +903,16 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 	{
 		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);
+			//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->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?
 
 	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
 	{

+ 2 - 1
lib/GameConstants.h

@@ -94,7 +94,8 @@ namespace GameConstants
 // Enum declarations
 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

+ 64 - 21
server/CGameHandler.cpp

@@ -275,20 +275,37 @@ void CGameHandler::levelUpHero(int ID)
 		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));
-		applyAndAsk(&hlu,hero->tempOwner,callback); //call levelUpHero when client responds
-	}
-	else if(hlu.skills.size() == 1) //apply, give only possible skill  and send info
-	{
-		sendAndApply(&hlu);
-		levelUpHero(ID, hlu.skills.back());
+		sendAndApply (&hlu);
+		if (hlu.skills.size())
+		{
+			levelUpHero (ID, vstd::pickRandomElementOf (hlu.skills, rand));
+		}
+		else //apply and send info
+		{
+			levelUpHero(ID);
+		}
 	}
-	else //apply and send info
+	else
 	{
-		sendAndApply(&hlu);
-		levelUpHero(ID);
+		if(hlu.skills.size() > 1) //apply and ask for secondary skill
+		{
+			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));
+			applyAndAsk(&hlu,hero->tempOwner,callback); //call levelUpHero when client responds
+		}
+		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();
 
-	if (skillAmount > 1) //apply and ask for secondary skill
-	{
-		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
+	if (hero->tempOwner == GameConstants::NEUTRAL_PLAYER) //choose skill automatically
 	{
 		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);
-		levelUpCommander(c);
+		if (skillAmount > 1) //apply and ask for secondary skill
+		{
+			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
 	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)
 	{
 		n.specialWeek = NewTurn::NORMAL;