1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Commanders can level up. It's non-interactive yet.

Printing secondary skills for Commanders.
This commit is contained in:
DjWarmonger
2012-05-18 14:02:27 +00:00
parent ed634a5f06
commit d491bc1c3a
19 changed files with 222 additions and 85 deletions

View File

@@ -22,8 +22,7 @@ public:
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel){};
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) {};
void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
void commanderGotLevel (const CCommanderInstance * commander, std::vector<std::pair<ui8, ui8> > secondarySkills,
std::vector<Bonus *> specialSkills, boost::function<void(ui32)> &callback) {};
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, boost::function<void(ui32)> &callback) {}; //TODO
};
#define NAME "EmptyAI 0.1"

View File

@@ -210,8 +210,7 @@ public:
virtual void init(CCallback * CB);
virtual void yourTurn();
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback) OVERRIDE; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<std::pair<ui8, ui8> > secondarySkills,
std::vector<Bonus *> specialSkills, boost::function<void(ui32)> &callback) {};
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, boost::function<void(ui32)> &callback) {}; //TODO
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) OVERRIDE; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) OVERRIDE; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void serialize(COSer<CSaveFile> &h, const int version) OVERRIDE; //saving

View File

@@ -301,8 +301,7 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
{
for (int i = ECommander::ATTACK; i <= ECommander::SPELL_POWER; ++i)
{
auto it = commander->secondarySkills.find(i);
if (it != commander->secondarySkills.end())
if (commander->secondarySkills[i])
{
std::string file = "zvs/Lib1.res/_";
switch (i)
@@ -326,10 +325,22 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
file += "MP";
break;
}
file += boost::lexical_cast<std::string>(it->second);
std::string sufix = boost::lexical_cast<std::string>((int)(commander->secondarySkills[i] - 1)); //casting ui8 causes ascii char conversion
if (type == COMMANDER_LEVEL_UP)
{
if (commander->secondarySkills[i] < ECommander::MAX_SKILL_LEVEL)
sufix += "="; //level-up highlight
else
sufix = "no"; //not avaliable - no number
}
file += sufix += ".bmp";
auto skillGraphics = new CPicture(file, 40 + i * 82, 121);
blitAtLoc(skillGraphics->bg, 0, 0, bitmap->bg);
//bonusGraphics = new CPicture(graphicsName, 26, 232);
//blitAtLoc(bonusGraphics->bg, 12, 2, bitmap->bg);
auto skillGraphics = new CPicture(file, 39 + i * 82, 223);
//if (skillGraphics->bg)
// blitAtLoc(skillGraphics->bg, 0, 0, bitmap->bg);
}
}
}

View File

@@ -40,7 +40,7 @@ class CAnimImage;
class CCreatureWindow : public CArtifactHolder
{
public:
enum CreWinType {OTHER = 0, BATTLE = 1, ARMY = 2, HERO = 3, COMMANDER = 4}; // > 3 are opened permanently
enum CreWinType {OTHER = 0, BATTLE = 1, ARMY = 2, HERO = 3, COMMANDER = 4, COMMANDER_LEVEL_UP = 5}; // > 3 are opened permanently
//bool active; //TODO: comment me
int type;//0 - rclick popup; 1 - normal window
int bonusRows; //height of skill window

View File

@@ -487,15 +487,20 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std:
CLevelWindow *lw = new CLevelWindow(hero,pskill,skills,callback);
GH.pushInt(lw);
}
void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander, std::vector<std::pair<ui8, ui8> > secondarySkills,
std::vector<Bonus *> specialSkills, boost::function<void(ui32)> &callback)
void CPlayerInterface::commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, boost::function<void(ui32)> &callback)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
waitWhileDialog();
CCS->soundh->playSound(soundBase::heroNewLevel);
CCreatureWindow * cw = new CCreatureWindow(commander);
GH.pushInt(cw);
//boost::function<void(ui32)>(boost::bind(&CCallback::selectionMade,cl->callbacks[h->tempOwner].get(),_1,id))
auto callback2 = boost::bind (&CCallback::selectionMade, cb, 0, playerID);
showYesNoDialog ("Commander got level", callback2, callback2, true, std::vector<CComponent*>());
//showYesNoDialog ("Commander got level", callback, callback, true, std::vector<CComponent*>());
//TODO: display full window
//CCreatureWindow * cw = new CCreatureWindow(commander);
//GH.pushInt(cw);
}
void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
{

View File

@@ -139,8 +139,7 @@ public:
void heroCreated(const CGHeroInstance* hero) OVERRIDE;
void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback) OVERRIDE;
void commanderGotLevel (const CCommanderInstance * commander, std::vector<std::pair<ui8, ui8> > secondarySkills,
std::vector<Bonus *> specialSkills, boost::function<void(ui32)> &callback) OVERRIDE;
void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, boost::function<void(ui32)> &callback) OVERRIDE;
void heroInGarrisonChange(const CGTownInstance *town) OVERRIDE;
void heroMoved(const TryMoveHero & details) OVERRIDE;
void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) OVERRIDE;

