1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* artifact manipulation in exchange window works (without switching artifacts between different heroes)

* support for 3 new artifacts:
- Ring of Vitality
- Ring of Life
- Vial of Lifeblood
* restructures creature ability preparing (creature abilities are now loaded from cr_abils.txt file). It needs further work - all changes in abilities should be moved from CCreatureHandler.cpp to cr_abils.txt as it's done in this commit (I hope it's clear how it should be done as there is an example)
This commit is contained in:
mateuszb 2009-06-28 13:49:39 +00:00
parent 9093320da8
commit 85eb5c7eb9
9 changed files with 254 additions and 276 deletions

View File

@ -2594,6 +2594,7 @@ void CBattleHex::clickRight(boost::logic::tribool down)
pom->luck = myst.Luck();
pom->morale = myst.Morale();
pom->speedBonus = myst.Speed() - myst.creature->speed;
pom->healthBonus = myst.MaxHealth() - myst.creature->hitPoints;
pom->shotsLeft = myst.shots;
for(int vb=0; vb<myst.effects.size(); ++vb)

View File

@ -1520,6 +1520,20 @@ void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
adventureInt->heroWindow->setHero(adventureInt->heroWindow->curHero);
adventureInt->heroWindow->activate();
}
CExchangeWindow* cew = dynamic_cast<CExchangeWindow*>(listInt.front());
if(cew) //exchange window is open
{
cew->deactivate();
for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
{
if(cew->heroInst[g] == hero)
{
cew->artifs[g]->setHero(hero);
}
}
cew->prepareBackground();
cew->activate();
}
}
void CPlayerInterface::updateWater()

View File

