mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
Version set to 0.83c, to be released as development build.
Code reorganizations in bonus system, allowing defining bonusNode-like classes. Fixed some issues with artifact handling (proper updating of GUI when moving, minor fixes). Restoring battle AI for neutrals after loading game.
This commit is contained in:
22
ChangeLog
22
ChangeLog
@ -1,14 +1,26 @@
|
|||||||
0.83 -> 0.84 (Mar 01 2011)
|
0.83 -> 0.84 (Mar 01 2011)
|
||||||
GENERAL:
|
GENERAL:
|
||||||
* Bonus system has been rewritten
|
* Bonus system has been rewritten
|
||||||
* Support for new artifacts (spell scrolls, angelic alliance)
|
* Partial support for running VCMI in duel mode (no adventure map, only one battle, ATM only AI-AI battles)
|
||||||
* Preliminary support for stack experience (no UI yet)
|
* New artifacts supported:
|
||||||
* Partial support for running VCMI in duel mode (no adventure map, only one battle)
|
- Angellic Alliance
|
||||||
|
- Bird of Perception
|
||||||
|
- Emblem of Cognizance
|
||||||
|
- Spell Scroll
|
||||||
|
- Stoic Watchman
|
||||||
|
|
||||||
BATTLES:
|
BATTLES:
|
||||||
* Support for eagle eye, tactics and artillery secondary skills (together with corresponding artifacts)
|
* Better animations handling
|
||||||
* Defensive stance is supported
|
* Defensive stance is supported
|
||||||
* New, improved AI for neutral player
|
|
||||||
|
HERO:
|
||||||
|
* New secondary skills supported:
|
||||||
|
- Artillery
|
||||||
|
- Eagle Eye
|
||||||
|
- Tactics
|
||||||
|
|
||||||
|
AI PLAYER:
|
||||||
|
* new AI leading neutral creatures in combat, slightly better then previous
|
||||||
|
|
||||||
|
|
||||||
0.82 -> 0.83 (Nov 01 2010)
|
0.82 -> 0.83 (Nov 01 2010)
|
||||||
|
@ -44,6 +44,28 @@
|
|||||||
extern SDL_Surface * screen;
|
extern SDL_Surface * screen;
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
|
void CHeroWithMaybePickedArtifact::getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||||
|
{
|
||||||
|
BonusList heroBonuses, bonusesFromPickedUpArtifact;
|
||||||
|
hero->getAllBonuses(heroBonuses, selector, limit, hero);
|
||||||
|
|
||||||
|
CArtifactsOfHero::SCommonPart *cp = cww->artSets.size() ? cww->artSets.front()->commonInfo : NULL;
|
||||||
|
if(cp && cp->src.art && cp->src.AOH && cp->src.AOH->getHero() == hero)
|
||||||
|
{
|
||||||
|
cp->src.art->getAllBonuses(bonusesFromPickedUpArtifact, selector, limit, hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(Bonus *b, bonusesFromPickedUpArtifact)
|
||||||
|
heroBonuses -= b;
|
||||||
|
BOOST_FOREACH(Bonus *b, heroBonuses)
|
||||||
|
out.push_back(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHeroWithMaybePickedArtifact::CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero)
|
||||||
|
: cww(Cww), hero(Hero)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void CHeroSwitcher::clickLeft(tribool down, bool previousState)
|
void CHeroSwitcher::clickLeft(tribool down, bool previousState)
|
||||||
{
|
{
|
||||||
if(!down)
|
if(!down)
|
||||||
@ -69,6 +91,7 @@ CHeroSwitcher::CHeroSwitcher(int serial)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
|
CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
|
||||||
|
: heroWArt(this, hero)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||||
garr = NULL;
|
garr = NULL;
|
||||||
@ -97,9 +120,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
|
|||||||
//right list of heroes
|
//right list of heroes
|
||||||
for(int g=0; g<8; ++g)
|
for(int g=0; g<8; ++g)
|
||||||
heroListMi.push_back(new CHeroSwitcher(g));
|
heroListMi.push_back(new CHeroSwitcher(g));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
flags = CDefHandler::giveDefEss("CREST58.DEF");
|
flags = CDefHandler::giveDefEss("CREST58.DEF");
|
||||||
|
|
||||||
//areas
|
//areas
|
||||||
@ -161,17 +182,16 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
|||||||
|
|
||||||
assert(hero == curHero);
|
assert(hero == curHero);
|
||||||
//assert(hero->tempOwner == LOCPLINT->playerID || hero->tempOwner == NEUTRAL_PLAYER); //for now we won't show hero windows for non-our heroes
|
//assert(hero->tempOwner == LOCPLINT->playerID || hero->tempOwner == NEUTRAL_PLAYER); //for now we won't show hero windows for non-our heroes
|
||||||
|
|
||||||
specArea->text = CGI->generaltexth->hTxts[hero->subID].longBonus;
|
specArea->text = CGI->generaltexth->hTxts[curHero->subID].longBonus;
|
||||||
|
|
||||||
tacticsButton->callback.clear();
|
tacticsButton->callback.clear();
|
||||||
tacticsButton->callback2.clear();
|
tacticsButton->callback2.clear();
|
||||||
|
|
||||||
dismissButton->hoverTexts[0] = boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name);
|
dismissButton->hoverTexts[0] = boost::str(boost::format(CGI->generaltexth->heroscrn[16]) % curHero->name % curHero->type->heroClass->name);
|
||||||
portraitArea->hoverText = boost::str(boost::format(CGI->generaltexth->allTexts[15]) % curHero->name % curHero->type->heroClass->name);
|
portraitArea->hoverText = boost::str(boost::format(CGI->generaltexth->allTexts[15]) % curHero->name % curHero->type->heroClass->name);
|
||||||
portraitArea->text = hero->getBiography();
|
portraitArea->text = curHero->getBiography();
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
AdventureMapButton * split = NULL;
|
AdventureMapButton * split = NULL;
|
||||||
{
|
{
|
||||||
@ -189,7 +209,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
|||||||
if(!artSets.size())
|
if(!artSets.size())
|
||||||
{
|
{
|
||||||
CArtifactsOfHero *arts = new CArtifactsOfHero(Point(-65, -8), true);
|
CArtifactsOfHero *arts = new CArtifactsOfHero(Point(-65, -8), true);
|
||||||
arts->setHero(hero);
|
arts->setHero(curHero);
|
||||||
artSets.push_back(arts);
|
artSets.push_back(arts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,14 +218,14 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
|||||||
//primary skills support
|
//primary skills support
|
||||||
for(size_t g=0; g<primSkillAreas.size(); ++g)
|
for(size_t g=0; g<primSkillAreas.size(); ++g)
|
||||||
{
|
{
|
||||||
primSkillAreas[g]->bonusValue = hero->getPrimSkillLevel(g);
|
primSkillAreas[g]->bonusValue = heroWArt.getPrimSkillLevel(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
//secondary skills support
|
//secondary skills support
|
||||||
for(size_t g=0; g< secSkillAreas.size(); ++g)
|
for(size_t g=0; g< secSkillAreas.size(); ++g)
|
||||||
{
|
{
|
||||||
int skill = hero->secSkills[g].first,
|
int skill = curHero->secSkills[g].first,
|
||||||
level = hero->getSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(hero->secSkills[g].first));
|
level = curHero->getSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(curHero->secSkills[g].first));
|
||||||
secSkillAreas[g]->type = skill;
|
secSkillAreas[g]->type = skill;
|
||||||
secSkillAreas[g]->bonusValue = level;
|
secSkillAreas[g]->bonusValue = level;
|
||||||
secSkillAreas[g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1];
|
secSkillAreas[g]->text = CGI->generaltexth->skillInfoTexts[skill][level-1];
|
||||||
@ -214,43 +234,43 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
|
|||||||
|
|
||||||
//printing experience - original format does not support ui64
|
//printing experience - original format does not support ui64
|
||||||
expArea->text = CGI->generaltexth->allTexts[2];
|
expArea->text = CGI->generaltexth->allTexts[2];
|
||||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(hero->level));
|
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(curHero->level));
|
||||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(CGI->heroh->reqExp(hero->level+1)));
|
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(CGI->heroh->reqExp(curHero->level+1)));
|
||||||
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(hero->exp));
|
boost::replace_first(expArea->text, "%d", boost::lexical_cast<std::string>(curHero->exp));
|
||||||
|
|
||||||
//printing spell points
|
//printing spell points
|
||||||
spellPointsArea->text = boost::str(boost::format(CGI->generaltexth->allTexts[205]) % hero->name % hero->mana % hero->manaLimit());
|
spellPointsArea->text = boost::str(boost::format(CGI->generaltexth->allTexts[205]) % curHero->name % curHero->mana % heroWArt.manaLimit());
|
||||||
|
|
||||||
//if we have exchange window with this hero open
|
//if we have exchange window with this curHero open
|
||||||
bool noDismiss=false;
|
bool noDismiss=false;
|
||||||
BOOST_FOREACH(IShowActivable *isa, GH.listInt)
|
BOOST_FOREACH(IShowActivable *isa, GH.listInt)
|
||||||
{
|
{
|
||||||
if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa))
|
if(CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>(isa))
|
||||||
for(int g=0; g < ARRAY_COUNT(cew->heroInst); ++g)
|
for(int g=0; g < ARRAY_COUNT(cew->heroInst); ++g)
|
||||||
if(cew->heroInst[g] == hero)
|
if(cew->heroInst[g] == curHero)
|
||||||
noDismiss = true;
|
noDismiss = true;
|
||||||
|
|
||||||
if (dynamic_cast<CKingdomInterface*>(isa))
|
if (dynamic_cast<CKingdomInterface*>(isa))
|
||||||
noDismiss = true;
|
noDismiss = true;
|
||||||
}
|
}
|
||||||
dismissButton->block(!!hero->visitedTown || noDismiss);
|
dismissButton->block(!!curHero->visitedTown || noDismiss);
|
||||||
|
|
||||||
if(hero->getSecSkillLevel(CGHeroInstance::TACTICS) == 0)
|
if(curHero->getSecSkillLevel(CGHeroInstance::TACTICS) == 0)
|
||||||
tacticsButton->block(true);
|
tacticsButton->block(true);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tacticsButton->block(false);
|
tacticsButton->block(false);
|
||||||
tacticsButton->callback = vstd::assigno(hero->tacticFormationEnabled,true);
|
tacticsButton->callback = vstd::assigno(curHero->tacticFormationEnabled,true);
|
||||||
tacticsButton->callback2 = vstd::assigno(hero->tacticFormationEnabled,false);
|
tacticsButton->callback2 = vstd::assigno(curHero->tacticFormationEnabled,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//setting formations
|
//setting formations
|
||||||
formations->onChange = 0;
|
formations->onChange = 0;
|
||||||
formations->select(hero->formation,true);
|
formations->select(curHero->formation,true);
|
||||||
formations->onChange = boost::bind(&CCallback::setFormation, LOCPLINT->cb, hero, _1);
|
formations->onChange = boost::bind(&CCallback::setFormation, LOCPLINT->cb, curHero, _1);
|
||||||
|
|
||||||
morale->set(hero);
|
morale->set(&heroWArt);
|
||||||
luck->set(hero);
|
luck->set(&heroWArt);
|
||||||
|
|
||||||
if(redrawNeeded)
|
if(redrawNeeded)
|
||||||
redraw();
|
redraw();
|
||||||
@ -271,6 +291,7 @@ void CHeroWindow::dismissCurrent()
|
|||||||
void CHeroWindow::questlog()
|
void CHeroWindow::questlog()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHeroWindow::showAll(SDL_Surface * to)
|
void CHeroWindow::showAll(SDL_Surface * to)
|
||||||
{
|
{
|
||||||
CIntObject::showAll(to);
|
CIntObject::showAll(to);
|
||||||
@ -319,7 +340,7 @@ void CHeroWindow::showAll(SDL_Surface * to)
|
|||||||
for(int m=0; m<4; ++m)
|
for(int m=0; m<4; ++m)
|
||||||
{
|
{
|
||||||
std::ostringstream primarySkill;
|
std::ostringstream primarySkill;
|
||||||
primarySkill<<curHero->getPrimSkillLevel(m);
|
primarySkill << primSkillAreas[m]->bonusValue;
|
||||||
printAtMiddleLoc(primarySkill.str(), 53 + 70 * m, 166, FONT_SMALL, zwykly, to);
|
printAtMiddleLoc(primarySkill.str(), 53 + 70 * m, 166, FONT_SMALL, zwykly, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,10 +386,10 @@ void CHeroWindow::showAll(SDL_Surface * to)
|
|||||||
//printing necessery texts
|
//printing necessery texts
|
||||||
printAtLoc(CGI->generaltexth->jktexts[6].substr(1, CGI->generaltexth->jktexts[6].size()-2), 69, 232, FONT_SMALL, tytulowy, to);
|
printAtLoc(CGI->generaltexth->jktexts[6].substr(1, CGI->generaltexth->jktexts[6].size()-2), 69, 232, FONT_SMALL, tytulowy, to);
|
||||||
std::ostringstream expstr;
|
std::ostringstream expstr;
|
||||||
expstr<<curHero->exp;
|
expstr << curHero->exp;
|
||||||
printAtLoc(expstr.str(), 68, 252, FONT_SMALL, zwykly, to);
|
printAtLoc(expstr.str(), 68, 252, FONT_SMALL, zwykly, to);
|
||||||
printAtLoc(CGI->generaltexth->jktexts[7].substr(1, CGI->generaltexth->jktexts[7].size()-2), 213, 232, FONT_SMALL, tytulowy, to);
|
printAtLoc(CGI->generaltexth->jktexts[7].substr(1, CGI->generaltexth->jktexts[7].size()-2), 213, 232, FONT_SMALL, tytulowy, to);
|
||||||
std::ostringstream manastr;
|
std::ostringstream manastr;
|
||||||
manastr << curHero->mana << '/' << curHero->manaLimit();
|
manastr << curHero->mana << '/' << heroWArt.manaLimit();
|
||||||
printAtLoc(manastr.str(), 211, 252, FONT_SMALL, zwykly, to);
|
printAtLoc(manastr.str(), 211, 252, FONT_SMALL, zwykly, to);
|
||||||
}
|
}
|
@ -37,7 +37,16 @@ public:
|
|||||||
CHeroSwitcher(int serial);
|
CHeroSwitcher(int serial);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//helper class for calculating values of hero bonuses without bonuses from picked up artifact
|
||||||
|
class CHeroWithMaybePickedArtifact : public IBonusBearer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const CGHeroInstance *hero;
|
||||||
|
CWindowWithArtifacts *cww;
|
||||||
|
|
||||||
|
CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero);
|
||||||
|
void getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts
|
class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts
|
||||||
{
|
{
|
||||||
@ -61,6 +70,8 @@ class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts
|
|||||||
LRClickableAreaWText * specArea;//speciality
|
LRClickableAreaWText * specArea;//speciality
|
||||||
MoraleLuckBox * morale, * luck;
|
MoraleLuckBox * morale, * luck;
|
||||||
std::vector<LRClickableAreaWTextComp *> secSkillAreas;
|
std::vector<LRClickableAreaWTextComp *> secSkillAreas;
|
||||||
|
CHeroWithMaybePickedArtifact heroWArt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const CGHeroInstance * curHero;
|
const CGHeroInstance * curHero;
|
||||||
AdventureMapButton * quitButton, * dismissButton, * questlogButton; //general
|
AdventureMapButton * quitButton, * dismissButton, * questlogButton; //general
|
||||||
|
@ -430,10 +430,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
battleints[255] = CAIHandler::getNewBattleAI(conf.cc.defaultBattleAI);
|
loadNeutralBattleAI();
|
||||||
battleints[255]->init(new CBattleCallback(gs, 255, this));
|
|
||||||
// playerint[255]->init(new CCallback(gs,255,this));
|
|
||||||
// battleints[255] = playerint[255];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state);
|
serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state);
|
||||||
@ -493,6 +490,9 @@ void CClient::serialize( Handler &h, const int version )
|
|||||||
nInt->init(callback);
|
nInt->init(callback);
|
||||||
nInt->serialize(h, version);
|
nInt->serialize(h, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!vstd::contains(battleints, NEUTRAL_PLAYER))
|
||||||
|
loadNeutralBattleAI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,6 +588,12 @@ void CClient::battleStarted(const BattleInfo * info)
|
|||||||
battleints[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
|
battleints[254]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CClient::loadNeutralBattleAI()
|
||||||
|
{
|
||||||
|
battleints[255] = CAIHandler::getNewBattleAI(conf.cc.defaultBattleAI);
|
||||||
|
battleints[255]->init(new CBattleCallback(gs, 255, this));
|
||||||
|
}
|
||||||
|
|
||||||
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
|
template void CClient::serialize( CISer<CLoadFile> &h, const int version );
|
||||||
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
|
template void CClient::serialize( COSer<CSaveFile> &h, const int version );
|
||||||
|
|
||||||
|
@ -82,6 +82,8 @@ public:
|
|||||||
|
|
||||||
void init();
|
void init();
|
||||||
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
void newGame(CConnection *con, StartInfo *si); //con - connection to server
|
||||||
|
|
||||||
|
void loadNeutralBattleAI();
|
||||||
void endGame(bool closeConnection = true);
|
void endGame(bool closeConnection = true);
|
||||||
void stopConnection();
|
void stopConnection();
|
||||||
void save(const std::string & fname);
|
void save(const std::string & fname);
|
||||||
|
@ -74,6 +74,7 @@ CFocusable * CFocusable::inputWithFocus;
|
|||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
|
|
||||||
|
|
||||||
void CGarrisonSlot::hover (bool on)
|
void CGarrisonSlot::hover (bool on)
|
||||||
{
|
{
|
||||||
////Hoverable::hover(on);
|
////Hoverable::hover(on);
|
||||||
@ -4663,7 +4664,6 @@ void CArtPlace::select ()
|
|||||||
if(slotID >= Arts::BACKPACK_START)
|
if(slotID >= Arts::BACKPACK_START)
|
||||||
ourOwner->scrollBackpack(0); //will update slots
|
ourOwner->scrollBackpack(0); //will update slots
|
||||||
|
|
||||||
// Update the hero bonuses.
|
|
||||||
ourOwner->updateParentWindow();
|
ourOwner->updateParentWindow();
|
||||||
ourOwner->safeRedraw();
|
ourOwner->safeRedraw();
|
||||||
}
|
}
|
||||||
@ -4695,7 +4695,7 @@ void CArtPlace::deactivate()
|
|||||||
|
|
||||||
void CArtPlace::showAll(SDL_Surface *to)
|
void CArtPlace::showAll(SDL_Surface *to)
|
||||||
{
|
{
|
||||||
if (ourArt && !picked)
|
if (ourArt && !picked && ourArt == ourOwner->curHero->getArt(slotID)) //last condition is needed for disassembling -> artifact may be gone, but we don't know yet TODO: real, nice solution
|
||||||
{
|
{
|
||||||
int graphic = locked ? 145 : ourArt->artType->id;
|
int graphic = locked ? 145 : ourArt->artType->id;
|
||||||
blitAt(graphics->artDefs->ourImages[graphic].bitmap, pos.x, pos.y, to);
|
blitAt(graphics->artDefs->ourImages[graphic].bitmap, pos.x, pos.y, to);
|
||||||
@ -5161,16 +5161,17 @@ void CArtifactsOfHero::updateParentWindow()
|
|||||||
if(!updateState)
|
if(!updateState)
|
||||||
{
|
{
|
||||||
cew->deactivate();
|
cew->deactivate();
|
||||||
for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
|
// for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
|
||||||
{
|
// {
|
||||||
if(cew->heroInst[g] == curHero)
|
// if(cew->heroInst[g] == curHero)
|
||||||
{
|
// {
|
||||||
cew->artifs[g]->setHero(curHero);
|
// cew->artifs[g]->setHero(curHero);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
cew->prepareBackground();
|
cew->prepareBackground();
|
||||||
|
cew->redraw();
|
||||||
cew->activate();
|
cew->activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5199,13 +5200,14 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
|
|||||||
if(dst.hero == curHero && dst.slot >= Arts::BACKPACK_START)
|
if(dst.hero == curHero && dst.slot >= Arts::BACKPACK_START)
|
||||||
setSlotData(getArtPlace(dst.slot), dst.slot);
|
setSlotData(getArtPlace(dst.slot), dst.slot);
|
||||||
if(src.hero == curHero || dst.hero == curHero) //we need to update all slots, artifact might be combined and affect more slots
|
if(src.hero == curHero || dst.hero == curHero) //we need to update all slots, artifact might be combined and affect more slots
|
||||||
updateWornSlots();
|
updateWornSlots(false);
|
||||||
|
|
||||||
if(commonInfo->src == src) //artifact was taken from us
|
if(commonInfo->src == src) //artifact was taken from us
|
||||||
{
|
{
|
||||||
assert(commonInfo->dst == dst || dst.slot == dst.hero->artifactsInBackpack.size() + Arts::BACKPACK_START);
|
assert(commonInfo->dst == dst || dst.slot == dst.hero->artifactsInBackpack.size() + Arts::BACKPACK_START);
|
||||||
commonInfo->reset();
|
commonInfo->reset();
|
||||||
unmarkSlots();
|
unmarkSlots();
|
||||||
|
updateParentWindow();
|
||||||
}
|
}
|
||||||
else if(commonInfo->dst == src) //the dest artifact was moved -> we are picking it
|
else if(commonInfo->dst == src) //the dest artifact was moved -> we are picking it
|
||||||
{
|
{
|
||||||
@ -5289,12 +5291,18 @@ void CArtifactsOfHero::artifactDisassembled(const ArtifactLocation &al)
|
|||||||
updateWornSlots();
|
updateWornSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CArtifactsOfHero::updateWornSlots()
|
void CArtifactsOfHero::updateWornSlots(bool redrawParent /*= true*/)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < Arts::BACKPACK_START; i++)
|
for(int i = 0; i < Arts::BACKPACK_START; i++)
|
||||||
setSlotData(getArtPlace(i), i);
|
setSlotData(getArtPlace(i), i);
|
||||||
|
|
||||||
updateParentWindow();
|
if(redrawParent)
|
||||||
|
updateParentWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
const CGHeroInstance * CArtifactsOfHero::getHero() const
|
||||||
|
{
|
||||||
|
return curHero;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CExchangeWindow::close()
|
void CExchangeWindow::close()
|
||||||
@ -5307,9 +5315,9 @@ void CExchangeWindow::activate()
|
|||||||
quit->activate();
|
quit->activate();
|
||||||
garr->activate();
|
garr->activate();
|
||||||
|
|
||||||
artifs[0]->setHero(heroInst[0]);
|
//artifs[0]->setHero(heroInst[0]);
|
||||||
artifs[0]->activate();
|
artifs[0]->activate();
|
||||||
artifs[1]->setHero(heroInst[1]);
|
//artifs[1]->setHero(heroInst[1]);
|
||||||
artifs[1]->activate();
|
artifs[1]->activate();
|
||||||
|
|
||||||
for(int g=0; g<ARRAY_COUNT(secSkillAreas); g++)
|
for(int g=0; g<ARRAY_COUNT(secSkillAreas); g++)
|
||||||
@ -5446,11 +5454,12 @@ void CExchangeWindow::prepareBackground()
|
|||||||
//heroes related thing
|
//heroes related thing
|
||||||
for(int b=0; b<ARRAY_COUNT(heroInst); b++)
|
for(int b=0; b<ARRAY_COUNT(heroInst); b++)
|
||||||
{
|
{
|
||||||
|
CHeroWithMaybePickedArtifact heroWArt = CHeroWithMaybePickedArtifact(this, heroInst[b]);
|
||||||
//printing primary skills' amounts
|
//printing primary skills' amounts
|
||||||
for(int m=0; m<4; ++m)
|
for(int m=0; m<4; ++m)
|
||||||
{
|
{
|
||||||
std::ostringstream primarySkill;
|
std::ostringstream primarySkill;
|
||||||
primarySkill<<heroInst[b]->getPrimSkillLevel(m);
|
primarySkill << heroWArt.getPrimSkillLevel(m);
|
||||||
CSDL_Ext::printAtMiddle(primarySkill.str(), 352 + 93 * b, 35 + 36 * m, FONT_SMALL, zwykly, bg);
|
CSDL_Ext::printAtMiddle(primarySkill.str(), 352 + 93 * b, 35 + 36 * m, FONT_SMALL, zwykly, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5472,10 +5481,10 @@ void CExchangeWindow::prepareBackground()
|
|||||||
printAtMiddle( makeNumberShort(heroInst[b]->mana), 155 + 490*b, 71, FONT_SMALL, zwykly, bg );
|
printAtMiddle( makeNumberShort(heroInst[b]->mana), 155 + 490*b, 71, FONT_SMALL, zwykly, bg );
|
||||||
|
|
||||||
//setting morale
|
//setting morale
|
||||||
blitAt(graphics->morale30->ourImages[heroInst[b]->MoraleVal()+3].bitmap, 177 + 490*b, 45, bg);
|
blitAt(graphics->morale30->ourImages[heroWArt.MoraleVal()+3].bitmap, 177 + 490*b, 45, bg);
|
||||||
|
|
||||||
//setting luck
|
//setting luck
|
||||||
blitAt(graphics->luck30->ourImages[heroInst[b]->LuckVal()+3].bitmap, 213 + 490*b, 45, bg);
|
blitAt(graphics->luck30->ourImages[heroWArt.LuckVal()+3].bitmap, 213 + 490*b, 45, bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//printing portraits
|
//printing portraits
|
||||||
@ -6453,7 +6462,7 @@ CThievesGuildWindow::~CThievesGuildWindow()
|
|||||||
// delete resdatabar;
|
// delete resdatabar;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoraleLuckBox::set(const CBonusSystemNode *node)
|
void MoraleLuckBox::set(const IBonusBearer *node)
|
||||||
{
|
{
|
||||||
const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:}
|
const int textId[] = {62, 88}; //eg %s \n\n\n {Current Luck Modifiers:}
|
||||||
const int noneTxtId = 108; //Russian version uses same text for neutral morale\luck
|
const int noneTxtId = 108; //Russian version uses same text for neutral morale\luck
|
||||||
@ -6461,7 +6470,7 @@ void MoraleLuckBox::set(const CBonusSystemNode *node)
|
|||||||
const int componentType[] = {SComponent::luck, SComponent::morale};
|
const int componentType[] = {SComponent::luck, SComponent::morale};
|
||||||
const int hoverTextBase[] = {7, 4};
|
const int hoverTextBase[] = {7, 4};
|
||||||
const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE};
|
const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE};
|
||||||
int (CBonusSystemNode::*getValue[])() const = {&CBonusSystemNode::LuckVal, &CBonusSystemNode::MoraleVal};
|
int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal};
|
||||||
|
|
||||||
int mrlt = -9;
|
int mrlt = -9;
|
||||||
TModDescr mrl;
|
TModDescr mrl;
|
||||||
@ -6484,8 +6493,7 @@ void MoraleLuckBox::set(const CBonusSystemNode *node)
|
|||||||
text += CGI->generaltexth->arraytxt[noneTxtId];
|
text += CGI->generaltexth->arraytxt[noneTxtId];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (node->nodeType == CBonusSystemNode::STACK_INSTANCE &&
|
if (node->hasBonusOfType (Bonus::UNDEAD) || node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::NON_LIVING)) //it's a creature window
|
||||||
(node->hasBonusOfType (Bonus::UNDEAD) || node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::NON_LIVING))) //it's a creature window
|
|
||||||
{
|
{
|
||||||
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
|
text += CGI->generaltexth->arraytxt[113]; //unaffected by morale
|
||||||
}
|
}
|
||||||
@ -6899,4 +6907,4 @@ bool CArtifactsOfHero::SCommonPart::Artpos::valid()
|
|||||||
{
|
{
|
||||||
assert(AOH && art);
|
assert(AOH && art);
|
||||||
return art == AOH->curHero->getArt(slotID);
|
return art == AOH->curHero->getArt(slotID);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ class CStackInstance;
|
|||||||
class IMarket;
|
class IMarket;
|
||||||
class CTextBox;
|
class CTextBox;
|
||||||
class CArtifactInstance;
|
class CArtifactInstance;
|
||||||
|
class IBonusBearer;
|
||||||
|
|
||||||
extern SDL_Color tytulowy, tlo, zwykly ;
|
extern SDL_Color tytulowy, tlo, zwykly ;
|
||||||
|
|
||||||
@ -878,7 +879,7 @@ class MoraleLuckBox : public LRClickableAreaWTextComp
|
|||||||
public:
|
public:
|
||||||
bool morale; //true if morale, false if luck
|
bool morale; //true if morale, false if luck
|
||||||
|
|
||||||
void set(const CBonusSystemNode *node);
|
void set(const IBonusBearer *node);
|
||||||
void showAll(SDL_Surface * to);
|
void showAll(SDL_Surface * to);
|
||||||
|
|
||||||
MoraleLuckBox(bool Morale, const Rect &r);
|
MoraleLuckBox(bool Morale, const Rect &r);
|
||||||
@ -972,7 +973,7 @@ public:
|
|||||||
/// Contains artifacts of hero. Distincts which artifacts are worn or backpacked
|
/// Contains artifacts of hero. Distincts which artifacts are worn or backpacked
|
||||||
class CArtifactsOfHero : public CIntObject
|
class CArtifactsOfHero : public CIntObject
|
||||||
{
|
{
|
||||||
const CGHeroInstance * curHero; //local copy of hero on which we operate
|
const CGHeroInstance * curHero;
|
||||||
|
|
||||||
std::vector<CArtPlace *> artWorn; // 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
|
std::vector<CArtPlace *> artWorn; // 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
|
||||||
std::vector<CArtPlace *> backpack; //hero's visible backpack (only 5 elements!)
|
std::vector<CArtPlace *> backpack; //hero's visible backpack (only 5 elements!)
|
||||||
@ -1012,6 +1013,7 @@ public:
|
|||||||
CArtPlace *getArtPlace(int slot);
|
CArtPlace *getArtPlace(int slot);
|
||||||
|
|
||||||
void setHero(const CGHeroInstance * hero);
|
void setHero(const CGHeroInstance * hero);
|
||||||
|
const CGHeroInstance *getHero() const;
|
||||||
void dispose(); //free resources not needed after closing windows and reset state
|
void dispose(); //free resources not needed after closing windows and reset state
|
||||||
void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right
|
void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right
|
||||||
|
|
||||||
@ -1019,7 +1021,7 @@ public:
|
|||||||
void markPossibleSlots(const CArtifactInstance* art);
|
void markPossibleSlots(const CArtifactInstance* art);
|
||||||
void unmarkSlots(bool withRedraw = true);
|
void unmarkSlots(bool withRedraw = true);
|
||||||
void setSlotData (CArtPlace* artPlace, int slotID);
|
void setSlotData (CArtPlace* artPlace, int slotID);
|
||||||
void updateWornSlots ();
|
void updateWornSlots (bool redrawParent = true);
|
||||||
void eraseSlotData (CArtPlace* artPlace, int slotID);
|
void eraseSlotData (CArtPlace* artPlace, int slotID);
|
||||||
|
|
||||||
CArtifactsOfHero(const Point& position, bool createCommonPart = false); //c-tor
|
CArtifactsOfHero(const Point& position, bool createCommonPart = false); //c-tor
|
||||||
|
2
global.h
2
global.h
@ -33,7 +33,7 @@ typedef si32 TBonusSubtype;
|
|||||||
#define THC
|
#define THC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NAME_VER ("VCMI 0.83b")
|
#define NAME_VER ("VCMI 0.83c")
|
||||||
extern std::string NAME; //full name
|
extern std::string NAME; //full name
|
||||||
extern std::string NAME_AFFIX; //client / server
|
extern std::string NAME_AFFIX; //client / server
|
||||||
#define CONSOLE_LOGGING_LEVEL 5
|
#define CONSOLE_LOGGING_LEVEL 5
|
||||||
|
@ -622,30 +622,11 @@ int3 CGHeroInstance::getPosition(bool h3m) const //h3m=true - returns position o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
si32 CGHeroInstance::manaLimit() const
|
|
||||||
{
|
|
||||||
return si32(getPrimSkillLevel(3) * (100.0f + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 24)) / 10.0f);
|
|
||||||
}
|
|
||||||
//void CGHeroInstance::setPosition(int3 Pos, bool h3m) //as above, but sets position
|
|
||||||
//{
|
|
||||||
// if (h3m)
|
|
||||||
// pos = Pos;
|
|
||||||
// else
|
|
||||||
// pos = convertPosition(Pos,true);
|
|
||||||
//}
|
|
||||||
|
|
||||||
bool CGHeroInstance::canWalkOnSea() const
|
bool CGHeroInstance::canWalkOnSea() const
|
||||||
{
|
{
|
||||||
return hasBonusOfType(Bonus::FLYING_MOVEMENT) || hasBonusOfType(Bonus::WATER_WALKING);
|
return hasBonusOfType(Bonus::FLYING_MOVEMENT) || hasBonusOfType(Bonus::WATER_WALKING);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CGHeroInstance::getPrimSkillLevel(int id) const
|
|
||||||
{
|
|
||||||
int ret = valOfBonuses(Bonus::PRIMARY_SKILL, id);
|
|
||||||
amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui8 CGHeroInstance::getSecSkillLevel(SecondarySkill skill) const
|
ui8 CGHeroInstance::getSecSkillLevel(SecondarySkill skill) const
|
||||||
{
|
{
|
||||||
for(size_t i=0; i < secSkills.size(); ++i)
|
for(size_t i=0; i < secSkills.size(); ++i)
|
||||||
|
@ -386,16 +386,11 @@ public:
|
|||||||
unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
|
||||||
unsigned int getLowestCreatureSpeed() const;
|
unsigned int getLowestCreatureSpeed() const;
|
||||||
int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
|
int3 getPosition(bool h3m = false) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
|
||||||
si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
|
|
||||||
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
|
||||||
bool canWalkOnSea() const;
|
bool canWalkOnSea() const;
|
||||||
int getCurrentLuck(int stack=-1, bool town=false) const;
|
int getCurrentLuck(int stack=-1, bool town=false) const;
|
||||||
int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
|
int getSpellCost(const CSpell *sp) const; //do not use during battles -> bonuses from army would be ignored
|
||||||
|
|
||||||
TModDescr getCurrentLuckModifiers(int stack=-1, bool town=false) const; //args as above
|
|
||||||
int getCurrentMorale(int stack=-1, bool town=false) const; //if stack - position of creature, if -1 then morale for hero is calculated; town - if bonuses from town (tavern) should be considered
|
|
||||||
TModDescr getCurrentMoraleModifiers(int stack=-1, bool town=false) const; //args as above
|
|
||||||
int getPrimSkillLevel(int id) const; //0-attack, 1-defence, 2-spell power, 3-knowledge
|
|
||||||
ui8 getSecSkillLevel(SecondarySkill skill) const; //0 - no skill
|
ui8 getSecSkillLevel(SecondarySkill skill) const; //0 - no skill
|
||||||
void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value
|
void setSecSkillLevel(SecondarySkill which, int val, bool abs);// abs == 0 - changes by value; 1 - sets to value
|
||||||
|
|
||||||
|
@ -140,12 +140,12 @@ void DLL_EXPORT BonusList::eliminateDuplicates()
|
|||||||
unique();
|
unique();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
|
int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
|
||||||
{
|
{
|
||||||
return valOfBonuses(Selector::type(type) && selector);
|
return valOfBonuses(Selector::type(type) && selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
|
int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
|
||||||
{
|
{
|
||||||
CSelector s = Selector::type(type);
|
CSelector s = Selector::type(type);
|
||||||
if(subtype != -1)
|
if(subtype != -1)
|
||||||
@ -154,18 +154,18 @@ int CBonusSystemNode::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/)
|
|||||||
return valOfBonuses(s);
|
return valOfBonuses(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CBonusSystemNode::valOfBonuses(const CSelector &selector) const
|
int IBonusBearer::valOfBonuses(const CSelector &selector) const
|
||||||
{
|
{
|
||||||
BonusList hlp;
|
BonusList hlp;
|
||||||
getBonuses(hlp, selector);
|
getBonuses(hlp, selector);
|
||||||
return hlp.totalValue();
|
return hlp.totalValue();
|
||||||
}
|
}
|
||||||
bool CBonusSystemNode::hasBonus(const CSelector &selector) const
|
bool IBonusBearer::hasBonus(const CSelector &selector) const
|
||||||
{
|
{
|
||||||
return getBonuses(selector).size() > 0;
|
return getBonuses(selector).size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBonusSystemNode::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) const
|
bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) const
|
||||||
{
|
{
|
||||||
CSelector s = Selector::type(type);
|
CSelector s = Selector::type(type);
|
||||||
if(subtype != -1)
|
if(subtype != -1)
|
||||||
@ -174,6 +174,150 @@ bool CBonusSystemNode::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*
|
|||||||
return hasBonus(s);
|
return hasBonus(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IBonusBearer::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
|
||||||
|
{
|
||||||
|
getModifiersWDescr(out, subtype != -1 ? Selector::typeSybtype(type, subtype) : Selector::type(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IBonusBearer::getModifiersWDescr(TModDescr &out, const CSelector &selector) const
|
||||||
|
{
|
||||||
|
getBonuses(selector).getModifiersWDescr(out);
|
||||||
|
}
|
||||||
|
int IBonusBearer::getBonusesCount(int from, int id) const
|
||||||
|
{
|
||||||
|
return getBonusesCount(Selector::source(from, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
int IBonusBearer::getBonusesCount(const CSelector &selector) const
|
||||||
|
{
|
||||||
|
return getBonuses(selector).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IBonusBearer::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
|
||||||
|
{
|
||||||
|
getBonuses(out, selector, 0, root);
|
||||||
|
// FOREACH_CONST_PARENT(p)
|
||||||
|
// p->getBonuses(out, selector, root ? root : this);
|
||||||
|
//
|
||||||
|
// bonuses.getBonuses(out, selector);
|
||||||
|
//
|
||||||
|
// if(!root)
|
||||||
|
// out.limit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
BonusList IBonusBearer::getBonuses(const CSelector &selector) const
|
||||||
|
{
|
||||||
|
BonusList ret;
|
||||||
|
getBonuses(ret, selector);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IBonusBearer::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||||
|
{
|
||||||
|
getAllBonuses(out, selector, limit, root);
|
||||||
|
out.eliminateDuplicates();
|
||||||
|
//
|
||||||
|
// getBonuses(out, selector); //first get all the bonuses
|
||||||
|
// out.remove_if(std::not1(limit)); //now remove the ones we don't like
|
||||||
|
// out.limit(*this); //apply bonuses' limiters
|
||||||
|
}
|
||||||
|
|
||||||
|
BonusList IBonusBearer::getBonuses(const CSelector &selector, const CSelector &limit) const
|
||||||
|
{
|
||||||
|
BonusList ret;
|
||||||
|
getBonuses(ret, selector, limit);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IBonusBearer::hasBonusFrom(ui8 source, ui32 sourceID) const
|
||||||
|
{
|
||||||
|
return hasBonus(Selector::source(source,sourceID));
|
||||||
|
}
|
||||||
|
|
||||||
|
int IBonusBearer::MoraleVal() const
|
||||||
|
{
|
||||||
|
if(hasBonusOfType(Bonus::NON_LIVING) || hasBonusOfType(Bonus::UNDEAD) ||
|
||||||
|
hasBonusOfType(Bonus::NO_MORALE) || hasBonusOfType(Bonus::SIEGE_WEAPON))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int ret = valOfBonuses(Selector::type(Bonus::MORALE));
|
||||||
|
|
||||||
|
if(hasBonusOfType(Bonus::SELF_MORALE)) //eg. minotaur
|
||||||
|
amax(ret, +1);
|
||||||
|
|
||||||
|
return abetw(ret, -3, +3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IBonusBearer::LuckVal() const
|
||||||
|
{
|
||||||
|
if(hasBonusOfType(Bonus::NO_LUCK))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int ret = valOfBonuses(Selector::type(Bonus::LUCK));
|
||||||
|
|
||||||
|
if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
|
||||||
|
amax(ret, +1);
|
||||||
|
|
||||||
|
return abetw(ret, -3, +3);
|
||||||
|
}
|
||||||
|
|
||||||
|
si32 IBonusBearer::Attack() const
|
||||||
|
{
|
||||||
|
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);
|
||||||
|
|
||||||
|
if(int frenzyPower = valOfBonuses(Bonus::IN_FRENZY)) //frenzy for attacker
|
||||||
|
{
|
||||||
|
ret += frenzyPower * Defense(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
si32 IBonusBearer::Defense(bool withFrenzy /*= true*/) const
|
||||||
|
{
|
||||||
|
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);
|
||||||
|
|
||||||
|
if(withFrenzy && hasBonusOfType(Bonus::IN_FRENZY)) //frenzy for defender
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui16 IBonusBearer::MaxHealth() const
|
||||||
|
{
|
||||||
|
return valOfBonuses(Bonus::STACK_HEALTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui32 IBonusBearer::getMinDamage() const
|
||||||
|
{
|
||||||
|
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 1));
|
||||||
|
}
|
||||||
|
ui32 IBonusBearer::getMaxDamage() const
|
||||||
|
{
|
||||||
|
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
si32 IBonusBearer::manaLimit() const
|
||||||
|
{
|
||||||
|
return si32(getPrimSkillLevel(3) * (100.0f + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 24)) / 10.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IBonusBearer::getPrimSkillLevel(int id) const
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if(id == PrimarySkill::ATTACK)
|
||||||
|
ret = Attack();
|
||||||
|
else if(id == PrimarySkill::DEFENSE)
|
||||||
|
ret = Defense();
|
||||||
|
else
|
||||||
|
ret = valOfBonuses(Bonus::PRIMARY_SKILL, id);
|
||||||
|
|
||||||
|
amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
Bonus * CBonusSystemNode::getBonus(const CSelector &selector)
|
Bonus * CBonusSystemNode::getBonus(const CSelector &selector)
|
||||||
{
|
{
|
||||||
Bonus *ret = bonuses.getFirst(selector);
|
Bonus *ret = bonuses.getFirst(selector);
|
||||||
@ -195,25 +339,6 @@ const Bonus * CBonusSystemNode::getBonus( const CSelector &selector ) const
|
|||||||
return (const_cast<CBonusSystemNode*>(this))->getBonus(selector);
|
return (const_cast<CBonusSystemNode*>(this))->getBonus(selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBonusSystemNode::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
|
|
||||||
{
|
|
||||||
getModifiersWDescr(out, subtype != -1 ? Selector::typeSybtype(type, subtype) : Selector::type(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBonusSystemNode::getModifiersWDescr(TModDescr &out, const CSelector &selector) const
|
|
||||||
{
|
|
||||||
getBonuses(selector).getModifiersWDescr(out);
|
|
||||||
}
|
|
||||||
int CBonusSystemNode::getBonusesCount(int from, int id) const
|
|
||||||
{
|
|
||||||
return getBonusesCount(Selector::source(from, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
int CBonusSystemNode::getBonusesCount(const CSelector &selector) const
|
|
||||||
{
|
|
||||||
return getBonuses(selector).size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBonusSystemNode::getParents(TCNodes &out) const /*retreives list of parent nodes (nodes to inherit bonuses from) */
|
void CBonusSystemNode::getParents(TCNodes &out) const /*retreives list of parent nodes (nodes to inherit bonuses from) */
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const CBonusSystemNode *parent, parents)
|
BOOST_FOREACH(const CBonusSystemNode *parent, parents)
|
||||||
@ -226,42 +351,6 @@ void CBonusSystemNode::getParents(TNodes &out)
|
|||||||
out.insert(const_cast<CBonusSystemNode*>(parent));
|
out.insert(const_cast<CBonusSystemNode*>(parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const
|
|
||||||
{
|
|
||||||
getBonuses(out, selector, 0, root);
|
|
||||||
// FOREACH_CONST_PARENT(p)
|
|
||||||
// p->getBonuses(out, selector, root ? root : this);
|
|
||||||
//
|
|
||||||
// bonuses.getBonuses(out, selector);
|
|
||||||
//
|
|
||||||
// if(!root)
|
|
||||||
// out.limit(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
BonusList CBonusSystemNode::getBonuses(const CSelector &selector) const
|
|
||||||
{
|
|
||||||
BonusList ret;
|
|
||||||
getBonuses(ret, selector);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBonusSystemNode::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
|
||||||
{
|
|
||||||
getAllBonuses(out, selector, limit, root);
|
|
||||||
out.eliminateDuplicates();
|
|
||||||
//
|
|
||||||
// getBonuses(out, selector); //first get all the bonuses
|
|
||||||
// out.remove_if(std::not1(limit)); //now remove the ones we don't like
|
|
||||||
// out.limit(*this); //apply bonuses' limiters
|
|
||||||
}
|
|
||||||
|
|
||||||
BonusList CBonusSystemNode::getBonuses(const CSelector &selector, const CSelector &limit) const
|
|
||||||
{
|
|
||||||
BonusList ret;
|
|
||||||
getBonuses(ret, selector, limit);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBonusSystemNode::getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
void CBonusSystemNode::getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/) const
|
||||||
{
|
{
|
||||||
FOREACH_CONST_PARENT(p)
|
FOREACH_CONST_PARENT(p)
|
||||||
@ -273,76 +362,6 @@ void CBonusSystemNode::getAllBonuses(BonusList &out, const CSelector &selector,
|
|||||||
out.limit(*this);
|
out.limit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBonusSystemNode::hasBonusFrom(ui8 source, ui32 sourceID) const
|
|
||||||
{
|
|
||||||
return hasBonus(Selector::source(source,sourceID));
|
|
||||||
}
|
|
||||||
|
|
||||||
int CBonusSystemNode::MoraleVal() const
|
|
||||||
{
|
|
||||||
if(hasBonusOfType(Bonus::NON_LIVING) || hasBonusOfType(Bonus::UNDEAD) ||
|
|
||||||
hasBonusOfType(Bonus::NO_MORALE) || hasBonusOfType(Bonus::SIEGE_WEAPON))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int ret = valOfBonuses(Selector::type(Bonus::MORALE));
|
|
||||||
|
|
||||||
if(hasBonusOfType(Bonus::SELF_MORALE)) //eg. minotaur
|
|
||||||
amax(ret, +1);
|
|
||||||
|
|
||||||
return abetw(ret, -3, +3);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CBonusSystemNode::LuckVal() const
|
|
||||||
{
|
|
||||||
if(hasBonusOfType(Bonus::NO_LUCK))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int ret = valOfBonuses(Selector::type(Bonus::LUCK));
|
|
||||||
|
|
||||||
if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
|
|
||||||
amax(ret, +1);
|
|
||||||
|
|
||||||
return abetw(ret, -3, +3);
|
|
||||||
}
|
|
||||||
|
|
||||||
si32 CBonusSystemNode::Attack() const
|
|
||||||
{
|
|
||||||
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);
|
|
||||||
|
|
||||||
if(int frenzyPower = valOfBonuses(Bonus::IN_FRENZY)) //frenzy for attacker
|
|
||||||
{
|
|
||||||
ret += frenzyPower * Defense(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
si32 CBonusSystemNode::Defense(bool withFrenzy /*= true*/) const
|
|
||||||
{
|
|
||||||
si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);
|
|
||||||
|
|
||||||
if(withFrenzy && hasBonusOfType(Bonus::IN_FRENZY)) //frenzy for defender
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui16 CBonusSystemNode::MaxHealth() const
|
|
||||||
{
|
|
||||||
return valOfBonuses(Bonus::STACK_HEALTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui32 CBonusSystemNode::getMinDamage() const
|
|
||||||
{
|
|
||||||
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 1));
|
|
||||||
}
|
|
||||||
ui32 CBonusSystemNode::getMaxDamage() const
|
|
||||||
{
|
|
||||||
return valOfBonuses(Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSybtype(Bonus::CREATURE_DAMAGE, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
CBonusSystemNode::CBonusSystemNode()
|
CBonusSystemNode::CBonusSystemNode()
|
||||||
{
|
{
|
||||||
nodeType = UNKNOWN;
|
nodeType = UNKNOWN;
|
||||||
|
@ -369,7 +369,47 @@ public:
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_EXPORT CBonusSystemNode
|
class DLL_EXPORT IBonusBearer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const = 0;
|
||||||
|
|
||||||
|
//new bonusing node interface
|
||||||
|
// * selector is predicate that tests if HeroBonus matches our criteria
|
||||||
|
// * root is node on which call was made (NULL will be replaced with this)
|
||||||
|
//interface
|
||||||
|
void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const; //as above but without duplicates
|
||||||
|
void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const;
|
||||||
|
void getModifiersWDescr(TModDescr &out, const CSelector &selector) const; //out: pairs<modifier value, modifier description>
|
||||||
|
int getBonusesCount(const CSelector &selector) const;
|
||||||
|
int valOfBonuses(const CSelector &selector) const;
|
||||||
|
bool hasBonus(const CSelector &selector) const;
|
||||||
|
BonusList getBonuses(const CSelector &selector, const CSelector &limit) const;
|
||||||
|
BonusList getBonuses(const CSelector &selector) const;
|
||||||
|
|
||||||
|
//legacy interface
|
||||||
|
int valOfBonuses(Bonus::BonusType type, const CSelector &selector) const;
|
||||||
|
int valOfBonuses(Bonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then anyt;
|
||||||
|
bool hasBonusOfType(Bonus::BonusType type, int subtype = -1) const;//determines if hero has a bonus of given type (and optionally subtype)
|
||||||
|
bool hasBonusFrom(ui8 source, ui32 sourceID) const;
|
||||||
|
void getModifiersWDescr( TModDescr &out, Bonus::BonusType type, int subtype = -1 ) const; //out: pairs<modifier value, modifier description>
|
||||||
|
int getBonusesCount(int from, int id) const;
|
||||||
|
|
||||||
|
//various hlp functions for non-trivial values
|
||||||
|
ui32 getMinDamage() const; //used for stacks and creatures only
|
||||||
|
ui32 getMaxDamage() const;
|
||||||
|
int MoraleVal() const; //range [-3, +3]
|
||||||
|
int LuckVal() const; //range [-3, +3]
|
||||||
|
si32 Attack() const; //get attack of stack with all modificators
|
||||||
|
si32 Defense(bool withFrenzy = true) const; //get defense of stack with all modificators
|
||||||
|
ui16 MaxHealth() const; //get max HP of stack with all modifiers
|
||||||
|
|
||||||
|
si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
|
||||||
|
int getPrimSkillLevel(int id) const; //0-attack, 1-defence, 2-spell power, 3-knowledge
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_EXPORT CBonusSystemNode : public IBonusBearer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BonusList bonuses; //wielded bonuses (local or up-propagated here)
|
BonusList bonuses; //wielded bonuses (local or up-propagated here)
|
||||||
@ -384,39 +424,11 @@ public:
|
|||||||
CBonusSystemNode();
|
CBonusSystemNode();
|
||||||
virtual ~CBonusSystemNode();
|
virtual ~CBonusSystemNode();
|
||||||
|
|
||||||
//new bonusing node interface
|
void getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const;
|
||||||
// * selector is predicate that tests if HeroBonus matches our criteria
|
|
||||||
// * root is node on which call was made (NULL will be replaced with this)
|
|
||||||
//interface
|
|
||||||
void getAllBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const;
|
|
||||||
void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL) const; //as above but without duplicates
|
|
||||||
void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const;
|
|
||||||
void getModifiersWDescr(TModDescr &out, const CSelector &selector) const; //out: pairs<modifier value, modifier description>
|
|
||||||
int getBonusesCount(const CSelector &selector) const;
|
|
||||||
int valOfBonuses(const CSelector &selector) const;
|
|
||||||
bool hasBonus(const CSelector &selector) const;
|
|
||||||
BonusList getBonuses(const CSelector &selector, const CSelector &limit) const;
|
|
||||||
BonusList getBonuses(const CSelector &selector) const;
|
|
||||||
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
|
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
|
||||||
|
|
||||||
//legacy interface
|
|
||||||
int valOfBonuses(Bonus::BonusType type, const CSelector &selector) const;
|
|
||||||
int valOfBonuses(Bonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then anyt;
|
|
||||||
bool hasBonusOfType(Bonus::BonusType type, int subtype = -1) const;//determines if hero has a bonus of given type (and optionally subtype)
|
|
||||||
bool hasBonusFrom(ui8 source, ui32 sourceID) const;
|
|
||||||
void getModifiersWDescr( TModDescr &out, Bonus::BonusType type, int subtype = -1 ) const; //out: pairs<modifier value, modifier description>
|
|
||||||
int getBonusesCount(int from, int id) const;
|
|
||||||
ui32 getMinDamage() const; //used for stacks and creatures only
|
|
||||||
ui32 getMaxDamage() const;
|
|
||||||
|
|
||||||
int MoraleVal() const; //range [-3, +3]
|
|
||||||
int LuckVal() const; //range [-3, +3]
|
|
||||||
si32 Attack() const; //get attack of stack with all modificators
|
|
||||||
si32 Defense(bool withFrenzy = true) const; //get defense of stack with all modificators
|
|
||||||
ui16 MaxHealth() const; //get max HP of stack with all modifiers
|
|
||||||
|
|
||||||
|
|
||||||
const Bonus *getBonus(const CSelector &selector) const;
|
const Bonus *getBonus(const CSelector &selector) const;
|
||||||
|
|
||||||
//non-const interface
|
//non-const interface
|
||||||
void getParents(TNodes &out); //retrieves list of parent nodes (nodes to inherit bonuses from)
|
void getParents(TNodes &out); //retrieves list of parent nodes (nodes to inherit bonuses from)
|
||||||
void getRedParents(TNodes &out); //retrieves list of red parent nodes (nodes bonuses propagate from)
|
void getRedParents(TNodes &out); //retrieves list of red parent nodes (nodes bonuses propagate from)
|
||||||
|
@ -2578,7 +2578,7 @@ bool CGameHandler::moveArtifact(si32 srcHeroID, si32 destHeroID, ui16 srcSlot, u
|
|||||||
// if (src.slot >= 19 && dst.slot >= 19 && src.slot < dst.slot)
|
// if (src.slot >= 19 && dst.slot >= 19 && src.slot < dst.slot)
|
||||||
// dst.slot--;
|
// dst.slot--;
|
||||||
|
|
||||||
if (src.slot == dst.slot)
|
if (src.slot == dst.slot && src.hero == dst.hero)
|
||||||
COMPLAIN_RET("Won't move artifact: Dest same as source!");
|
COMPLAIN_RET("Won't move artifact: Dest same as source!");
|
||||||
|
|
||||||
//moving art to backpack is always allowed (we've ruled out exceptions)
|
//moving art to backpack is always allowed (we've ruled out exceptions)
|
||||||
|
Reference in New Issue
Block a user