View File

@@ -537,8 +537,15 @@ void HeroLevelUp::applyCl( CClient *cl )
}
void CommanderLevelUp::applyCl( CClient *cl )
{
if (commander->armyObj && vstd::contains(cl->playerint, commander->armyObj->tempOwner)) //is it possible for Commander to exist beyond armed instance?
CCommanderInstance * commander = GS(cl)->getHero(heroid)->commander;
assert (commander);
ui8 player = commander->armyObj->tempOwner;
if (commander->armyObj && vstd::contains(cl->playerint, player)) //is it possible for Commander to exist beyond armed instance?
{
auto callback = boost::function<void(ui32)>(boost::bind(&CCallback::selectionMade,cl->callbacks[player].get(),_1,id));
cl->playerint[player]->showBlockingDialog("Commander got level", std::vector<Component>(), id, -1, false, true);
//cl->playerint[player]->commanderGotLevel(commander, skills, callback);
}
}

View File

@@ -24,16 +24,16 @@
//Value of bonuses given by each skill level
"skillLevels":
[
{"ATTACK": [2, 5, 9, 15, 25]}, //0
{"DEFENSE": [4, 10, 18, 30, 50]}, //1
{"HEALTH": [10, 25, 45, 70, 100]}, //2
{"DAMAGE": [10, 25, 45, 70, 100]}, //3
{"SPEED": [1, 2, 3, 4, 6]}, //4
{"SPELL_POWER":[1, 3, 6, 14, 29]}, //5
{"CASTS": [1, 2, 3, 4, 5]},
{"RESISTANCE": [5, 15, 35, 60, 90]}
{"name": "ATTACK", "levels": [2, 5, 9, 15, 25]}, //0
{"name": "DEFENSE", "levels": [4, 10, 18, 30, 50]}, //1
{"name": "HEALTH", "levels": [10, 25, 45, 70, 100]}, //2
{"name": "DAMAGE", "levels": [10, 25, 45, 70, 100]}, //3
{"name": "SPEED", "levels": [1, 2, 3, 4, 6]}, //4
{"name": "SPELL_POWER", "levels": [1, 3, 6, 14, 29]}, //5
{"name": "CASTS", "levels": [1, 2, 3, 4, 5]},
{"name": "RESISTANCE", "levels": [5, 15, 35, 60, 90]}
],
"abilityRequiremenets":
"abilityRequirements":
//Two secondary skills needed for each special ability
[
{"ability": ["ENEMY_DEFENCE_REDUCTION", 50, 0, 0 ], "skills": [0, 1]},

View File

@@ -624,7 +624,8 @@ void CCreatureHandler::loadCreatures()
i = 0;
BOOST_FOREACH (auto skill, config3["skillLevels"].Vector())
{
BOOST_FOREACH (auto skillLevel, skill.Vector())
skillLevels.push_back (std::vector<ui8>());
BOOST_FOREACH (auto skillLevel, skill["levels"].Vector())
{
skillLevels[i].push_back (skillLevel.Float());
}

View File

@@ -981,11 +981,13 @@ void CCommanderInstance::init()
{
alive = true;
experience = 0;
level = 1;
count = 1;
type = NULL;
idRand = -1;
_armyObj = NULL;
setNodeType (Bonus::COMMANDER);
setNodeType (Bonus::COMMANDER);
secondarySkills.resize (ECommander::SPELL_POWER + 1);
}
CCommanderInstance::~CCommanderInstance()
@@ -1016,6 +1018,7 @@ int CCommanderInstance::getExpRank() const
void CCommanderInstance::levelUp ()
{
level++;
BOOST_FOREACH (auto bonus, VLC->creh->commanderLevelPremy)
{ //grant all regular level-up bonuses
accumulateBonus (*bonus);

View File

@@ -80,8 +80,9 @@ public:
//commander class is determined by its base creature
ui8 alive;
ui8 level; //required only to count callbacks
std::string name; // each Commander has different name
std::map <ui8, ui8> secondarySkills; //ID, level
std::vector <ui8> secondarySkills; //ID -> level
//std::vector <CArtifactInstance *> arts;
void init() OVERRIDE;
CCommanderInstance();
@@ -98,7 +99,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & static_cast<CStackInstance&>(*this);
h & alive & name & secondarySkills;
h & alive & level & name & secondarySkills;
}
};

View File

@@ -75,8 +75,7 @@ public:
virtual void init(CCallback * CB){};
virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<std::pair<ui8, ui8> > secondarySkills,
std::vector<Bonus *> specialSkills, boost::function<void(ui32)> &callback) = 0;
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, boost::function<void(ui32)> &callback)=0;
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving

View File

@@ -178,6 +178,7 @@ namespace EBattleStackState
namespace ECommander
{
enum SecondarySkills {ATTACK, DEFENSE, HEALTH, DAMAGE, SPEED, SPELL_POWER, CASTS, RESISTANCE};
const int MAX_SKILL_LEVEL = 5;
}
namespace Obj

View File

@@ -658,7 +658,7 @@ void CBonusSystemNode::accumulateBonus(Bonus &b)
{
Bonus *bonus = exportedBonuses.getFirst(Selector::typeSubtype(b.type, b.subtype)); //only local bonuses are interesting //TODO: what about value type?
if(bonus)
bonus += b.val;
bonus->val += b.val;
else
addNewBonus(new Bonus(b)); //duplicate needed, original may get destroyed
}

View File

@@ -33,6 +33,7 @@ class CSelectionScreen;
class CGObjectInstance;
class CArtifactInstance;
//class CMapInfo;
struct StackLocation;
struct ArtSlotInfo;
struct QuestInfo;
@@ -165,6 +166,27 @@ public:
}
};
struct StackLocation
{
ConstTransitivePtr<CArmedInstance> army;
TSlot slot;
StackLocation()
{
slot = -1;
}
StackLocation(const CArmedInstance *Army, TSlot Slot)
{
army = const_cast<CArmedInstance*>(Army); //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
slot = Slot;
}
DLL_LINKAGE const CStackInstance *getStack();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & army & slot;
}
};
/***********************************************************************************************************/
@@ -500,21 +522,25 @@ struct UpdateCampaignState : public CPackForClient //119
h & camp;
}
};
struct SetCommanderproperty : public CPackForClient //120
struct SetCommanderProperty : public CPackForClient //120
{
enum ECommanderProperty {ALIVE, BONUS};
enum ECommanderProperty {ALIVE, BONUS, SECONDARY_SKILL};
SetCommanderproperty(){type = 120;};
SetCommanderProperty(){type = 120;};
void applyCl(CClient *cl){};
DLL_LINKAGE void applyGs(CGameState *gs){};
DLL_LINKAGE void applyGs(CGameState *gs);
ui8 which;
ui8 alive;
si32 heroid; //for commander attached to hero
StackLocation sl; //for commander not on the hero?
ui8 which; // use ECommanderProperty
ui8 amount; //0 for dead, >0 for alive
si32 additionalInfo; //for secondary skills choice
Bonus accumulatedBonus;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & which & alive & accumulatedBonus;
h & heroid & sl & which & amount & additionalInfo & accumulatedBonus;
}
};
struct AddQuest : public CPackForClient //121
@@ -762,27 +788,6 @@ struct NewArtifact : public CPackForClient //520
}
};
struct StackLocation
{
ConstTransitivePtr<CArmedInstance> army;
TSlot slot;
StackLocation()
{
slot = -1;
}
StackLocation(const CArmedInstance *Army, TSlot Slot)
{
army = const_cast<CArmedInstance*>(Army); //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
slot = Slot;
}
DLL_LINKAGE const CStackInstance *getStack();
template <typename Handler> void serialize(Handler &h, const int version)
{
h & army & slot;
}
};
struct CGarrisonOperationPack : CPackForClient
{
};
@@ -1159,15 +1164,16 @@ struct CommanderLevelUp : public Query
void applyCl(CClient *cl);
DLL_LINKAGE void applyGs(CGameState *gs);
CCommanderInstance * commander;
std::vector<std::pair<ui8, ui8> > secondarySkills;
std::vector<Bonus *> specialSkills;
si32 heroid; //for commander attached to hero
StackLocation sl; //for commander not on the hero?
std::vector<ui32> skills; //1-6 - secondary skills, val - 100 - special skill
CommanderLevelUp(){type = 2005;};
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & commander & secondarySkills & specialSkills;
h & id & heroid & sl & skills;
}
};