@ -2053,7 +2053,7 @@ CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount, StackState
//health
printAt(CGI->generaltexth->allTexts[388],155,124,GEOR13,zwykly,bitmap);
SDL_itoa(c->hitPoints,pom,10);
SDL_itoa(c->hitPoints + State->healthBonus,pom,10);
printToWR(pom,276,137,GEOR13,zwykly,bitmap);
//remaining health
@ -3766,17 +3766,10 @@ void CExchangeWindow::questlog(int whichHero)
{
}
CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) //c-tor
void CExchangeWindow::prepareBackground()
{
char bufor[400];
heroInst[0] = LOCPLINT->cb->getHeroInfo(hero1, 2);
heroInst[1] = LOCPLINT->cb->getHeroInfo(hero2, 2);
artifs[0] = new CArtifactsOfHero(genRect(600, 800, -334, 150));
artifs[0]->setHero(heroInst[0]);
artifs[1] = new CArtifactsOfHero(genRect(600, 800, 96, 150));
artifs[1]->setHero(heroInst[1]);
if(bg)
SDL_FreeSurface(bg);
SDL_Surface * bgtemp; //loaded as 8bpp surface
bgtemp = BitmapHandler::loadBitmap("TRADE2.BMP");
@ -3797,14 +3790,6 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) //c-tor
{
//graphics
blitAt(skilldef->ourImages[g].bitmap, genRect(32, 32, 385, 19 + 36 * g), bg);
//primary skill's clickable areas
primSkillAreas.push_back(new LRClickableAreaWTextComp());
primSkillAreas[g]->pos = genRect(32, 32, pos.x+385, pos.y + 19 + 36 * g);
primSkillAreas[g]->text = CGI->generaltexth->arraytxt[2+g];
primSkillAreas[g]->type = g;
primSkillAreas[g]->bonus = -1;
primSkillAreas[g]->baseType = 0;
}
CDefHandler * un32 = CDefHandler::giveDef("UN32.DEF");
@ -3825,6 +3810,62 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) //c-tor
blitAt(graphics->abils32->ourImages[heroInst[b]->secSkills[m].first * 3 + heroInst[b]->secSkills[m].second + 2].bitmap, genRect(32, 32, pos.x + 32 + 36 * m + 454 * b, pos.y + 88), bg);
}
//hero's specialty
blitAt(un32->ourImages[heroInst[b]->subID].bitmap, 67 + 490*b, 45, bg);
//experience
blitAt(skilldef->ourImages[4].bitmap, 103 + 490*b, 45, bg);
printAtMiddle( makeNumberShort(heroInst[b]->exp), 119 + 490*b, 71, GEOR13, zwykly, bg );
//mana points
blitAt(skilldef->ourImages[5].bitmap, 139 + 490*b, 45, bg);
printAtMiddle( makeNumberShort(heroInst[b]->mana), 155 + 490*b, 71, GEOR13, zwykly, bg );
//setting morale
blitAt(graphics->morale30->ourImages[heroInst[b]->getCurrentMorale()+3].bitmap, 177 + 490*b, 45, bg);
//setting luck
blitAt(graphics->luck30->ourImages[heroInst[b]->getCurrentLuck()+3].bitmap, 213 + 490*b, 45, bg);
}
//printing portraits
blitAt(graphics->portraitLarge[heroInst[0]->portrait], 257, 13, bg);
blitAt(graphics->portraitLarge[heroInst[1]->portrait], 485, 13, bg);
delete un32;
delete skilldef;
}
CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
{
char bufor[400];
heroInst[0] = LOCPLINT->cb->getHeroInfo(hero1, 2);
heroInst[1] = LOCPLINT->cb->getHeroInfo(hero2, 2);
artifs[0] = new CArtifactsOfHero(genRect(600, 800, -334, 150));
artifs[0]->setHero(heroInst[0]);
artifs[1] = new CArtifactsOfHero(genRect(600, 800, 96, 150));
artifs[1]->setHero(heroInst[1]);
prepareBackground();
//primary skills
for(int g=0; g<4; ++g)
{
//primary skill's clickable areas
primSkillAreas.push_back(new LRClickableAreaWTextComp());
primSkillAreas[g]->pos = genRect(32, 32, pos.x+385, pos.y + 19 + 36 * g);
primSkillAreas[g]->text = CGI->generaltexth->arraytxt[2+g];
primSkillAreas[g]->type = g;
primSkillAreas[g]->bonus = -1;
primSkillAreas[g]->baseType = 0;
}
//heroes related thing
for(int b=0; b<ARRAY_COUNT(heroInst); b++)
{
//secondary skill's clickable areas
for(int g=0; g<heroInst[b]->secSkills.size(); ++g)
{
@ -3841,21 +3882,9 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) //c-tor
secSkillAreas[b][g]->hoverText = std::string(bufor);
}
//hero's specialty
blitAt(un32->ourImages[heroInst[b]->subID].bitmap, 67 + 490*b, 45, bg);
//experience
blitAt(skilldef->ourImages[4].bitmap, 103 + 490*b, 45, bg);
printAtMiddle( makeNumberShort(heroInst[b]->exp), 119 + 490*b, 71, GEOR13, zwykly, bg );
//mana points
blitAt(skilldef->ourImages[5].bitmap, 139 + 490*b, 45, bg);
printAtMiddle( makeNumberShort(heroInst[b]->mana), 155 + 490*b, 71, GEOR13, zwykly, bg );
//setting morale
morale[b] = new LRClickableAreaWTextComp();
morale[b]->pos = genRect(32, 32, pos.x + 177 + 490*b, pos.y + 45);
blitAt(graphics->morale30->ourImages[heroInst[b]->getCurrentMorale()+3].bitmap, 177 + 490*b, 45, bg);
std::vector<std::pair<int,std::string> > mrl = heroInst[b]->getCurrentMoraleModifiers();
int mrlv = heroInst[b]->getCurrentMorale();
@ -3871,7 +3900,6 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) //c-tor
//setting luck
luck[b] = new LRClickableAreaWTextComp();
luck[b]->pos = genRect(32, 32, pos.x + 213 + 490*b, pos.y + 45);
blitAt(graphics->luck30->ourImages[heroInst[b]->getCurrentLuck()+3].bitmap, 213 + 490*b, 45, bg);
mrl = heroInst[b]->getCurrentLuckModifiers();
mrlv = heroInst[b]->getCurrentLuck();
@ -3885,10 +3913,6 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) //c-tor
luck[b]->text += mrl[it].second;
}
//printing portraits
blitAt(graphics->portraitLarge[heroInst[0]->portrait], 257, 13, bg);
blitAt(graphics->portraitLarge[heroInst[1]->portrait], 485, 13, bg);
//buttons
quit = new AdventureMapButton(CGI->generaltexth->tcommands[8], "", boost::bind(&CExchangeWindow::close, this), pos.x+732, pos.y+567, "IOKAY.DEF", SDLK_RETURN);
questlogButton[0] = new AdventureMapButton(CGI->generaltexth->heroscrn[0], std::string(), boost::bind(&CExchangeWindow::questlog,this, 0), pos.x+10, pos.y+44, "hsbtns4.def");
@ -3899,9 +3923,6 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) //c-tor
//garrison interface
garr = new CGarrisonInt(pos.x + 69, pos.y + 131, 4, Point(418,0), bg, Point(0,0), heroInst[0],heroInst[1], true);
delete un32;
delete skilldef;
}
CExchangeWindow::~CExchangeWindow() //d-tor

