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

- Created config file for true type fonts (disabled by default)

- Implemented buildings with bonuses for defending hero (glyphs of fear, fountain of fortune, some grails)
- Minor fixes
This commit is contained in:
Ivan Savenko 2010-02-04 15:50:59 +00:00
parent ce00ceaf08
commit 3aefb896fe
16 changed files with 357 additions and 118 deletions

View File

@ -5,6 +5,7 @@
#include "CGameInfo.h"
#include "CHeroWindow.h"
#include "CMessage.h"
#include "CKingdomInterface.h"
#include "SDL.h"
#include "SDL_Extensions.h"
#include "CBitmapHandler.h"
@ -258,7 +259,20 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
artifs->setHero(hero);
dismissButton->block(!!hero->visitedTown);
//if we have exchange window with this hero open
bool noDismiss=false;
for(std::list<IShowActivable *>::iterator it=GH.listInt.begin() ; it != GH.listInt.end(); it++)
{
CExchangeWindow * cew = dynamic_cast<CExchangeWindow*>((*it));
if(cew)
for(int g=0; g<ARRAY_COUNT(cew->heroInst); ++g)
if(cew->heroInst[g] == hero)
noDismiss = true;
CKingdomInterface * cki = dynamic_cast<CKingdomInterface*>((*it));
if (cki)
noDismiss = true;
}
dismissButton->block(!!hero->visitedTown || noDismiss);
if(hero->getSecSkillLevel(19)==0)
gar2button->block(true);
else

View File