View File

@@ -76,6 +76,28 @@ DLL_LINKAGE void SetSecSkill::applyGs( CGameState *gs )
hero->setSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(which), val, abs);
}
DLL_LINKAGE void SetCommanderProperty::applyGs(CGameState *gs)
{
CCommanderInstance * commander = gs->getHero(heroid)->commander;
assert (commander);
switch (which)
{
case BONUS:
commander->accumulateBonus (accumulatedBonus);
break;
case SECONDARY_SKILL:
commander->secondarySkills[additionalInfo] = amount;
break;
case ALIVE:
if (amount)
commander->setAlive(true);
else
commander->setAlive(false);
break;
}
}
DLL_LINKAGE void HeroVisitCastle::applyGs( CGameState *gs )
{
CGHeroInstance *h = gs->getHero(hid);
@@ -901,6 +923,8 @@ DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs )
DLL_LINKAGE void CommanderLevelUp::applyGs (CGameState *gs)
{
CCommanderInstance * commander = gs->getHero(heroid)->commander;
assert (commander);
commander->levelUp();
}
@@ -1007,7 +1031,7 @@ void BattleResult::applyGs( CGameState *gs )
if (h)
{
h->getBonusList().remove_if(Bonus::OneBattle);
if (h->commander)
if (h->commander && h->commander->alive)
{
h->commander->giveStackExp(exp[i]);
CBonusSystemNode::treeHasChanged();

View File

@@ -139,6 +139,7 @@ void registerTypes2(Serializer &s)
s.template registerType<SetHoverName>();
s.template registerType<HeroLevelUp>();
s.template registerType<CommanderLevelUp>();
s.template registerType<SetCommanderProperty>();
s.template registerType<BlockingDialog>();
s.template registerType<GarrisonDialog>();
s.template registerType<BattleStart>();

View File

@@ -285,42 +285,123 @@ void CGameHandler::levelUpHero(int ID)
}
}
void CGameHandler::levelUpCommander (const CCommanderInstance * c, int secondarySkill, int specialSKill)
void CGameHandler::levelUpCommander (const CCommanderInstance * c, int skill)
{
if (secondarySkill >=0 )
SetCommanderProperty scp;
auto hero = dynamic_cast<const CGHeroInstance *>(c->armyObj);
if (hero)
scp.heroid = hero->id;
else
{
//c->secondarySkills[secondarySkill]++; //TODO: make sure to resize vector in first place
complain ("Commander is not led by hero!");
return;
}
if (specialSKill >= 0)
scp.which = SetCommanderProperty::BONUS;
scp.accumulatedBonus.additionalInfo = 0;
scp.accumulatedBonus.duration = Bonus::PERMANENT;
scp.accumulatedBonus.turnsRemain = 0;
scp.accumulatedBonus.source = Bonus::COMMANDER;
scp.accumulatedBonus.valType = Bonus::BASE_NUMBER;
if (skill <= ECommander::SPELL_POWER)
{
auto it = VLC->creh->skillRequirements.begin();
std::advance(it, specialSKill); //suboptimal, use bmap?
//c->accumulateBonus(it->first);
auto difference = [](std::vector< std::vector <ui8> > skillLevels, std::vector <ui8> secondarySkills, int skill)->int
{
return skillLevels[skill][secondarySkills[skill]] - (secondarySkills[skill] ? skillLevels[skill][secondarySkills[skill]-1] : 0);
};
switch (skill)
{
case ECommander::ATTACK:
scp.accumulatedBonus.type = Bonus::PRIMARY_SKILL;
scp.accumulatedBonus.subtype = PrimarySkill::ATTACK;
break;
case ECommander::DEFENSE:
scp.accumulatedBonus.type = Bonus::PRIMARY_SKILL;
scp.accumulatedBonus.subtype = PrimarySkill::DEFENSE;
break;
case ECommander::HEALTH:
scp.accumulatedBonus.type = Bonus::STACK_HEALTH;
scp.accumulatedBonus.valType = Bonus::PERCENT_TO_BASE;
break;
case ECommander::DAMAGE:
scp.accumulatedBonus.type = Bonus::CREATURE_DAMAGE;
scp.accumulatedBonus.subtype = 0;
scp.accumulatedBonus.valType = Bonus::PERCENT_TO_BASE;
break;
case ECommander::SPEED:
scp.accumulatedBonus.type = Bonus::STACKS_SPEED;
break;
case ECommander::SPELL_POWER:
scp.accumulatedBonus.type = Bonus::MAGIC_RESISTANCE;
scp.accumulatedBonus.val = difference (VLC->creh->skillLevels, c->secondarySkills, ECommander::RESISTANCE);
sendAndApply (&scp); //additional pack
scp.accumulatedBonus.type = Bonus::CASTS;
scp.accumulatedBonus.val = difference (VLC->creh->skillLevels, c->secondarySkills, ECommander::CASTS);
sendAndApply (&scp); //additional pack
scp.accumulatedBonus.type = Bonus::CREATURE_ENCHANT_POWER; //send normally
break;
}
scp.accumulatedBonus.val = difference (VLC->creh->skillLevels, c->secondarySkills, skill);
sendAndApply (&scp);
scp.which = SetCommanderProperty::SECONDARY_SKILL;
scp.additionalInfo = skill;
scp.amount = c->secondarySkills[skill] + 1;
sendAndApply (&scp);
}
else if (skill >= 100)
{
scp.accumulatedBonus = VLC->creh->skillRequirements[skill-100].first;
sendAndApply (&scp);
}
levelUpCommander (c);
//c->levelUp(); //change standard parameters
}
void CGameHandler::levelUpCommander(const CCommanderInstance * c)
{
return;
if (c->experience < VLC->heroh->reqExp (c->level + 1))
{
return;
}
CommanderLevelUp clu;
auto hero = dynamic_cast<const CGHeroInstance *>(c->armyObj);
if (hero)
clu.heroid = hero->id;
else
{
complain ("Commander is not led by hero!");
return;
}
//picking sec. skills for choice
int secondarySkill = -1, specialSkill = -1;
int skills = clu.secondarySkills.size() + clu.specialSkills.size();
if (skills > 1) //apply and ask for secondary skill
for (int i = 0; i <= ECommander::SPELL_POWER; ++i)
{
//auto callback = boost::bind (callWith<ui16>, clu.specialSkills, boost::bind(&CGameHandler::levelUpCommander, this, c, _1), _1);
//applyAndAsk (&clu, c->armyObj->tempOwner, callback); //call levelUpCommander when client responds
if (c->secondarySkills[i] < ECommander::MAX_SKILL_LEVEL)
clu.skills.push_back(i);
}
else if (skills == 1) //apply, give only possible skill and send info
int i = 100;
BOOST_FOREACH (auto specialSkill, VLC->creh->skillRequirements)
{
if (c->secondarySkills[specialSkill.second.first] == ECommander::MAX_SKILL_LEVEL &&
c->secondarySkills[specialSkill.second.second] == ECommander::MAX_SKILL_LEVEL)
clu.skills.push_back (i);
++i;
}
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
{
sendAndApply(&clu);
levelUpCommander(c, secondarySkill, specialSkill);
levelUpCommander(c, clu.skills.back());
}
else //apply and send info
{

View File

@@ -182,7 +182,7 @@ public:
void vistiCastleObjects (const CGTownInstance *t, const CGHeroInstance *h);
void levelUpHero(int ID, int skill);//handle client respond and send one more request if needed
void levelUpHero(int ID);//initial call - check if hero have remaining levelups & handle them
void levelUpCommander (const CCommanderInstance * c, int secondarySkill, int specialSKill);
void levelUpCommander (const CCommanderInstance * c, int skill); //secondary skill 1 to 6, special skill : skill - 100
void levelUpCommander (const CCommanderInstance * c);
void afterBattleCallback(); // called after level-ups are finished
//////////////////////////////////////////////////////////////////////////