View File

@ -678,15 +678,15 @@ class CExchangeWindow : public CIntObject, public CWindowWithGarrison
SDL_Surface *bg; //background
AdventureMapButton * quit, * questlogButton[2];
const CGHeroInstance * heroInst[2];
CArtifactsOfHero * artifs[2];
std::vector<LRClickableAreaWTextComp *> secSkillAreas[2], primSkillAreas;
LRClickableAreaWTextComp *morale[2], *luck[2];
public:
const CGHeroInstance * heroInst[2];
CArtifactsOfHero * artifs[2];
void close();
void activate();
void deactivate();
@ -694,6 +694,8 @@ public:
void questlog(int whichHero); //questlog button callback; whichHero: 0 - left, 1 - right
void prepareBackground(); //prepares or redraws bg
CExchangeWindow(si32 hero1, si32 hero2); //c-tor
~CExchangeWindow(); //d-tor
};

13
config/cr_abils.txt Normal file
View File

@ -0,0 +1,13 @@
//creatures' abilities description
//first line: use abilities from ZCRTRAIT.TXT [0 - no, 1 - yes]
//next lines: + [CREATURE_ID] [ABILITY_ID] [value] [subtype] [additional info] [comment to the end of line] /*adding ability*/
// or: - [CREATURE_ID] [ABILITY_ID] /*removing ability*/
// or: 0 /*end of ability descriptions*/
1
+ 115 1 0 0 0 //water elemental should be treated as double-wide
+ 123 1 0 0 0 //ice elemental should be treated as double-wide
+ 140 1 0 0 0 //boar should be treated as double-wide
+ 142 1 0 0 0 //nomads should be treated as double-wide
- 46 2 //hell hound doesn't fly
- 47 2 //cerberus doesn't fly
0

View File

