mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
* morale/luck support in battles
* minor improvements/fixes * updated changelog More objects supported: * Faerie Ring * Swan Pond * Idol of Fortune * Fountain of Fortune * Rally Flag * Oasis * Temple * Watering Hole * Fountain of Youth
This commit is contained in:
parent
218a3beaf6
commit
e1d6ff54d7
@ -23,6 +23,7 @@ struct BattleResult;
|
|||||||
struct BattleAttack;
|
struct BattleAttack;
|
||||||
struct BattleStackAttacked;
|
struct BattleStackAttacked;
|
||||||
struct SpellCasted;
|
struct SpellCasted;
|
||||||
|
struct HeroBonus;
|
||||||
class CObstacle
|
class CObstacle
|
||||||
{
|
{
|
||||||
int ID;
|
int ID;
|
||||||
@ -67,6 +68,7 @@ public:
|
|||||||
virtual void tileRevealed(const std::set<int3> &pos){};
|
virtual void tileRevealed(const std::set<int3> &pos){};
|
||||||
virtual void yourTurn(){};
|
virtual void yourTurn(){};
|
||||||
virtual void availableCreaturesChanged(const CGTownInstance *town){};
|
virtual void availableCreaturesChanged(const CGTownInstance *town){};
|
||||||
|
virtual void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain){};//if gain hero received bonus, else he lost it
|
||||||
|
|
||||||
//battle call-ins
|
//battle call-ins
|
||||||
virtual void actionFinished(const BattleAction *action){};//occurs AFTER every action taken by any stack or by the hero
|
virtual void actionFinished(const BattleAction *action){};//occurs AFTER every action taken by any stack or by the hero
|
||||||
|
@ -362,6 +362,20 @@ const CStack::StackEffect * CStack::getEffect(ui16 id) const
|
|||||||
return &effects[i];
|
return &effects[i];
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
si8 CStack::Morale() const
|
||||||
|
{
|
||||||
|
si8 ret = morale;
|
||||||
|
//premies from spells/other effects
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
si8 CStack::Luck() const
|
||||||
|
{
|
||||||
|
si8 ret = luck;
|
||||||
|
//premies from spells/other effects
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, int notThatOne)
|
CGHeroInstance* CGameState::HeroesPool::pickHeroFor(bool native, int player, const CTown *town, int notThatOne)
|
||||||
{
|
{
|
||||||
if(player<0 || player>=PLAYER_LIMIT)
|
if(player<0 || player>=PLAYER_LIMIT)
|
||||||
@ -781,14 +795,14 @@ void CGameState::applyNL(IPack * pack)
|
|||||||
{
|
{
|
||||||
BattleSetActiveStack *ns = static_cast<BattleSetActiveStack*>(pack);
|
BattleSetActiveStack *ns = static_cast<BattleSetActiveStack*>(pack);
|
||||||
curB->activeStack = ns->stack;
|
curB->activeStack = ns->stack;
|
||||||
|
CStack *st = curB->getStack(ns->stack);
|
||||||
|
if(vstd::contains(st->state,MOVED))
|
||||||
|
st->state.insert(HAD_MORALE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3003:
|
case 3003:
|
||||||
{
|
{
|
||||||
BattleResult *br = static_cast<BattleResult*>(pack);
|
BattleResult *br = static_cast<BattleResult*>(pack);
|
||||||
|
|
||||||
//TODO: give exp, artifacts to winner, decrease armies (casualties)
|
|
||||||
|
|
||||||
for(unsigned i=0;i<curB->stacks.size();i++)
|
for(unsigned i=0;i<curB->stacks.size();i++)
|
||||||
delete curB->stacks[i];
|
delete curB->stacks[i];
|
||||||
delete curB;
|
delete curB;
|
||||||
@ -834,7 +848,7 @@ void CGameState::applyNL(IPack * pack)
|
|||||||
case 8:
|
case 8:
|
||||||
st->state.insert(WAITING);
|
st->state.insert(WAITING);
|
||||||
break;
|
break;
|
||||||
case 2: case 6: case 7: case 9: case 10:
|
case 2: case 6: case 7: case 9: case 10: case 11:
|
||||||
st->state.insert(MOVED);
|
st->state.insert(MOVED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,7 @@ public:
|
|||||||
ui16 position; //position on battlefield
|
ui16 position; //position on battlefield
|
||||||
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
|
||||||
si16 shots; //how many shots left
|
si16 shots; //how many shots left
|
||||||
|
si8 morale, luck; //base stack luck/morale
|
||||||
|
|
||||||
std::set<EAbilities> abilities;
|
std::set<EAbilities> abilities;
|
||||||
std::set<ECombatInfo> state;
|
std::set<ECombatInfo> state;
|
||||||
@ -146,6 +147,8 @@ public:
|
|||||||
CStack() : creature(NULL),amount(-1),owner(255), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1), slot(255), baseAmount(-1), counterAttacks(1), effects(), state(), abilities(){}
|
CStack() : creature(NULL),amount(-1),owner(255), position(-1), ID(-1), attackerOwned(true), firstHPleft(-1), slot(255), baseAmount(-1), counterAttacks(1), effects(), state(), abilities(){}
|
||||||
const StackEffect * getEffect(ui16 id) const; //effect id (SP)
|
const StackEffect * getEffect(ui16 id) const; //effect id (SP)
|
||||||
ui32 speed() const;
|
ui32 speed() const;
|
||||||
|
si8 Morale() const;
|
||||||
|
si8 Luck() const;
|
||||||
template <typename Handler> void save(Handler &h, const int version)
|
template <typename Handler> void save(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & creature->idNumber;
|
h & creature->idNumber;
|
||||||
@ -160,7 +163,7 @@ public:
|
|||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
|
||||||
& shots;
|
& shots & morale & luck;
|
||||||
if(h.saving)
|
if(h.saving)
|
||||||
save(h,version);
|
save(h,version);
|
||||||
else
|
else
|
||||||
|
@ -462,8 +462,8 @@ void CHeroWindow::deactivate()
|
|||||||
portraitArea->deactivate();
|
portraitArea->deactivate();
|
||||||
expArea->deactivate();
|
expArea->deactivate();
|
||||||
spellPointsArea->deactivate();
|
spellPointsArea->deactivate();
|
||||||
morale->activate();
|
morale->deactivate();
|
||||||
luck->activate();
|
luck->deactivate();
|
||||||
|
|
||||||
garInt->deactivate();
|
garInt->deactivate();
|
||||||
|
|
||||||
|
@ -1887,19 +1887,12 @@ int3 CPlayerInterface::repairScreenPos(int3 pos)
|
|||||||
void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val)
|
void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||||
SDL_FreeSurface(graphics->heroWins[hero->subID]);//TODO: moznaby zmieniac jedynie fragment bitmapy zwiazany z dana umiejetnoscia
|
redrawHeroWin(hero);
|
||||||
graphics->heroWins[hero->subID] = infoWin(hero); //a nie przerysowywac calosc. Troche roboty, obecnie chyba nie wartej swieczki.
|
|
||||||
if (adventureInt->selection == hero)
|
|
||||||
adventureInt->infoBar.draw();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero)
|
void CPlayerInterface::heroManaPointsChanged(const CGHeroInstance * hero)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||||
SDL_FreeSurface(graphics->heroWins[hero->subID]);//TODO: moznaby zmieniac jedynie fragment bitmapy zwiazany z dana umiejetnoscia
|
redrawHeroWin(hero);
|
||||||
graphics->heroWins[hero->subID] = infoWin(hero); //a nie przerysowywac calosc. Troche roboty, obecnie chyba nie wartej swieczki.
|
|
||||||
if (adventureInt->selection == hero)
|
|
||||||
adventureInt->infoBar.draw();
|
|
||||||
}
|
}
|
||||||
void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
|
void CPlayerInterface::heroMovePointsChanged(const CGHeroInstance * hero)
|
||||||
{
|
{
|
||||||
@ -2079,10 +2072,13 @@ void CPlayerInterface::actionStarted(const BattleAction* action)
|
|||||||
{
|
{
|
||||||
battleInt->creAnims[action->stackNumber]->setType(20);
|
battleInt->creAnims[action->stackNumber]->setType(20);
|
||||||
}
|
}
|
||||||
//if((action->actionType==2 || (action->actionType==6 && action->destinationTile!=cb->battleGetPos(action->stackNumber)))) //deactivating interface when move is started
|
|
||||||
{
|
|
||||||
battleInt->deactivate();
|
battleInt->deactivate();
|
||||||
}
|
|
||||||
|
CStack *stack = cb->battleGetStackByID(action->stackNumber);
|
||||||
|
char txt[400];
|
||||||
|
|
||||||
if(action->actionType == 1)
|
if(action->actionType == 1)
|
||||||
{
|
{
|
||||||
if(action->side)
|
if(action->side)
|
||||||
@ -2090,48 +2086,37 @@ void CPlayerInterface::actionStarted(const BattleAction* action)
|
|||||||
else
|
else
|
||||||
battleInt->attackingHero->setPhase(4);
|
battleInt->attackingHero->setPhase(4);
|
||||||
}
|
}
|
||||||
if(action->actionType == 3) //defend
|
if(!stack)
|
||||||
{
|
{
|
||||||
char txt[2000];
|
tlog1<<"Something wrong with stackNumber in actionStarted"<<std::endl;
|
||||||
CStack * stack = cb->battleGetStackByID(action->stackNumber);
|
return;
|
||||||
if(stack)
|
|
||||||
{
|
|
||||||
if(stack->amount == 1)
|
|
||||||
{
|
|
||||||
sprintf(txt, CGI->generaltexth->allTexts[120].c_str(), stack->creature->nameSing.c_str(), 0);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
int txtid = 0;
|
||||||
|
switch(action->actionType)
|
||||||
{
|
{
|
||||||
sprintf(txt, CGI->generaltexth->allTexts[121].c_str(), stack->creature->namePl.c_str(), 0);
|
case 3: //defend
|
||||||
|
txtid = 120;
|
||||||
|
break;
|
||||||
|
case 8: //wait
|
||||||
|
txtid = 136;
|
||||||
|
break;
|
||||||
|
case 11: //bad morale
|
||||||
|
txtid = -34; //negative -> no separate singular/plural form
|
||||||
|
battleInt->displayEffect(30,stack->position);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(txtid > 0 && stack->amount != 1)
|
||||||
|
txtid++; //move to plural text
|
||||||
|
else if(txtid < 0)
|
||||||
|
txtid = -txtid;
|
||||||
|
|
||||||
|
if(txtid)
|
||||||
|
{
|
||||||
|
sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(), (stack->amount != 1) ? stack->creature->namePl.c_str() : stack->creature->nameSing.c_str(), 0);
|
||||||
LOCPLINT->battleInt->console->addText(txt);
|
LOCPLINT->battleInt->console->addText(txt);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
tlog1<<"Somthing wrong with stackNumber in actionStarted -> actionType 3"<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(action->actionType == 8) //wait
|
|
||||||
{
|
|
||||||
char txt[2000];
|
|
||||||
CStack * stack = cb->battleGetStackByID(action->stackNumber);
|
|
||||||
if(stack)
|
|
||||||
{
|
|
||||||
if(stack->amount == 1)
|
|
||||||
{
|
|
||||||
sprintf(txt, CGI->generaltexth->allTexts[136].c_str(), stack->creature->nameSing.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(txt, CGI->generaltexth->allTexts[137].c_str(), stack->creature->namePl.c_str());
|
|
||||||
}
|
|
||||||
LOCPLINT->battleInt->console->addText(txt);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tlog1<<"Somthing wrong with stackNumber in actionStarted -> actionType 8"<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::actionFinished(const BattleAction* action)
|
void CPlayerInterface::actionFinished(const BattleAction* action)
|
||||||
@ -2156,6 +2141,16 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
|
|||||||
CBattleInterface *b = battleInt;
|
CBattleInterface *b = battleInt;
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||||
|
|
||||||
|
CStack *stack = cb->battleGetStackByID(stackID);
|
||||||
|
if(vstd::contains(stack->state,MOVED)) //this stack has moved and makes second action -> high morale
|
||||||
|
{
|
||||||
|
std::string hlp = CGI->generaltexth->allTexts[33];
|
||||||
|
boost::algorithm::replace_first(hlp,"%s",(stack->amount != 1) ? stack->creature->namePl : stack->creature->nameSing);
|
||||||
|
battleInt->displayEffect(20,stack->position);
|
||||||
|
battleInt->console->addText(hlp);
|
||||||
|
}
|
||||||
|
|
||||||
b->stackActivated(stackID);
|
b->stackActivated(stackID);
|
||||||
}
|
}
|
||||||
//wait till BattleInterface sets its command
|
//wait till BattleInterface sets its command
|
||||||
@ -2215,14 +2210,18 @@ void CPlayerInterface::battleStackAttacked(BattleStackAttacked * bsa)
|
|||||||
void CPlayerInterface::battleAttack(BattleAttack *ba)
|
void CPlayerInterface::battleAttack(BattleAttack *ba)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||||
|
if(ba->bsa.lucky()) //lucky hit
|
||||||
|
{
|
||||||
|
CStack *stack = cb->battleGetStackByID(ba->stackAttacking);
|
||||||
|
std::string hlp = CGI->generaltexth->allTexts[45];
|
||||||
|
boost::algorithm::replace_first(hlp,"%s",(stack->amount != 1) ? stack->creature->namePl.c_str() : stack->creature->nameSing.c_str());
|
||||||
|
battleInt->console->addText(hlp);
|
||||||
|
battleInt->displayEffect(18,stack->position);
|
||||||
|
}
|
||||||
if(ba->shot())
|
if(ba->shot())
|
||||||
battleInt->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked));
|
battleInt->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked));
|
||||||
else
|
else
|
||||||
battleInt->stackAttacking( ba->stackAttacking, ba->counter() ? curAction->destinationTile : curAction->additionalInfo );
|
battleInt->stackAttacking( ba->stackAttacking, ba->counter() ? curAction->destinationTile : curAction->additionalInfo );
|
||||||
/*if(ba->killed())
|
|
||||||
battleInt->stackKilled(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());
|
|
||||||
else
|
|
||||||
battleInt->stackIsAttacked(ba->bsa.stackAttacked, ba->bsa.damageAmount, ba->bsa.killedAmount, ba->stackAttacking, ba->shot());*/
|
|
||||||
}
|
}
|
||||||
void CPlayerInterface::showComp(SComponent comp)
|
void CPlayerInterface::showComp(SComponent comp)
|
||||||
{
|
{
|
||||||
@ -2359,6 +2358,21 @@ void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town )
|
|||||||
fs->draw(castleInt,false);
|
fs->draw(castleInt,false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroBonus &bonus, bool gain )
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||||
|
redrawHeroWin(hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
|
||||||
|
{
|
||||||
|
SDL_FreeSurface(graphics->heroWins[hero->subID]);
|
||||||
|
graphics->heroWins[hero->subID] = infoWin(hero);
|
||||||
|
if (adventureInt->selection == hero)
|
||||||
|
adventureInt->infoBar.draw();
|
||||||
|
}
|
||||||
|
|
||||||
CStatusBar::CStatusBar(int x, int y, std::string name, int maxw)
|
CStatusBar::CStatusBar(int x, int y, std::string name, int maxw)
|
||||||
{
|
{
|
||||||
bg=BitmapHandler::loadBitmap(name);
|
bg=BitmapHandler::loadBitmap(name);
|
||||||
|
@ -380,6 +380,7 @@ public:
|
|||||||
void tileRevealed(const std::set<int3> &pos);
|
void tileRevealed(const std::set<int3> &pos);
|
||||||
void yourTurn();
|
void yourTurn();
|
||||||
void availableCreaturesChanged(const CGTownInstance *town);
|
void availableCreaturesChanged(const CGTownInstance *town);
|
||||||
|
void heroBonusChanged(const CGHeroInstance *hero, const HeroBonus &bonus, bool gain);//if gain hero received bonus, else he lost it
|
||||||
//for battles
|
//for battles
|
||||||
void actionFinished(const BattleAction* action);//occurs AFTER action taken by active stack or by the hero
|
void actionFinished(const BattleAction* action);//occurs AFTER action taken by active stack or by the hero
|
||||||
void actionStarted(const BattleAction* action);//occurs BEFORE action taken by active stack or by the hero
|
void actionStarted(const BattleAction* action);//occurs BEFORE action taken by active stack or by the hero
|
||||||
@ -396,6 +397,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
//-------------//
|
//-------------//
|
||||||
|
void redrawHeroWin(const CGHeroInstance * hero);
|
||||||
void updateWater();
|
void updateWater();
|
||||||
void showComp(SComponent comp);
|
void showComp(SComponent comp);
|
||||||
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
void openTownWindow(const CGTownInstance * town); //shows townscreen
|
||||||
|
71
ChangeLog
71
ChangeLog
@ -1,22 +1,51 @@
|
|||||||
0.64 -> 0.next (???) [as for r689]
|
0.7 -> 0.71 (as for r707)
|
||||||
|
GENERAL:
|
||||||
|
* morale/luck system and corresponding sec. skills supported
|
||||||
|
* fixed crash when hero get level and has less than two sec. skills to choose between
|
||||||
|
|
||||||
|
ADVENTURE INTERFACE:
|
||||||
|
* added missing path arrows
|
||||||
|
* corrected centering on hero's position
|
||||||
|
|
||||||
|
BATTLES:
|
||||||
|
* spell books won't be placed in War Machine slots after battle
|
||||||
|
|
||||||
|
TOWN INTERFACE:
|
||||||
|
* Rampart's Treasury requires Miner's Guild
|
||||||
|
|
||||||
|
OBJECTS:
|
||||||
|
New objects supported:
|
||||||
|
* Faerie Ring
|
||||||
|
* Swan Pond
|
||||||
|
* Idol of Fortune
|
||||||
|
* Fountain of Fortune
|
||||||
|
* Rally Flag
|
||||||
|
* Oasis
|
||||||
|
* Temple
|
||||||
|
* Watering Hole
|
||||||
|
* Fountain of Youth
|
||||||
|
|
||||||
|
|
||||||
|
0.64 -> 0.7 (Feb 01 2009)
|
||||||
GENERAL:
|
GENERAL:
|
||||||
* move some settings to the config/settings.txt file
|
* move some settings to the config/settings.txt file
|
||||||
* partial support for new screen resolutions
|
* partial support for new screen resolutions
|
||||||
|
* it's possible to set game resolution in pregame (type 'resolution' in the console)
|
||||||
* /Data and /Sprites subfolders can be used for adding files not present in .lod archives
|
* /Data and /Sprites subfolders can be used for adding files not present in .lod archives
|
||||||
* fixed crashbug occuring when hero levelled above 15 level
|
* fixed crashbug occuring when hero levelled above 15 level
|
||||||
* support for non-standard screen resolutions
|
* support for non-standard screen resolutions
|
||||||
* F4 toggles between full-screen and windowed mode (experimental)
|
* F4 toggles between full-screen and windowed mode
|
||||||
* splitting stacks the shift+click
|
|
||||||
* minor improvements in creature card window
|
* minor improvements in creature card window
|
||||||
|
* splitting stacks with the shift+click
|
||||||
|
* creature card window contains info about modified speed
|
||||||
|
|
||||||
ADVENTURE INTERFACE:
|
ADVENTURE INTERFACE:
|
||||||
* smooth map scrolling on hero movement
|
|
||||||
* added water animation
|
* added water animation
|
||||||
* speed of scrolling map and hero movement can be adjusted in the System Options Window
|
* speed of scrolling map and hero movement can be adjusted in the System Options Window
|
||||||
* partial handling r-clicks on adventure map
|
* partial handling r-clicks on adventure map
|
||||||
|
|
||||||
TOWN INTERFACE:
|
TOWN INTERFACE:
|
||||||
* the scroll tab won't remain hanged to our mouse position if we move the mouse away from the scroll bar
|
* the scroll tab won't remain hanged to our mouse position if we move the mouse is away from the scroll bar
|
||||||
* fixed cloning creatures bug in garrisons (and related issues)
|
* fixed cloning creatures bug in garrisons (and related issues)
|
||||||
|
|
||||||
BATTLES
|
BATTLES
|
||||||
@ -31,21 +60,21 @@ BATTLES
|
|||||||
* battle console displays notifications about wait/defend commands
|
* battle console displays notifications about wait/defend commands
|
||||||
* several reported bugs fixed
|
* several reported bugs fixed
|
||||||
* new spells supported:
|
* new spells supported:
|
||||||
a) Haste
|
a) Haste
|
||||||
b) lightning bolt
|
b) lightning bolt
|
||||||
c) ice bolt
|
c) ice bolt
|
||||||
d) slow
|
d) slow
|
||||||
e) implosion
|
e) implosion
|
||||||
f) forgetfulness
|
f) forgetfulness
|
||||||
g) shield
|
g) shield
|
||||||
h) air shield
|
h) air shield
|
||||||
i) bless
|
i) bless
|
||||||
j) curse
|
j) curse
|
||||||
k) bloodlust
|
k) bloodlust
|
||||||
l) weakness
|
l) weakness
|
||||||
m) stone skin
|
m) stone skin
|
||||||
n) prayer
|
n) prayer
|
||||||
o) frenzy
|
o) frenzy
|
||||||
|
|
||||||
AI PLAYER:
|
AI PLAYER:
|
||||||
* Genius AI (first VCMI AI) will control computer creatures during the combat.
|
* Genius AI (first VCMI AI) will control computer creatures during the combat.
|
||||||
@ -54,9 +83,11 @@ OBJECTS:
|
|||||||
* Guardians property for resources is handled
|
* Guardians property for resources is handled
|
||||||
* support for Witch Hut
|
* support for Witch Hut
|
||||||
* support for Arena
|
* support for Arena
|
||||||
|
* support for Library of Enlightenment
|
||||||
|
|
||||||
And a lot of minor fixes
|
And a lot of minor fixes
|
||||||
|
|
||||||
|
|
||||||
0.63 -> 0.64 (Nov 01 2008)
|
0.63 -> 0.64 (Nov 01 2008)
|
||||||
GENERAL:
|
GENERAL:
|
||||||
* sprites from /Sprites folder are handled correctly
|
* sprites from /Sprites folder are handled correctly
|
||||||
|
@ -212,6 +212,9 @@ void CClient::process(int what)
|
|||||||
*serv >> gb;
|
*serv >> gb;
|
||||||
tlog5 << "Hero receives bonus\n";
|
tlog5 << "Hero receives bonus\n";
|
||||||
gs->apply(&gb);
|
gs->apply(&gb);
|
||||||
|
CGHeroInstance *h = gs->getHero(gb.hid);
|
||||||
|
if(vstd::contains(playerint,h->tempOwner))
|
||||||
|
playerint[h->tempOwner]->heroBonusChanged(h,h->bonuses.back(),true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 500:
|
case 500:
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "CSpellHandler.h"
|
#include "CSpellHandler.h"
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/random/linear_congruential.hpp>
|
#include <boost/random/linear_congruential.hpp>
|
||||||
#include "CTownHandler.h"
|
#include "CTownHandler.h"
|
||||||
#include "CArtHandler.h"
|
#include "CArtHandler.h"
|
||||||
@ -611,7 +612,7 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentMoraleModifie
|
|||||||
|
|
||||||
//various morale bonuses (from buildings, artifacts, etc)
|
//various morale bonuses (from buildings, artifacts, etc)
|
||||||
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
|
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
|
||||||
if(i->type == HeroBonus::MORALE)
|
if(i->type == HeroBonus::MORALE || i->type == HeroBonus::MORALE_AND_LUCK)
|
||||||
ret.push_back(std::make_pair(i->val, i->description));
|
ret.push_back(std::make_pair(i->val, i->description));
|
||||||
|
|
||||||
//leadership
|
//leadership
|
||||||
@ -688,7 +689,7 @@ std::vector<std::pair<int,std::string> > CGHeroInstance::getCurrentLuckModifiers
|
|||||||
|
|
||||||
//various morale bonuses (from buildings, artifacts, etc)
|
//various morale bonuses (from buildings, artifacts, etc)
|
||||||
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
|
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
|
||||||
if(i->type == HeroBonus::LUCK)
|
if(i->type == HeroBonus::LUCK || i->type == HeroBonus::MORALE_AND_LUCK)
|
||||||
ret.push_back(std::make_pair(i->val, i->description));
|
ret.push_back(std::make_pair(i->val, i->description));
|
||||||
|
|
||||||
//luck skill
|
//luck skill
|
||||||
@ -1608,48 +1609,108 @@ void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
{
|
{
|
||||||
bool visited = h->getBonus(HeroBonus::OBJECT,ID);
|
bool visited = h->getBonus(HeroBonus::OBJECT,ID);
|
||||||
int messageID, bonusType, bonusVal;
|
int messageID, bonusType, bonusVal;
|
||||||
|
int bonusMove = 0;
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = h->tempOwner;
|
iw.player = h->tempOwner;
|
||||||
|
GiveBonus gbonus;
|
||||||
|
gbonus.hid = h->id;
|
||||||
|
gbonus.bonus.duration = HeroBonus::ONE_BATTLE;
|
||||||
|
gbonus.bonus.source = HeroBonus::OBJECT;
|
||||||
|
gbonus.bonus.id = ID;
|
||||||
|
|
||||||
switch(ID)
|
switch(ID)
|
||||||
{
|
{
|
||||||
case 14: //swan pond
|
case 14: //swan pond
|
||||||
messageID = 29;
|
messageID = 29;
|
||||||
bonusType = HeroBonus::LUCK;
|
gbonus.bonus.type = HeroBonus::LUCK;
|
||||||
bonusVal = 2;
|
gbonus.bonus.val = 2;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,67);
|
||||||
|
bonusMove = -h->movement;
|
||||||
|
break;
|
||||||
case 28: //Faerie Ring
|
case 28: //Faerie Ring
|
||||||
messageID = 49;
|
messageID = 49;
|
||||||
bonusType = HeroBonus::LUCK;
|
gbonus.bonus.type = HeroBonus::LUCK;
|
||||||
bonusVal = 1;
|
gbonus.bonus.val = 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,71);
|
||||||
break;
|
break;
|
||||||
case 30: //fountain of fortune
|
case 30: //fountain of fortune
|
||||||
messageID = 55;
|
messageID = 55;
|
||||||
bonusType = HeroBonus::LUCK;
|
gbonus.bonus.type = HeroBonus::LUCK;
|
||||||
bonusVal = rand()%5 - 1;
|
gbonus.bonus.val = rand()%5 - 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,69);
|
||||||
|
gbonus.bdescr.replacements.push_back((gbonus.bonus.val<0 ? "-" : "+") + boost::lexical_cast<std::string>(gbonus.bonus.val));
|
||||||
break;
|
break;
|
||||||
case 38: //idol of fortune
|
case 38: //idol of fortune
|
||||||
messageID = 62;
|
messageID = 62;
|
||||||
bonusType = HeroBonus::IDOL_OF_FORTUNE_BONUS;
|
if(cb->getDate(1) == 7) //7th day of week
|
||||||
bonusVal = 1;
|
gbonus.bonus.type = HeroBonus::MORALE_AND_LUCK;
|
||||||
|
else
|
||||||
|
gbonus.bonus.type = (cb->getDate(1)%2) ? HeroBonus::LUCK : HeroBonus::MORALE;
|
||||||
|
gbonus.bonus.val = 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,68);
|
||||||
|
break;
|
||||||
|
case 64: //Rally Flag
|
||||||
|
messageID = 111;
|
||||||
|
gbonus.bonus.type = HeroBonus::MORALE_AND_LUCK;
|
||||||
|
gbonus.bonus.val = 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,102);
|
||||||
|
bonusMove = 400;
|
||||||
|
break;
|
||||||
|
case 56: //oasis
|
||||||
|
messageID = 95;
|
||||||
|
gbonus.bonus.type = HeroBonus::MORALE;
|
||||||
|
gbonus.bonus.val = 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,95);
|
||||||
|
bonusMove = 800;
|
||||||
|
break;
|
||||||
|
case 96: //temple
|
||||||
|
messageID = 140;
|
||||||
|
gbonus.bonus.type = HeroBonus::MORALE;
|
||||||
|
if(cb->getDate(1)==7) //sunday
|
||||||
|
{
|
||||||
|
gbonus.bonus.val = 2;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,97);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gbonus.bonus.val = 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,96);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 110://Watering Hole
|
||||||
|
messageID = 166;
|
||||||
|
gbonus.bonus.type = HeroBonus::MORALE;
|
||||||
|
gbonus.bonus.val = 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,100);
|
||||||
|
bonusMove = 400;
|
||||||
|
break;
|
||||||
|
case 31: //Fountain of Youth
|
||||||
|
messageID = 57;
|
||||||
|
gbonus.bonus.type = HeroBonus::MORALE;
|
||||||
|
gbonus.bonus.val = 1;
|
||||||
|
gbonus.bdescr << std::pair<ui8,ui32>(6,103);
|
||||||
|
bonusMove = 400;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(visited)
|
if(visited)
|
||||||
{
|
{
|
||||||
|
if(ID==64 || ID==96 || ID==56)
|
||||||
|
messageID--;
|
||||||
|
else
|
||||||
messageID++;
|
messageID++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
iw.components.push_back(Component(9,0,1,0));
|
if(gbonus.bonus.type == HeroBonus::MORALE || gbonus.bonus.type == HeroBonus::MORALE_AND_LUCK)
|
||||||
GiveBonus gbonus;
|
iw.components.push_back(Component(8,0,gbonus.bonus.val,0));
|
||||||
gbonus.bonus = HeroBonus(HeroBonus::ONE_BATTLE,HeroBonus::LUCK,HeroBonus::OBJECT, bonusVal, ID,"");
|
if(gbonus.bonus.type == HeroBonus::LUCK || gbonus.bonus.type == HeroBonus::MORALE_AND_LUCK)
|
||||||
gbonus.hid = h->id;
|
iw.components.push_back(Component(9,0,gbonus.bonus.val,0));
|
||||||
gbonus.bdescr << std::pair<ui8,ui32>(6,71);
|
|
||||||
cb->giveHeroBonus(&gbonus);
|
cb->giveHeroBonus(&gbonus);
|
||||||
if(ID==14) //swan pond - take all move points
|
if(bonusMove) //swan pond - take all move points
|
||||||
{
|
{
|
||||||
SetMovePoints smp;
|
SetMovePoints smp;
|
||||||
smp.hid = h->id;
|
smp.hid = h->id;
|
||||||
smp.val = 0;
|
smp.val = h->movement + bonusMove;
|
||||||
cb->setMovePoints(&smp);
|
cb->setMovePoints(&smp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ struct BattleAction
|
|||||||
{
|
{
|
||||||
ui8 side; //who made this action: false - left, true - right player
|
ui8 side; //who made this action: false - left, true - right player
|
||||||
ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
|
ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
|
||||||
ui8 actionType; // 0 = Cancel BattleAction 1 = Hero cast a spell 2 = Walk 3 = Defend 4 = Retreat from the battle 5 = Surrender 6 = Walk and Attack 7 = Shoot 8 = Wait 9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons)
|
ui8 actionType; // 0 = No action; 1 = Hero cast a spell 2 = Walk 3 = Defend 4 = Retreat from the battle 5 = Surrender 6 = Walk and Attack 7 = Shoot 8 = Wait 9 = Catapult 10 = Monster casts a spell (i.e. Faerie Dragons) 11 - Bad morale freeze
|
||||||
ui16 destinationTile;
|
ui16 destinationTile;
|
||||||
si32 additionalInfo; // e.g. spell number if type is 1 || 10; tile to attack if type is 6
|
si32 additionalInfo; // e.g. spell number if type is 1 || 10; tile to attack if type is 6
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
struct DLL_EXPORT HeroBonus
|
struct DLL_EXPORT HeroBonus
|
||||||
{
|
{
|
||||||
enum BonusType{NONE, MOVEMENT, MORALE, LUCK, IDOL_OF_FORTUNE_BONUS};
|
enum BonusType{NONE, MOVEMENT, LAND_MOVEMENT, SEA_MOVEMENT, MORALE, LUCK, MORALE_AND_LUCK};
|
||||||
enum BonusDuration{PERMANENT, ONE_BATTLE, ONE_DAY, ONE_WEEK};
|
enum BonusDuration{PERMANENT, ONE_BATTLE, ONE_DAY, ONE_WEEK};
|
||||||
enum BonusSource{ARTIFACT, OBJECT};
|
enum BonusSource{ARTIFACT, OBJECT};
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ struct BattleStackAttacked : public CPack<BattleStackAttacked>//3005
|
|||||||
{
|
{
|
||||||
ui32 stackAttacked;
|
ui32 stackAttacked;
|
||||||
ui32 newAmount, newHP, killedAmount, damageAmount;
|
ui32 newAmount, newHP, killedAmount, damageAmount;
|
||||||
ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown
|
ui8 flags; //1 - is stack killed; 2 - is there special effect to be shown; 4 - lucky hit
|
||||||
ui32 effect; //set only if flag 2 is present
|
ui32 effect; //set only if flag 2 is present
|
||||||
|
|
||||||
|
|
||||||
@ -518,6 +518,10 @@ struct BattleStackAttacked : public CPack<BattleStackAttacked>//3005
|
|||||||
{
|
{
|
||||||
return flags & 2;
|
return flags & 2;
|
||||||
}
|
}
|
||||||
|
bool lucky()
|
||||||
|
{
|
||||||
|
return flags & 4;
|
||||||
|
}
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount & effect;
|
h & stackAttacked & newAmount & newHP & flags & killedAmount & damageAmount & effect;
|
||||||
|
5
map.cpp
5
map.cpp
@ -1781,6 +1781,11 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
|
|||||||
case 14: //Swan pond
|
case 14: //Swan pond
|
||||||
case 38: //idol of fortune
|
case 38: //idol of fortune
|
||||||
case 30: //Fountain of Fortune
|
case 30: //Fountain of Fortune
|
||||||
|
case 64: //Rally Flag
|
||||||
|
case 56: //oasis
|
||||||
|
case 96: //temple
|
||||||
|
case 110://Watering Hole
|
||||||
|
case 31: //Fountain of Youth
|
||||||
{
|
{
|
||||||
nobj = new CGBonusingObject();
|
nobj = new CGBonusingObject();
|
||||||
break;
|
break;
|
||||||
|
5
map.h
5
map.h
@ -499,6 +499,11 @@ struct DLL_EXPORT Mapa : public CMapHeader
|
|||||||
case 14: //Swan pond
|
case 14: //Swan pond
|
||||||
case 38: //idol of fortune
|
case 38: //idol of fortune
|
||||||
case 30: //Fountain of Fortune
|
case 30: //Fountain of Fortune
|
||||||
|
case 64: //Rally Flag
|
||||||
|
case 56: //oasis
|
||||||
|
case 96: //temple
|
||||||
|
case 110://Watering Hole
|
||||||
|
case 31: //Fountain of Youth
|
||||||
SERIALIZE(CGBonusingObject);
|
SERIALIZE(CGBonusingObject);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -310,6 +310,29 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
|
|||||||
//stack loop
|
//stack loop
|
||||||
CStack *next;
|
CStack *next;
|
||||||
while(!battleResult.get() && (next=gs->curB->getNextStack()))
|
while(!battleResult.get() && (next=gs->curB->getNextStack()))
|
||||||
|
{
|
||||||
|
next->state -= WAITING; //if stack was waiting it'll now make move, so it won't be "waiting" anymore
|
||||||
|
|
||||||
|
//check for bad morale => freeze
|
||||||
|
if(next->Morale() < 0)
|
||||||
|
{
|
||||||
|
if( rand()%24 < (-next->Morale())*2 )
|
||||||
|
{
|
||||||
|
//unit loses its turn - empty freeze action
|
||||||
|
BattleAction ba;
|
||||||
|
ba.actionType = 11;
|
||||||
|
ba.additionalInfo = 1;
|
||||||
|
ba.side = !next->attackerOwned;
|
||||||
|
ba.stackNumber = next->ID;
|
||||||
|
sendAndApply(&StartAction(ba));
|
||||||
|
sendDataToClients(ui16(3008));
|
||||||
|
checkForBattleEnd(stacks); //check if this "action" ended the battle (not likely but who knows...)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
askInterfaceForMove:
|
||||||
|
//ask interface and wait for answer
|
||||||
{
|
{
|
||||||
BattleSetActiveStack sas;
|
BattleSetActiveStack sas;
|
||||||
sas.stack = next->ID;
|
sas.stack = next->ID;
|
||||||
@ -318,7 +341,19 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
|
|||||||
while(!battleMadeAction.data && !battleResult.get()) //active stack hasn't made its action and battle is still going
|
while(!battleMadeAction.data && !battleResult.get()) //active stack hasn't made its action and battle is still going
|
||||||
battleMadeAction.cond.wait(lock);
|
battleMadeAction.cond.wait(lock);
|
||||||
battleMadeAction.data = false;
|
battleMadeAction.data = false;
|
||||||
|
}
|
||||||
|
//we're after action, all results applied
|
||||||
checkForBattleEnd(stacks); //check if this action ended the battle
|
checkForBattleEnd(stacks); //check if this action ended the battle
|
||||||
|
|
||||||
|
//check for good morale
|
||||||
|
if(!vstd::contains(next->state,HAD_MORALE) //only one extra move per turn possible
|
||||||
|
&& !vstd::contains(next->state,DEFENDING)
|
||||||
|
&& !vstd::contains(next->state,WAITING)
|
||||||
|
&& next->alive()
|
||||||
|
&& next->Morale() > 0
|
||||||
|
)
|
||||||
|
if(rand()%24 < next->Morale()) //this stack hasn't got morale this turn
|
||||||
|
goto askInterfaceForMove; //move this stack once more
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +430,11 @@ void CGameHandler::prepareAttack(BattleAttack &bat, CStack *att, CStack *def)
|
|||||||
bat.stackAttacking = att->ID;
|
bat.stackAttacking = att->ID;
|
||||||
bat.bsa.stackAttacked = def->ID;
|
bat.bsa.stackAttacked = def->ID;
|
||||||
bat.bsa.damageAmount = BattleInfo::calculateDmg(att, def, gs->getHero(att->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), gs->getHero(def->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), bat.shot());//counting dealt damage
|
bat.bsa.damageAmount = BattleInfo::calculateDmg(att, def, gs->getHero(att->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), gs->getHero(def->attackerOwned ? gs->curB->hero1 : gs->curB->hero2), bat.shot());//counting dealt damage
|
||||||
|
if(att->Luck() > 0 && rand()%24 < att->Luck())
|
||||||
|
{
|
||||||
|
bat.bsa.damageAmount *= 2;
|
||||||
|
bat.bsa.flags |= 4;
|
||||||
|
}
|
||||||
prepareAttacked(bat.bsa,def);
|
prepareAttacked(bat.bsa,def);
|
||||||
}
|
}
|
||||||
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
|
||||||
@ -2035,6 +2075,20 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
|
|||||||
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
|
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army1.slots.begin(); i!=army1.slots.end(); i++)
|
||||||
{
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
|
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero1->tempOwner, stacks.size(), true,i->first));
|
||||||
|
|
||||||
|
//base luck/morale calculations
|
||||||
|
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
||||||
|
if(hero1)
|
||||||
|
{
|
||||||
|
stacks.back()->morale = hero1->getCurrentMorale(i->first,false);
|
||||||
|
stacks.back()->luck = hero1->getCurrentLuck(i->first,false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stacks.back()->morale = 0;
|
||||||
|
stacks.back()->luck = 0;
|
||||||
|
}
|
||||||
|
|
||||||
stacks[stacks.size()-1]->ID = stacks.size()-1;
|
stacks[stacks.size()-1]->ID = stacks.size()-1;
|
||||||
}
|
}
|
||||||
//initialization of positions
|
//initialization of positions
|
||||||
@ -2068,7 +2122,21 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
|
|||||||
stacks[b]->position = attackerLoose[army1.slots.size()-1][b];
|
stacks[b]->position = attackerLoose[army1.slots.size()-1][b];
|
||||||
}
|
}
|
||||||
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
|
for(std::map<si32,std::pair<ui32,si32> >::iterator i = army2.slots.begin(); i!=army2.slots.end(); i++)
|
||||||
|
{
|
||||||
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first));
|
stacks.push_back(new CStack(&VLC->creh->creatures[i->second.first],i->second.second,hero2 ? hero2->tempOwner : 255, stacks.size(), false, i->first));
|
||||||
|
//base luck/morale calculations
|
||||||
|
//TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town
|
||||||
|
if(hero2)
|
||||||
|
{
|
||||||
|
stacks.back()->morale = hero2->getCurrentMorale(i->first,false);
|
||||||
|
stacks.back()->luck = hero2->getCurrentLuck(i->first,false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stacks.back()->morale = 0;
|
||||||
|
stacks.back()->luck = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(army2.formation)
|
if(army2.formation)
|
||||||
for(int b=0; b<army2.slots.size(); ++b) //tight
|
for(int b=0; b<army2.slots.size(); ++b) //tight
|
||||||
|
Loading…
Reference in New Issue
Block a user