@ -66,15 +66,15 @@ CKingdomInterface::CKingdomInterface()
slots = CDefHandler::giveDefEss("OVSLOT.DEF");
toHeroes = new AdventureMapButton (CGI->generaltexth->overview[11],"",
boost::bind(&CKingdomInterface::listToHeroes,this),748,28+size*116,"OVBUTN1.DEF");
boost::bind(&CKingdomInterface::listToHeroes,this),748,28+size*116,"OVBUTN1.DEF", SDLK_h);
toHeroes->block(2);
toTowns = new AdventureMapButton (CGI->generaltexth->overview[12],"",
boost::bind(&CKingdomInterface::listToTowns,this),748,64+size*116,"OVBUTN6.DEF");
boost::bind(&CKingdomInterface::listToTowns,this),748,64+size*116,"OVBUTN6.DEF", SDLK_t);
toTowns->block(0);
exit = new AdventureMapButton (CGI->generaltexth->allTexts[600],"",
boost::bind(&CKingdomInterface::close,this),748,99+size*116,"OVBUTN1.DEF");
boost::bind(&CKingdomInterface::close,this),748,99+size*116,"OVBUTN1.DEF", SDLK_RETURN);
exit->bitmapOffset = 3;
statusbar = new CStatusBar(pos.x+7,pos.y+91+size*116,"TSTATBAR.bmp",732);
@ -108,7 +108,7 @@ CKingdomInterface::CKingdomInterface()
for (size_t i=0; i<SKILL_PER_HERO; i++)
{
incomes.push_back(new HoverableArea());//bottom panel with mines
incomes[i]->pos = genRect(54,68,pos.x+20+i*80,pos.y+31+size*116);
incomes[i]->pos = genRect(57,68,pos.x+20+i*80,pos.y+31+size*116);
incomes[i]->hoverText = CGI->generaltexth->mines[i].first;
}
incomes[7]->pos.w = 136;
@ -129,7 +129,7 @@ CKingdomInterface::CKingdomInterface()
INSERT_MAP (87,0) ,87));//Harbor
#undef INSERT_MAP
for(size_t i = 0; i<CGI->state->map->objects.size(); i++)
for(size_t i = 0; i<CGI->state->map->objects.size(); i++)//getting mines and dwelling (in one pass to make it faster)
{
CGObjectInstance* obj = CGI->state->map->objects[i];//current object
if (obj)
@ -197,7 +197,7 @@ void CKingdomInterface::moveObjectList(int newPos)
/*Bottom*/ case 3: objPos = bottom;
break;
}
GH.totalRedraw();
showAll(screen2);
}
CKingdomInterface::~CKingdomInterface()
@ -349,10 +349,6 @@ void CKingdomInterface::deactivate()
slider->deactivate();
}
void CKingdomInterface::keyPressed(const SDL_KeyboardEvent & key)
{
}
void CKingdomInterface::recreateHeroList(int pos)
{
std::vector<const CGHeroInstance*> Heroes = LOCPLINT->cb->getHeroesInfo(true);
@ -371,20 +367,18 @@ void CKingdomInterface::recreateHeroList(int pos)
}
for (i;i<size;i++)//if we still have empty pieces
heroes[i]->setHero(NULL);//empty pic
GH.totalRedraw();
}
void CKingdomInterface::recreateTownList(int pos)
{
std::vector<const CGTownInstance*> Towns = LOCPLINT->cb->getTownsInfo(true);
std::vector<const CGTownInstance*> Towns = LOCPLINT->cb->getTownsInfo(false);
for(size_t i=0;i<size;i++)
{
if (i+pos<Towns.size())
if (i+pos<LOCPLINT->cb->howManyTowns())
towns[i]->setTown(Towns[i+pos]);//replace town
else
towns[i]->setTown(NULL);//only empty pic
}
GH.totalRedraw();
}
void CKingdomInterface::listToTowns()
@ -401,6 +395,7 @@ void CKingdomInterface::listToTowns()
heroes[i]->deactivate();
towns[i]->activate();
}
showAll(screen2);
}
void CKingdomInterface::listToHeroes()
@ -417,6 +412,7 @@ void CKingdomInterface::listToHeroes()
towns[i]->deactivate();
heroes[i]->activate();
}
showAll(screen2);
}
void CKingdomInterface::sliderMoved(int newpos)
@ -435,6 +431,7 @@ void CKingdomInterface::sliderMoved(int newpos)
recreateTownList(newpos);
for (size_t i=0; i<size; i++)
towns[i]->activate();
showAll(screen2);
}
else//heroes
{
@ -444,6 +441,7 @@ void CKingdomInterface::sliderMoved(int newpos)
recreateHeroList(newpos);
for (size_t i=0; i<size; i++)
heroes[i]->activate();
showAll(screen2);
}
}
@ -459,10 +457,10 @@ CKingdomInterface::CTownItem::CTownItem(int num, CKingdomInterface * Owner)
town = NULL;
garr = NULL;
garrHero = new HoverableArea();
garrHero = new LRClickableAreaOpenHero();
garrHero->pos = genRect(64, 58, pos.x+244, pos.y + 6);
visitHero = new HoverableArea();
visitHero = new LRClickableAreaOpenHero();
visitHero->pos = genRect(64, 58, pos.x+476, pos.y + 6);
for (int i=0; i<CREATURES_PER_TOWN;i++)
@ -480,7 +478,7 @@ CKingdomInterface::CTownItem::CTownItem(int num, CKingdomInterface * Owner)
fortArea = new HoverableArea();
fortArea->pos = genRect(38, 38, pos.x+111, pos.y + 31);
townImage = new HoverableArea();
townImage = new LRClickableAreaOpenTown();
townImage->pos = genRect(64, 58, pos.x+5, pos.y + 6);
incomeArea = new HoverableArea();
@ -506,24 +504,28 @@ void CKingdomInterface::CTownItem::setTown(const CGTownInstance * newTown)
return;
garr = NULL;
}
garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),slots->ourImages[owner->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,false,true, 4,Point(-126,37));
garr->update = false;
garr = new CGarrisonInt(pos.x+313,pos.y+3,4,Point(232,0),slots->ourImages[owner->PicCount+2].bitmap,Point(313,2),town,town->visitingHero,true,true, 4,Point(-126,37));
garr->update = true;
/*for (int i=4; i<7; i++)
{
garr->sup[0][i][0].pos.x -= 126;
garr->sup[0][i][0].pos.y += 37;
garr->sdown[0][i][0].pos.x -= 126;
garr->sdown[0][i][0].pos.y += 37;
}*/
char buf[400];
if (town->garrisonHero)
{
garrHero->hero = town->garrisonHero;
sprintf(buf, CGI->generaltexth->allTexts[15].c_str(), town->garrisonHero->name.c_str(), town->garrisonHero->type->heroClass->name.c_str());
garrHero->hoverText = buf;
}
if (town->visitingHero)
{
visitHero->hero = town->visitingHero;
sprintf(buf, CGI->generaltexth->allTexts[15].c_str(), town->visitingHero->name.c_str(), town->visitingHero->type->heroClass->name.c_str());
visitHero->hoverText = buf;
}
for (int i=0; i<CREATURES_PER_TOWN;i++)
{
creaCount[i]->town = NULL;
int crid = -1;
if (!vstd::contains(town->builtBuildings,30+i))
continue;
if (vstd::contains(town->builtBuildings,30+i+CREATURES_PER_TOWN))
crid = town->town->upgradedCreatures[i];
@ -541,6 +543,7 @@ void CKingdomInterface::CTownItem::setTown(const CGTownInstance * newTown)
}
townImage->hoverText = town->name;
townImage->town = town;
hallArea->hoverText = CGI->buildh->buildings[town->subID][10+town->hallLevel()]->Name();
if (town->hasFort())
@ -553,7 +556,8 @@ void CKingdomInterface::CTownItem::activate()
{
if (!town)
return;
garr->activate();
setTown(town);
hallArea->activate();
fortArea->activate();
incomeArea->activate();
@ -570,13 +574,14 @@ void CKingdomInterface::CTownItem::activate()
creaGrowth[i]->activate();
creaCount [i]->activate();
}
garr->activate();
}
void CKingdomInterface::CTownItem::deactivate()
{
if (!town)
return;
garr->deactivate();
hallArea->deactivate();
fortArea->deactivate();
incomeArea->deactivate();
@ -592,7 +597,7 @@ void CKingdomInterface::CTownItem::deactivate()
{
creaGrowth[i]->deactivate();
creaCount [i]->deactivate();
}
} garr->deactivate();
}
void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
@ -602,7 +607,7 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
blitAt(slots->ourImages[numb % owner->PicCount].bitmap,pos.x,pos.y,to);
return;
}//background
blitAt(slots->ourImages[owner->PicCount+2].bitmap,pos.x,pos.y,to);
blitAt(slots->ourImages[owner->PicCount+2].bitmap,pos.x,pos.y,to); garr->show(to);
//town pic/name
int townPic = town->subID*2;
if (!town->hasFort())
@ -622,9 +627,21 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
std::ostringstream oss;
oss << town->dailyIncome();
CSDL_Ext::printAtMiddle(oss.str(),pos.x+189,pos.y+61,FONT_SMALL,zwykly,to);
// Creature bonuses/ Creature available texts - need to find text wrapper thingy (have "\n" inside text)
// CSDL_Ext::printAtWR(CGI->generaltexth->allTexts[265],pos.x,pos.y+80,GEOR13,zwykly,to);
// CSDL_Ext::printTo(CGI->generaltexth->allTexts[266],pos.x+350,pos.y+80,GEOR13,zwykly,to);
std::vector<std::string> * toPrin = CMessage::breakText(CGI->generaltexth->allTexts[265]);
CSDL_Ext::printAt((*toPrin)[0], pos.x+4, pos.y+76, FONT_SMALL, tytulowy, to);
if(toPrin->size()!=1)
CSDL_Ext::printAt((*toPrin)[1], pos.x+4, pos.y+92, FONT_SMALL, tytulowy, to);
delete toPrin;
toPrin = CMessage::breakText(CGI->generaltexth->allTexts[266]);
CSDL_Ext::printAt((*toPrin)[0], pos.x+351, pos.y+76, FONT_SMALL, tytulowy, to);
if(toPrin->size()!=1)
CSDL_Ext::printAt((*toPrin)[1], pos.x+351, pos.y+92, FONT_SMALL, tytulowy, to);
delete toPrin;
for (int i=0; i<CREATURES_PER_TOWN;i++)
{//creatures info
int crid = -1;
@ -651,7 +668,7 @@ void CKingdomInterface::CTownItem::showAll(SDL_Surface * to)
CSDL_Ext::printTo(ostrs.str(),pos.x+440+i*37,pos.y+110,FONT_TINY,zwykly,to);
}
garr->show(to);
if (town->garrisonHero)
blitAt(graphics->portraitLarge[town->garrisonHero->portrait],pos.x+244,pos.y+6,to);
@ -691,7 +708,7 @@ CKingdomInterface::CHeroItem::CHeroItem(int num, CKingdomInterface * Owner)
artRight = new AdventureMapButton("", "", boost::bind
(&CKingdomInterface::CHeroItem::scrollArts,this,+1), 675, 66, "hsbtns5.def", SDLK_RIGHT);
portrait = new LRClickableAreaWText();
portrait = new LRClickableAreaOpenHero();
portrait->pos = genRect(64, 58, pos.x+5, pos.y + 5);
char bufor[400];
for(int i=0; i<PRIMARY_SKILLS; i++)
@ -769,8 +786,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
artLeft->block(hero->artifacts.size() <= 8);
artRight->block(hero->artifacts.size() <= 8);
garr = new CGarrisonInt(pos.x+6, pos.y+78, 4, Point(), slots->ourImages[owner->PicCount].bitmap,
Point(6,78), hero, NULL, false, true);
garr->update = false;
Point(6,78), hero, NULL, true, true);
for (int i=0; i<artifacts.size(); i++)
{
@ -798,7 +814,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
sprintf(bufor, CGI->generaltexth->allTexts[15].c_str(), hero->name.c_str(), hero->type->heroClass->name.c_str());
portrait->hoverText = std::string(bufor);
portrait->text = hero->getBiography();
portrait->hero = hero;
speciality->text = CGI->generaltexth->hTxts[hero->subID].longBonus;
@ -872,6 +888,7 @@ void CKingdomInterface::CHeroItem::scrollArts(int move)
backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type].Name());
}
}
showAll(screen2);
}
void CKingdomInterface::CHeroItem::showAll(SDL_Surface * to)
@ -951,11 +968,12 @@ void CKingdomInterface::CHeroItem::onArtChange(int newstate)
deactivate();
artGroup = newstate;
activate();
GH.totalRedraw();
showAll(screen2);
}
void CKingdomInterface::CHeroItem::activate()
{
setHero(hero);
if (!hero)
return;
artButtons->activate();
@ -1077,7 +1095,15 @@ void CKingdomInterface::CTownItem::CCreaPlace::clickLeft(tribool down, bool prev
void CKingdomInterface::CTownItem::CCreaPlace::clickRight(tribool down, bool previousState)
{
//TODO
if (down && town)
{
int crid;
if (town->builtBuildings.find(30+type+CREATURES_PER_TOWN)!=town->builtBuildings.end())
crid = town->town->upgradedCreatures[type];
else
crid = town->town->basicCreatures[type];
GH.pushInt(new CCreInfoWindow(crid, 0, town->creatures[type].first, NULL, 0, 0, NULL));
}
}
void CKingdomInterface::CTownItem::CCreaPlace::deactivate()

View File

@ -47,8 +47,8 @@ class CKingdomInterface : public CIntObject
CKingdomInterface * owner;
int numb;//position on screen (1..size)
HoverableArea *hallArea, *fortArea, *incomeArea;//hoverable text for town hall, fort, income
HoverableArea * garrHero, *visitHero;//portraits of heroes
HoverableArea * townImage;//town image
LRClickableAreaOpenHero * garrHero, *visitHero;//portraits of heroes
LRClickableAreaOpenTown * townImage;//town image
std::vector < HoverableArea * > creaGrowth;
std::vector < CCreaPlace * > creaCount;
void setTown(const CGTownInstance * newTown);//change town and update info
@ -70,13 +70,14 @@ class CKingdomInterface : public CIntObject
void activate();
void deactivate();
};
public:
public:
const CGHeroInstance * hero;
CKingdomInterface * owner;
int artGroup,numb;//current art group (0 = equiped, 1 = misc, 2 = backpack)
int backpackPos;//first visible artifact in backpack
AdventureMapButton * artLeft, * artRight;//buttons for backpack
LRClickableAreaWText * portrait;
LRClickableAreaOpenHero * portrait;
LRClickableAreaWText * experience;
LRClickableAreaWTextComp * morale, * luck;
LRClickableAreaWText * spellPoints;
@ -134,7 +135,6 @@ public:
void moveObjectList(int newPos);
void recreateHeroList(int pos);//recreating heroes list (on slider move)
void recreateTownList(int pos);//same for town list
void keyPressed(const SDL_KeyboardEvent & key);
void listToTowns();//changing list to town view
void listToHeroes();//changing list to heroes view
void sliderMoved(int newpos);//when we move a slider...

View File

@ -9,7 +9,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/thread.hpp>
#include <SDL_ttf.h>
#include <SDL_mixer.h>
#include "SDL_Extensions.h"
#include "SDL_framerate.h"
@ -76,7 +75,6 @@ VCMIDirs GVCMIDirs;
std::queue<SDL_Event*> events;
boost::mutex eventsM;
TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
static bool gOnlyAI = false;
void processCommand(const std::string &message);
@ -95,21 +93,6 @@ void init()
#endif
CSDL_Ext::std32bppSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, rmask, gmask, bmask, amask);
tlog0 << "\tInitializing minors: " << pomtime.getDif() << std::endl;
TTF_Init();
atexit(TTF_Quit);
TNRB16 = TTF_OpenFont(DATA_DIR "/Fonts/tnrb.ttf",16);
GEOR13 = TTF_OpenFont(DATA_DIR "/Fonts/georgia.ttf",13);
GEOR16 = TTF_OpenFont(DATA_DIR "/Fonts/georgia.ttf",16);
GEORXX = TTF_OpenFont(DATA_DIR "/Fonts/tnrb.ttf",22);
GEORM = TTF_OpenFont(DATA_DIR "/Fonts/georgia.ttf",10);
if(! (TNRB16 && GEOR16 && GEORXX && GEORM))
{
tlog1 << "One of the fonts couldn't be loaded!\n";
exit(-1);
}
THC tlog0<<"\tInitializing fonts: "<<pomtime.getDif()<<std::endl;
{
//read system options
CLoadFile settings(GVCMIDirs.UserPath + "/config/sysopts.bin");
@ -138,7 +121,7 @@ void init()
//CGI->musich->init();
//CGI->musich->setVolume(GDefaultOptions.musicVolume);
tlog0<<"\tInitializing sound: "<<pomtime.getDif()<<std::endl;
tlog0<<"Initializing screen, fonts and sound handling: "<<tmh.getDif()<<std::endl;
tlog0<<"Initializing screen and sound handling: "<<tmh.getDif()<<std::endl;
initDLL(::console,logfile);
CGI->setFromLib();

View File

@ -7,9 +7,6 @@
#include "../hch/CLodHandler.h"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/replace.hpp>
#include "../hch/CDefHandler.h"
#include "CGameInfo.h"
#include "SDL_Extensions.h"
#include <sstream>
#include "../hch/CGeneralTextHandler.h"
#include "Graphics.h"
@ -33,7 +30,6 @@ SDL_Color tytulowy = {229, 215, 123, 0},
darkTitle = {215, 175, 78, 0};
extern SDL_Surface * screen;
extern TTF_Font * TNRB16, *TNR, *GEOR13;
using namespace NMessage;
@ -264,12 +260,29 @@ SDL_Surface * CMessage::blitTextOnSur(std::vector<std::vector<SDL_Surface*> > *
return ret;
}
std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::string> * brtext, int &fontHeigh, TTF_Font *font)
SDL_Surface * FNT_RenderText (EFonts font, std::string text, SDL_Color kolor= zwykly)
{
if (graphics->fontsTrueType[font])
return TTF_RenderText_Blended(graphics->fontsTrueType[font], text.c_str(), kolor);
const Font *f = graphics->fonts[font];
int w = f->getWidth(text.c_str()),
h = f->height;
SDL_Surface * ret = CSDL_Ext::newSurface(w, h, screen);
SDL_FillRect (ret, NULL, SDL_MapRGB(ret->format,128,128,128));//if use default black - no shadowing
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,128,128,128));
CSDL_Ext::printAt(text.c_str(), 0, 0, font, kolor, ret);
return ret;
}
std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::string> * brtext, int &fontHeigh, EFonts font)
{
if(!font) font = TNRB16;
std::vector<std::vector<SDL_Surface*> > * txtg = new std::vector<std::vector<SDL_Surface*> >();
txtg->resize(brtext->size());
fontHeigh = TTF_FontHeight(font);
if (graphics->fontsTrueType[font])
fontHeigh = TTF_FontHeight(graphics->fontsTrueType[font]);
else
fontHeigh = graphics->fonts[font]->height;
for (size_t i=0; i<brtext->size();i++) //foreach line
{
@ -283,7 +296,7 @@ std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::st
z++;
if (z)
(*txtg)[i].push_back(TTF_RenderText_Blended(font, (*brtext)[i].substr(0,z).c_str(), zwykly));
(*txtg)[i].push_back(FNT_RenderText(font, (*brtext)[i].substr(0,z), zwykly));
(*brtext)[i].erase(0,z);
if ((*brtext)[i][0] == '{')
@ -300,7 +313,7 @@ std::vector<std::vector<SDL_Surface*> > * CMessage::drawText(std::vector<std::st
z++;
if (z)
(*txtg)[i].push_back(TTF_RenderText_Blended(font, (*brtext)[i].substr(0,z).c_str(), tytulowy));
(*txtg)[i].push_back(FNT_RenderText(font, (*brtext)[i].substr(0,z), tytulowy));
(*brtext)[i].erase(0,z);
if ((*brtext)[i][0] == '}')
@ -387,7 +400,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int
}
if(dynamic_cast<CSelWindow*>(ret)) //it's selection window, so we'll blit "or" between components
_or = TTF_RenderText_Blended(GEOR13,CGI->generaltexth->allTexts[4].c_str(),zwykly);
_or = FNT_RenderText(FONT_MEDIUM,CGI->generaltexth->allTexts[4],zwykly);
std::vector<std::string> * brtext = breakText(text, charperline, true, true); //text
std::vector<std::vector<SDL_Surface*> > * txtg = drawText(brtext, fontHeight);
@ -493,7 +506,7 @@ SDL_Surface * CMessage::genMessage
if (title.length())
{
SDL_Surface * titleText = TTF_RenderText_Blended(TNRB16,title.c_str(),tytulowy);
SDL_Surface * titleText = FNT_RenderText(FONT_BIG,title,tytulowy);
//draw title
SDL_Rect tytul = genRect(titleText->h,titleText->w,((ret->w/2)-(titleText->w/2)),37);
@ -505,7 +518,7 @@ SDL_Surface * CMessage::genMessage
{
int by = 37+i*21;
if (title.length()) by+=40;
SDL_Surface * tresc = TTF_RenderText_Blended(TNRB16,(*tekst)[i].c_str(),zwykly);
SDL_Surface * tresc = FNT_RenderText(FONT_BIG,(*tekst)[i],zwykly);
SDL_Rect trescRect = genRect(tresc->h,tresc->w,((ret->w/2)-(tresc->w/2)),by);
SDL_BlitSurface(tresc,NULL,ret,&trescRect);
SDL_FreeSurface(tresc);
@ -570,7 +583,7 @@ ComponentResolved::ComponentResolved( SComponent *Comp )
comp = Comp;
img = comp->getImg();
std::vector<std::string> * brtext = CMessage::breakText(comp->subtitle,13,true,true); //text
txt = CMessage::drawText(brtext,txtFontHeight,GEOR13);
txt = CMessage::drawText(brtext,txtFontHeight,FONT_MEDIUM);
delete brtext;
//calculate dimensions

View File

@ -1,8 +1,8 @@
#ifndef __CMESSAGE_H__
#define __CMESSAGE_H__
#include "FontBase.h"
#include "../global.h"
#include <SDL_ttf.h>
#include <SDL.h>
/*
@ -59,7 +59,7 @@ class CMessage
public:
static std::pair<int,int> getMaxSizes(std::vector<std::vector<SDL_Surface*> > * txtg, int fontHeight);
static std::vector<std::vector<SDL_Surface*> > * drawText(std::vector<std::string> * brtext, int &fontHeigh, TTF_Font *font = NULL);
static std::vector<std::vector<SDL_Surface*> > * drawText(std::vector<std::string> * brtext, int &fontHeigh, EFonts font = FONT_MEDIUM);
static SDL_Surface * blitTextOnSur(std::vector<std::vector<SDL_Surface*> > * txtg, int fontHeight, int & curh, SDL_Surface * ret, int xCenterPos=-1); //xPos==-1 works as if ret->w/2
static void drawIWindow(CInfoWindow * ret, std::string text, int player, int charperline);
static CSimpleWindow * genWindow(std::string text, int player, bool centerOnMouse=false, int Lmar=35, int Rmar=35, int Tmar=35, int Bmar=35);//supports h3 text formatting; player sets color of window, Lmar/Rmar/Tmar/Bmar are Left/Right/Top/Bottom margins

View File

@ -3868,6 +3868,30 @@ void LRClickableAreaWTextComp::deactivate()
deactivateHover();
}
void LRClickableAreaOpenHero::clickLeft(tribool down, bool previousState)
{
if((!down) && previousState && hero)
LOCPLINT->openHeroWindow(hero);
}
void LRClickableAreaOpenHero::clickRight(tribool down, bool previousState)
{
if((!down) && previousState && hero)
LOCPLINT->openHeroWindow(hero);
}
void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState)
{
if((!down) && previousState && town)
LOCPLINT->openTownWindow(town);
}
void LRClickableAreaOpenTown::clickRight(tribool down, bool previousState)
{
if((!down) && previousState && town)
LOCPLINT->openTownWindow(town);
}
void CArtifactsOfHero::activate()
{
for(size_t f=0; f<artWorn.size(); ++f)
@ -4190,7 +4214,9 @@ void CExchangeWindow::activate()
quit->activate();
garr->activate();
artifs[0]->setHero(heroInst[0]);
artifs[0]->activate();
artifs[1]->setHero(heroInst[1]);
artifs[1]->activate();
for(int g=0; g<ARRAY_COUNT(secSkillAreas); g++)
@ -4424,9 +4450,9 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
secSkillAreas[b][g]->hoverText = std::string(bufor);
}
portrait[b] = new LRClickableAreaWText();
portrait[b] = new LRClickableAreaOpenHero();
portrait[b]->pos = genRect(64, 58, pos.x + 257 + 228*b, pos.y + 13);
portrait[b]->text = heroInst[b]->getBiography();
portrait[b]->hero = heroInst[b];
sprintf(bufor, CGI->generaltexth->allTexts[15].c_str(), heroInst[b]->name.c_str(), heroInst[b]->type->heroClass->name.c_str());
portrait[b]->hoverText = std::string(bufor);
@ -4461,8 +4487,11 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
morale[b]->bonus = mrlv;
morale[b]->text = CGI->generaltexth->arraytxt[88];
boost::algorithm::replace_first(morale[b]->text,"%s",CGI->generaltexth->arraytxt[86-mrlt]);
for(int it=0; it < mrl.size(); it++)
morale[b]->text += mrl[it].second;
if (!mrl.size())
morale[b]->text += CGI->generaltexth->arraytxt[108];
else
for(int it=0; it < mrl.size(); it++)
morale[b]->text += mrl[it].second;
//setting luck
luck[b] = new LRClickableAreaWTextComp();
@ -4476,8 +4505,11 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
luck[b]->bonus = mrlv;
luck[b]->text = CGI->generaltexth->arraytxt[62];
boost::algorithm::replace_first(luck[b]->text,"%s",CGI->generaltexth->arraytxt[60-mrlt]);
for(int it=0; it < mrl.size(); it++)
luck[b]->text += mrl[it].second;
if (!mrl.size())
luck[b]->text += CGI->generaltexth->arraytxt[77];
else
for(int it=0; it < mrl.size(); it++)
luck[b]->text += mrl[it].second;
}
//buttons

View File

@ -644,6 +644,23 @@ public:
virtual void clickRight(tribool down, bool previousState);
};
class LRClickableAreaOpenHero: public LRClickableAreaWTextComp
{
public:
const CGHeroInstance * hero;
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
};
class LRClickableAreaOpenTown: public LRClickableAreaWTextComp
{
public:
const CGTownInstance * town;
void clickLeft(tribool down, bool previousState);
void clickRight(tribool down, bool previousState);
};
class CArtPlace: public LRClickableAreaWTextComp
{
private:
@ -740,7 +757,7 @@ class CExchangeWindow : public CWindowWithGarrison
LRClickableAreaWText *speciality[2];
LRClickableAreaWText *experience[2];
LRClickableAreaWText *spellPoints[2];
LRClickableAreaWText *portrait[2];
LRClickableAreaOpenHero *portrait[2];
public:

View File

@ -2,6 +2,7 @@
#include "Graphics.h"
#include "../hch/CDefHandler.h"
#include "SDL_Extensions.h"
#include <SDL_ttf.h>
#include <boost/assign/std/vector.hpp>
#include <sstream>
#include <iomanip>
@ -271,6 +272,7 @@ Graphics::Graphics()
std::vector<Task> tasks; //preparing list of graphics to load
tasks += boost::bind(&Graphics::loadFonts,this);
tasks += boost::bind(&Graphics::loadTrueType,this);
tasks += boost::bind(&Graphics::loadPaletteAndColors,this);
tasks += boost::bind(&Graphics::loadHeroFlags,this);
tasks += boost::bind(&Graphics::loadHeroPortraits,this);
@ -612,6 +614,39 @@ void Graphics::blueToPlayersAdv(SDL_Surface * sur, int player)
}
}
void Graphics::loadTrueType()
{
bool ttfPresent;//was TTF initialised or not
for(int i = 0; i < FONTS_NUMBER; i++)
fontsTrueType[i] = NULL;
std::ifstream ff(DATA_DIR "/config/fonts.txt");
while(!ff.eof())
{
int enabl, fntID, fntSize;
std::string fntName;
ff >> enabl;//enabled font or not
if (enabl==-1)
break;//end of data
ff >> fntID;//what font will be replaced
ff >> fntName;//name of truetype font
ff >> fntSize;//size of font
if (enabl)
{
if (!ttfPresent)
{
ttfPresent = true;
TTF_Init();
atexit(TTF_Quit);
};
fntName = DATA_DIR + ( "/Fonts/" + fntName);
fontsTrueType[fntID] = TTF_OpenFont(fntName.c_str(),fntSize);
}
}
ff.close();
ff.clear();
}
Font * Graphics::loadFont( const char * name )
{
int len = 0;

View File

@ -1,7 +1,7 @@
#ifndef __GRAPHICS_H__
#define __GRAPHICS_H__
#include <SDL_ttf.h>
#include "../global.h"
#include "FontBase.h"
@ -50,6 +50,7 @@ public:
//Fonts
static const int FONTS_NUMBER = 9;
Font *fonts[FONTS_NUMBER];
TTF_Font * fontsTrueType[FONTS_NUMBER];//true type fonts, if some of the fonts not loaded - NULL
//various graphics
SDL_Color * playerColors; //array [8]
@ -108,6 +109,7 @@ public:
SDL_Surface * drawTownInfoWin(const CGTownInstance * curh);
SDL_Surface * getPic(int ID, bool fort=true, bool builded=false); //returns small picture of town: ID=-1 - blank; -2 - border; -3 - random
void blueToPlayersAdv(SDL_Surface * sur, int player); //replaces blue interface colour with a color of player
void loadTrueType();
void loadFonts();
Font *loadFont(const char * name);
};

View File

@ -78,7 +78,7 @@ void updateRect (SDL_Rect * rect, SDL_Surface * scr)
SDL_UpdateRect(scr,rect->x,rect->y,rect->w,rect->h);
}
/*void CSDL_Ext::printAtMiddleWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
void printAtMiddleWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
{
std::vector<std::string> * ws = CMessage::breakText(text,charpr);
std::vector<SDL_Surface*> wesu;
@ -107,9 +107,9 @@ void updateRect (SDL_Rect * rect, SDL_Surface * scr)
for (size_t i=0; i < wesu.size(); ++i)
SDL_FreeSurface(wesu[i]);
delete ws;
}*/
}
/*void CSDL_Ext::printAtWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
void printAtWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor, SDL_Surface * dst)
{
std::vector<std::string> * ws = CMessage::breakText(text,charpr);
std::vector<SDL_Surface*> wesu;
@ -128,9 +128,14 @@ void updateRect (SDL_Rect * rect, SDL_Surface * scr)
SDL_FreeSurface(wesu[i]);
delete ws;
}
*/
void CSDL_Ext::printAtWB(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst, bool refresh)
{
if (graphics->fontsTrueType[font])
{
printAtWB(text,x, y, graphics->fontsTrueType[font], charpr, kolor, dst);
return;
}
const Font *f = graphics->fonts[font];
std::vector<std::string> * ws = CMessage::breakText(text,charpr);
@ -146,6 +151,12 @@ void CSDL_Ext::printAtWB(const std::string & text, int x, int y, EFonts font, in
void CSDL_Ext::printAtMiddleWB( const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor/*=tytulowy*/, SDL_Surface * dst/*=screen*/, bool refrsh /*= false*/ )
{
if (graphics->fontsTrueType[font])
{
printAtMiddleWB(text,x, y, graphics->fontsTrueType[font], charpr, kolor, dst);
return;
}
const Font *f = graphics->fonts[font];
std::vector<std::string> * ws = CMessage::breakText(text,charpr);
int totalHeight = ws->size() * f->height;
@ -159,7 +170,7 @@ void CSDL_Ext::printAtMiddleWB( const std::string & text, int x, int y, EFonts f
delete ws;
}
/*void CSDL_Ext::printAtMiddle(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality, bool refresh)
void printAtMiddle(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2, bool refresh=false)
{
if(text.length()==0) return;
SDL_Surface * temp;
@ -187,10 +198,15 @@ void CSDL_Ext::printAtMiddleWB( const std::string & text, int x, int y, EFonts f
if(refresh)
SDL_UpdateRect(dst,x-(temp->w/2),y-(temp->h/2),temp->w,temp->h);
SDL_FreeSurface(temp);
}*/
}
void CSDL_Ext::printAtMiddle( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
{
if (graphics->fontsTrueType[font])
{
printAtMiddle(text,x, y, graphics->fontsTrueType[font], kolor, dst);
return;
}
const Font *f = graphics->fonts[font];
int nx = x - f->getWidth(text.c_str())/2,
ny = y - f->height/2;
@ -198,7 +214,7 @@ void CSDL_Ext::printAtMiddle( const std::string & text, int x, int y, EFonts fon
printAt(text, nx, ny, font, kolor, dst, refresh);
}
/*void CSDL_Ext::printAt(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality, bool refresh)
void printAt(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2, bool refresh=false)
{
if (text.length()==0)
return;
@ -227,12 +243,17 @@ void CSDL_Ext::printAtMiddle( const std::string & text, int x, int y, EFonts fon
if(refresh)
SDL_UpdateRect(dst,x,y,temp->w,temp->h);
SDL_FreeSurface(temp);
}*/
}
void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
{
if(!text.size())
return;
if (graphics->fontsTrueType[font])
{
printAt(text,x, y, graphics->fontsTrueType[font], kolor, dst);
return;
}
assert(dst);
assert(font < Graphics::FONTS_NUMBER);
@ -250,13 +271,15 @@ void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL
for(int txti = first; txti < beyondEnd; txti++)
{
const unsigned char c = text[txti];
src = f->chars[c].pixels;
x += f->chars[c].unknown1;
for(int i = 0; i < f->height && (y + i) < (dst->h - 1); i++)
{
px = (Uint8*)dst->pixels;
px += (y+i) * dst->pitch + x * bpp;
src = f->chars[c].pixels;
src += i * f->chars[c].width;//if we have reached end of surface in previous line
for(int j = 0; j < f->chars[c].width && (j + x) < (dst->w - 1); j++)
{
switch(*src)
@ -285,12 +308,7 @@ void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL
}
}
/*void CSDL_Ext::printAtWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality)
{
printAt(text,x,y,font,kolor,dst,quality, true);
}*/
/*void CSDL_Ext::printTo(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality)
void printTo(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2)
{
if (text.length()==0)
return;
@ -318,15 +336,20 @@ void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL
SDL_BlitSurface(temp,NULL,dst,&genRect(temp->h,temp->w,x-temp->w,y-temp->h));
SDL_UpdateRect(dst,x-temp->w,y-temp->h,temp->w,temp->h);
SDL_FreeSurface(temp);
}*/
}
void CSDL_Ext::printTo( const std::string & text, int x, int y, EFonts font, SDL_Color kolor/*=zwykly*/, SDL_Surface * dst/*=screen*/, bool refresh /*= false*/ )
{
if (graphics->fontsTrueType[font])
{
printTo(text,x, y, graphics->fontsTrueType[font], kolor, dst);
return;
}
const Font *f = graphics->fonts[font];
printAt(text, x - f->getWidth(text.c_str()), y - f->height, font, kolor, dst, refresh);
}
/*void CSDL_Ext::printToWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality)
void printToWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor, SDL_Surface * dst, unsigned char quality=2)
{
if (text.length()==0)
return;
@ -353,7 +376,7 @@ void CSDL_Ext::printTo( const std::string & text, int x, int y, EFonts font, SDL
}
SDL_BlitSurface(temp,NULL,dst,&genRect(temp->h,temp->w,x-temp->w,y-temp->h));
SDL_FreeSurface(temp);
}*/
}
void CSDL_Ext::SDL_PutPixel(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A)
{

View File

@ -20,7 +20,6 @@
extern SDL_Surface * screen, *screen2, *screenBuf;
extern SDL_Color tytulowy, tlo, zwykly ;
extern TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM;
void blitAtWR(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
void blitAtWR(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst=screen);
@ -117,14 +116,6 @@ namespace CSDL_Ext
int blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); //blits 8 bpp surface with alpha channel to 24 bpp surface
Uint32 colorToUint32(const SDL_Color * color); //little endian only
/* void printTo(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2);// quality: 0 - lowest, 1 - medium, 2 - highest; prints at right bottom corner of specific area. position of corner indicated by (x, y)
void printToWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2);// quality: 0 - lowest, 1 - medium, 2 - highest; prints at right bottom corner of specific area. position of corner indicated by (x, y)
void printAtMiddle(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2, bool refresh = false); // quality: 0 - lowest, 1 - medium, 2 - highest
void printAtMiddleWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen);
void printAtWB(const std::string & text, int x, int y, TTF_Font * font, int charpr, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen);
void printAt(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2, bool refresh = false); // quality: 0 - lowest, 1 - medium, 2 - highest
void printAtWR(const std::string & text, int x, int y, TTF_Font * font, SDL_Color kolor=tytulowy, SDL_Surface * dst=screen, unsigned char quality = 2); // quality: 0 - lowest, 1 - medium, 2 - highest
*/
void printAtWB(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor=zwykly, SDL_Surface * dst=screen, bool refresh = false);
void printAt(const std::string & text, int x, int y, EFonts font, SDL_Color kolor=zwykly, SDL_Surface * dst=screen, bool refresh = false);
void printTo(const std::string & text, int x, int y, EFonts font, SDL_Color kolor=zwykly, SDL_Surface * dst=screen, bool refresh = false);

29
config/fonts.txt Normal file
View File

@ -0,0 +1,29 @@
0 0 tnrb.ttf 20
0 1 georgia.ttf 10
0 2 tnrb.ttf 13
0 3 georgia.ttf 13
0 4 tnrb.ttf 16
0 5 georgia.ttf 13
0 6 tnrb.ttf 08
0 7 georgia.ttf 10
0 8 georgia.ttf 13
-1
Format:
1 = enabled, 0=disabled
font numeric ID
TTF font name
font size
ID of fonts:
0 BIGFONT.FNT //windows titles
1 CALLI10R.FNT ?
2 CREDITS.FNT
3 HISCORE.FNT
4 MEDFONT.FNT //most used font
5 SMALFONT.FNT //most used font
6 TIMES08R.FNT ?
7 TINY.FNT //used for small texts
8 VERD10B.FNT ?

View File

@ -1622,6 +1622,49 @@ int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
return ret;
}
int CGTownInstance::defenceBonus(int type) const
{
int ret=0;
switch (type)
{
/*attack*/ case 0:
if (subID == 6 && vstd::contains(builtBuildings,26))//Stronghold, grail
ret += 12;
if (subID == 7 && vstd::contains(builtBuildings,26))//Fortress, grail
ret += 10;
if (subID == 7 && vstd::contains(builtBuildings,22))//Fortress, Blood Obelisk
ret += 2;
return ret;
/*defence*/ case 1:
if (subID == 7 && vstd::contains(builtBuildings,21))//Fortress, Glyphs of Fear
ret += 2;
if (subID == 7 && vstd::contains(builtBuildings,26))//Fortress, Grail
ret += 10;
return ret;
/*spellpower*/ case 2:
if (subID == 3 && vstd::contains(builtBuildings,21))//Inferno, Brimstone Clouds
ret += 2;
if (subID == 5 && vstd::contains(builtBuildings,26))//Dungeon, Grail
ret += 12;
return ret;
/*knowledge*/ case 3:
if (subID == 2 && vstd::contains(builtBuildings,26))//Tower, Grail
ret += 15;
return ret;
/*morale*/ case 4:
if ( vstd::contains(builtBuildings, 5))//Any, Tavern
ret += 1;
if (subID == 0 && vstd::contains(builtBuildings,22))//Castle, Brotherhood of the sword
ret += 1;
return ret;
/*luck*/ case 5:
if (subID == 1 && vstd::contains(builtBuildings,21))//Rampart, Fountain of Fortune
ret += 2;
return ret;
}
return 0;//Why we are here? wrong type?
}
bool CGTownInstance::needsLastStack() const
{
if(garrisonHero)
@ -1700,7 +1743,7 @@ void CGTownInstance::newTurn() const
{
if (cb->getDate(1) == 1) //reset on new week
{
if (vstd::contains(builtBuildings,17) && subID == 1 && cb->getDate(0) && (tempOwner < PLAYER_LIMIT) )//give resources for Rampart, Mystic Pond
if (vstd::contains(builtBuildings,17) && subID == 1 && cb->getDate(0) != 1 && (tempOwner < PLAYER_LIMIT) )//give resources for Rampart, Mystic Pond
{
int resID = rand()%4+2;//bonus to random rare resource
resID = (resID==2)?1:resID;

View File

@ -493,6 +493,7 @@ public:
int dailyIncome() const; //calculates daily income of this town
int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
void removeCapitols (ui8 owner, bool me) const;
int defenceBonus(int type) const;//bonuses for defending hero, 0..3 - primary skills, 4 = morale, 5 = luck
CGTownInstance();
virtual ~CGTownInstance();

View File

@ -1265,6 +1265,35 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
}
}
//giving building bonuses, if siege and we have harrisoned hero
if (town)
{
if (hero2)
for (int i=0; i<4; i++)
{
int val = town->defenceBonus(i);
if (val)
{
GiveBonus gs;
gs.bonus = HeroBonus(HeroBonus::ONE_BATTLE, HeroBonus::PRIMARY_SKILL, HeroBonus::OBJECT, val, -1, "", i);
gs.hid = hero2->id;
sendAndApply(&gs);
}
}
int bonuseValue = town->defenceBonus(4);//morale
if (bonuseValue)
for(int g=0; g<stacks.size(); ++g)
if (!stacks[g]->attackerOwned)//garrisoned stack
stacks[g]->features.push_back(makeFeature(StackFeature::MORALE_BONUS, StackFeature::WHOLE_BATTLE, 0, bonuseValue, StackFeature::OTHER_SOURCE));
bonuseValue = town->defenceBonus(5);//luck
if (bonuseValue)
for(int g=0; g<stacks.size(); ++g)
if (!stacks[g]->attackerOwned)//garrisoned stack
stacks[g]->features.push_back(makeFeature(StackFeature::LUCK_BONUS, StackFeature::WHOLE_BATTLE, 0, bonuseValue, StackFeature::OTHER_SOURCE));
}
//giving terrain premies for heroes & stacks
int bonusSubtype = -1;
@ -2555,7 +2584,8 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
if(vstd::contains(hero->artifWorn,ui16(9+aid)) && complain("Hero already has this machine!")
|| !vstd::contains(town->builtBuildings,si32(16)) && complain("No blackismith!")
|| gs->getPlayer(hero->getOwner())->resources[6] < price && complain("Not enough gold!") //no gold
|| town->town->warMachine!= aid && complain("This machine is unavailable here!") ) //TODO: ballista yard in Stronghold
|| (!(town->subID == 6 && vstd::contains(town->builtBuildings,si32(22) ) )
&& town->town->warMachine!= aid ) && complain("This machine is unavailable here!") )
{
return false;
}