@ -90,10 +90,40 @@ si32 CCreature::maxAmount(const std::vector<si32> &res) const //how many creatur
return ret;
}
int readNumber(int & befi, int & i, int andame, std::string & buf) //helper function for void CCreatureHandler::loadCreatures()
{
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
std::string tmp = buf.substr(befi, i-befi);
int ret = atoi(buf.substr(befi, i-befi).c_str());
++i;
return ret;
}
void CCreatureHandler::loadCreatures()
{
notUsedMonsters += 122,124,126,128,145,146,147,148,149,160,161,162,163,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191;
tlog5 << "\t\tReading ZCRTRAIT.TXT" << std::endl;
tlog5 << "\t\tReading config/cr_abils.txt and ZCRTRAIT.TXT" << std::endl;
bool useCreAbilsFromZCRTRAIT = true;
////////////reading cr_abils.txt ///////////////////
std::ifstream abils("config" PATHSEPARATOR "cr_abils.txt", std::ios::in | std::ios::binary); //this file is not in lod
const int MAX_LINE_SIZE = 1000;
char abilLine[MAX_LINE_SIZE+1];
for(int i=0; i<5; ++i) //removing 5 comment lines
{
abils.getline(abilLine, MAX_LINE_SIZE);
}
//reading first line (determining if we should use creature abilities from ZCRTRAIT.TXT)
abils.getline(abilLine, MAX_LINE_SIZE);
useCreAbilsFromZCRTRAIT = atoi(abilLine);
////////////reading ZCRTRAIT.TXT ///////////////////
std::string buf = bitmaph->getTextFile("ZCRTRAIT.TXT");
int andame = buf.size();
int i=0; //buf iterator
@ -141,194 +171,24 @@ void CCreatureHandler::loadCreatures()
ncre.namePl = buf.substr(befi, i-befi);
++i;
befi=i;
for(i; i<andame; ++i)
for(int v=0; v<7; ++v)
{
if(buf[i]=='\t')
break;
ncre.cost[v] = readNumber(befi, i, andame, buf);
}
ncre.cost[0] = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.cost[1] = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.cost[2] = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.cost[3] = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.cost[4] = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.cost[5] = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.cost[6] = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.fightValue = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.AIValue = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.growth = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.hordeGrowth = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.hitPoints = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.speed = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.attack = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.defence = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.damageMin = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.damageMax = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.shots = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.spells = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.ammMin = atoi(buf.substr(befi, i-befi).c_str());
++i;
befi=i;
for(i; i<andame; ++i)
{
if(buf[i]=='\t')
break;
}
ncre.ammMax = atoi(buf.substr(befi, i-befi).c_str());
++i;
ncre.fightValue = readNumber(befi, i, andame, buf);
ncre.AIValue = readNumber(befi, i, andame, buf);
ncre.growth = readNumber(befi, i, andame, buf);
ncre.hordeGrowth = readNumber(befi, i, andame, buf);
ncre.hitPoints = readNumber(befi, i, andame, buf);
ncre.speed = readNumber(befi, i, andame, buf);
ncre.attack = readNumber(befi, i, andame, buf);
ncre.defence = readNumber(befi, i, andame, buf);
ncre.damageMin = readNumber(befi, i, andame, buf);
ncre.damageMax = readNumber(befi, i, andame, buf);
ncre.shots = readNumber(befi, i, andame, buf);
ncre.spells = readNumber(befi, i, andame, buf);
ncre.ammMin = readNumber(befi, i, andame, buf);
ncre.ammMax = readNumber(befi, i, andame, buf);
befi=i;
for(i; i<andame; ++i)
@ -347,52 +207,55 @@ void CCreatureHandler::loadCreatures()
}
ncre.abilityRefs = buf.substr(befi, i-befi);
i+=2;
if(boost::algorithm::find_first(ncre.abilityRefs, "DOUBLE_WIDE"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::DOUBLE_WIDE, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "FLYING_ARMY"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::FLYING, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "SHOOTING_ARMY"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::SHOOTER, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "SIEGE_WEAPON"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::SIEGE_WEAPON, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_two_attacks"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::ADDITIONAL_ATTACK, 1));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_free_attack"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::BLOCKS_RETAILATION, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "IS_UNDEAD"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::UNDEAD, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_no_melee_penalty"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::NO_MELEE_PENALTY, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_jousting"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::JOUSTING, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_raises_morale"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::RAISING_MORALE, 1));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_lowers_morale"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::ENEMY_MORALE_DECREASING, 1));
if(boost::algorithm::find_first(ncre.abilityRefs, "KING_1"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::KING1, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "KING_2"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::KING2, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "KING_3"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::KING3, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_no_wall_penalty"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::NO_WALL_PENALTY, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "CATAPULT"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::CATAPULT, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "MULTI_HEADED"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::ATTACKS_ALL_ADAJCENT, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "IMMUNE_TO_MIND_SPELLS"))
{
std::vector<int> mindSpells = getMindSpells();
for(int g=0; g<mindSpells.size(); ++g)
if(useCreAbilsFromZCRTRAIT)
{ //adding abilities from ZCRTRAIT.TXT
if(boost::algorithm::find_first(ncre.abilityRefs, "DOUBLE_WIDE"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::DOUBLE_WIDE, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "FLYING_ARMY"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::FLYING, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "SHOOTING_ARMY"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::SHOOTER, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "SIEGE_WEAPON"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::SIEGE_WEAPON, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_two_attacks"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::ADDITIONAL_ATTACK, 1));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_free_attack"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::BLOCKS_RETAILATION, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "IS_UNDEAD"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::UNDEAD, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_no_melee_penalty"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::NO_MELEE_PENALTY, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_jousting"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::JOUSTING, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_raises_morale"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::RAISING_MORALE, 1));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_lowers_morale"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::ENEMY_MORALE_DECREASING, 1));
if(boost::algorithm::find_first(ncre.abilityRefs, "KING_1"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::KING1, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "KING_2"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::KING2, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "KING_3"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::KING3, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "const_no_wall_penalty"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::NO_WALL_PENALTY, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "CATAPULT"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::CATAPULT, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "MULTI_HEADED"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::ATTACKS_ALL_ADAJCENT, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "IMMUNE_TO_MIND_SPELLS"))
{
creatures[40].abilities += makeCreatureAbility(StackFeature::SPELL_IMMUNITY, 0, mindSpells[g]); //giants are immune to mind spells
std::vector<int> mindSpells = getMindSpells();
for(int g=0; g<mindSpells.size(); ++g)
{
creatures[40].abilities += makeCreatureAbility(StackFeature::SPELL_IMMUNITY, 0, mindSpells[g]); //giants are immune to mind spells
}
}
if(boost::algorithm::find_first(ncre.abilityRefs, "IMMUNE_TO_FIRE_SPELLS"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::FIRE_IMMUNITY, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "HAS_EXTENDED_ATTACK"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::TWO_HEX_ATTACK_BREATH, 0));
}
if(boost::algorithm::find_first(ncre.abilityRefs, "IMMUNE_TO_FIRE_SPELLS"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::FIRE_IMMUNITY, 0));
if(boost::algorithm::find_first(ncre.abilityRefs, "HAS_EXTENDED_ATTACK"))
ncre.abilities.push_back(makeCreatureAbility(StackFeature::TWO_HEX_ATTACK_BREATH, 0));
if(ncre.nameSing!=std::string("") && ncre.namePl!=std::string(""))
{
@ -401,6 +264,59 @@ void CCreatureHandler::loadCreatures()
}
}
////second part of reading cr_abils.txt////
bool contReading = true;
while(contReading) //main reading loop
{
abils.getline(abilLine, MAX_LINE_SIZE);
std::istringstream reader(abilLine);
char command;
reader >> command;
switch(command)
{
case '+': //add new ability
{
int creatureID;
StackFeature nsf;
si32 buf;
reader >> creatureID;
reader >> buf; nsf.type = buf; //it reads ui8 as byte, in file it has different format
reader >> buf; nsf.value = buf;
reader >> buf; nsf.subtype = buf;
reader >> buf; nsf.additionalInfo = buf;
nsf.source = StackFeature::CREATURE_ABILITY;
nsf.duration = StackFeature::WHOLE_BATTLE;
nsf.turnsRemain = 0;
creatures[creatureID].abilities += nsf;
break;
}
case '-': //remove ability
{
int creatureID;
ui32 type;
reader >> creatureID;
reader >> type;
StackFeature::ECombatFeatures ecf = static_cast<StackFeature::ECombatFeatures>(type);
creatures[creatureID].abilities -= ecf;
break;
}
case '0': //end reading
{
contReading = false;
break;
}
default: //invalid command
{
tlog1 << "Parse error in file config/cr_abils.txt" << std::endl;
break;
}
}
}
abils.close();
tlog5 << "\t\tReading config/crerefnam.txt" << std::endl;
//loading reference names
std::ifstream ifs("config/crerefnam.txt");
@ -528,13 +444,14 @@ void CCreatureHandler::loadCreatures()
inp2.close();
//TODO: create a tidy configuration file to control fixing unit abilities
creatures[115].abilities.push_back(makeCreatureAbility(StackFeature::DOUBLE_WIDE, 0));//water elemental should be treated as double-wide
/* creatures[115].abilities.push_back(makeCreatureAbility(StackFeature::DOUBLE_WIDE, 0));//water elemental should be treated as double-wide
creatures[123].abilities.push_back(makeCreatureAbility(StackFeature::DOUBLE_WIDE, 0));//ice elemental should be treated as double-wide
creatures[140].abilities.push_back(makeCreatureAbility(StackFeature::DOUBLE_WIDE, 0));//boar should be treated as double-wide
creatures[142].abilities.push_back(makeCreatureAbility(StackFeature::DOUBLE_WIDE, 0));//nomads should be treated as double-wide
creatures[46].abilities -= StackFeature::FLYING; //hell hound
creatures[47].abilities -= StackFeature::FLYING; //cerberus
*/
creatures[52].abilities += makeCreatureAbility(StackFeature::FLYING, 0); //Efreeti
creatures[53].abilities += makeCreatureAbility(StackFeature::FLYING, 0); //Efreet Sultan

View File

@ -597,6 +597,11 @@ si32 CStack::Defense(bool withFrenzy /*= true*/) const
return ret;
}
ui16 CStack::MaxHealth() const
{
return creature->hitPoints + valOfFeatures(StackFeature::HP_BONUS);
}
bool CStack::willMove()
{
return !vstd::contains(state, DEFENDING)

View File

@ -183,6 +183,7 @@ public:
si8 Luck() const; //get luck of stack with all modificators
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
template <typename Handler> void save(Handler &h, const int version)
{
h & creature->idNumber;

View File

@ -437,13 +437,13 @@ askInterfaceForMove:
}
void CGameHandler::prepareAttacked(BattleStackAttacked &bsa, CStack *def)
{
bsa.killedAmount = bsa.damageAmount / def->creature->hitPoints;
unsigned damageFirst = bsa.damageAmount % def->creature->hitPoints;
bsa.killedAmount = bsa.damageAmount / def->MaxHealth();
unsigned damageFirst = bsa.damageAmount % def->MaxHealth();
if( def->firstHPleft <= damageFirst )
{
bsa.killedAmount++;
bsa.newHP = def->firstHPleft + def->creature->hitPoints - damageFirst;
bsa.newHP = def->firstHPleft + def->MaxHealth() - damageFirst;
}
else
{
@ -849,6 +849,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
stacks.back()->luck = hero1->getCurrentLuck(i->first,false);
stacks.back()->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->getPrimSkillLevel(0), StackFeature::BONUS_FROM_HERO));
stacks.back()->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->getPrimSkillLevel(1), StackFeature::BONUS_FROM_HERO));
stacks.back()->features.push_back(makeFeature(StackFeature::HP_BONUS, StackFeature::WHOLE_BATTLE, 0, hero1->valOfBonuses(HeroBonus::STACK_HEALTH), StackFeature::BONUS_FROM_HERO));
stacks.back()->firstHPleft = stacks.back()->MaxHealth();
}
else
{
@ -900,6 +902,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army
stacks.back()->luck = hero2->getCurrentLuck(i->first,false);
stacks.back()->features.push_back(makeFeature(StackFeature::ATTACK_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->getPrimSkillLevel(0), StackFeature::BONUS_FROM_HERO));
stacks.back()->features.push_back(makeFeature(StackFeature::DEFENCE_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->getPrimSkillLevel(1), StackFeature::BONUS_FROM_HERO));
stacks.back()->features.push_back(makeFeature(StackFeature::HP_BONUS, StackFeature::WHOLE_BATTLE, 0, hero2->valOfBonuses(HeroBonus::STACK_HEALTH), StackFeature::BONUS_FROM_HERO));
stacks.back()->firstHPleft = stacks.back()->MaxHealth();
}
else
{