From e63747d2d20e1972dd9ac1c19a199715dcaf2498 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Mon, 4 Feb 2013 12:32:53 +0000 Subject: [PATCH] Fixed #860 and #1169 Imprisoned heroes as well as their commanders will get full level ups, with updated specialty, mana and movement. --- Global.h | 13 ++++++ client/NetPacksClient.cpp | 2 + lib/CCreatureHandler.cpp | 17 +------- lib/CGameState.cpp | 4 +- lib/CObjectHandler.cpp | 33 ++++++++++----- lib/GameConstants.h | 3 +- server/CGameHandler.cpp | 85 +++++++++++++++++++++++++++++---------- 7 files changed, 107 insertions(+), 50 deletions(-) diff --git a/Global.h b/Global.h index 919cec8a8..863c41b44 100644 --- a/Global.h +++ b/Global.h @@ -481,6 +481,19 @@ namespace vstd return vf(lhs) < vf(rhs); }); } + + static int retreiveRandNum(const boost::function &randGen) + { + if (randGen) + return randGen(); + else + return rand(); + } + + template const T & pickRandomElementOf(const std::vector &v, const boost::function &randGen) + { + return v.at(retreiveRandNum(randGen) % v.size()); + } } using std::shared_ptr; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 69e4bb551..1c698ecf7 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -537,6 +537,8 @@ void HeroLevelUp::applyCl( CClient *cl ) { cl->playerint[h->tempOwner]->heroGotLevel(h, static_cast(primskill), skills, queryID); } + //else + // cb->selectionMade(0, queryID); } void CommanderLevelUp::applyCl( CClient *cl ) diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 5c86e9164..5e49cfbf3 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -1011,19 +1011,6 @@ CCreatureHandler::~CCreatureHandler() { } -static int retreiveRandNum(const boost::function &randGen) -{ - if(randGen) - return randGen(); - else - return rand(); -} - -template const T & pickRandomElementOf(const std::vector &v, const boost::function &randGen) -{ - return v.at(retreiveRandNum(randGen) % v.size()); -} - int CCreatureHandler::pickRandomMonster(const boost::function &randGen, int tier) const { int r = 0; @@ -1031,7 +1018,7 @@ int CCreatureHandler::pickRandomMonster(const boost::function &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 &randGen, i return 0; } - return pickRandomElementOf(allowed, randGen); + return vstd::pickRandomElementOf(allowed, randGen); } return r; } diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 9a5fb1912..13aa1ae92 100644 --- a/lib/CGameState.cpp +++ b/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(obj)->initHero(); } BOOST_FOREACH(CGObjectInstance *obj, map->objects) { diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 362788f08..4a8452728 100644 --- a/lib/CObjectHandler.cpp +++ b/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 { diff --git a/lib/GameConstants.h b/lib/GameConstants.h index e0b8512f3..5696e59d2 100644 --- a/lib/GameConstants.h +++ b/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 diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 81d072642..3ea8f5b37 100644 --- a/server/CGameHandler.cpp +++ b/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 callback = boost::function(boost::bind(callWith,hlu.skills,boost::function(boost::bind(&CGameHandler::levelUpHero,this,ID,_1)),_1)); - applyAndAsk(&hlu,hero->tempOwner,callback); //call levelUpHero when client responds + sendAndApply (&hlu); + 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); - levelUpHero(ID, hlu.skills.back()); - } - else //apply and send info - { - sendAndApply(&hlu); - levelUpHero(ID); + if(hlu.skills.size() > 1) //apply and ask for secondary skill + { + boost::function callback = boost::function(boost::bind + (callWith, hlu.skills, boost::function(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(boost::bind(callWith, clu.skills, boost::function(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(boost::bind(callWith, clu.skills, boost::function(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 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;