Преглед изворни кода

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

DjWarmonger пре 12 година
родитељ
комит
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;