diff --git a/AI/GeniusAI/genius.vcproj b/AI/GeniusAI/genius.vcproj
index 2acef3b96..7b937a2d6 100644
--- a/AI/GeniusAI/genius.vcproj
+++ b/AI/GeniusAI/genius.vcproj
@@ -295,6 +295,14 @@
>
+
+
+
+
@@ -311,6 +319,14 @@
RelativePath=".\DLLMain.cpp"
>
+
+
+
+
diff --git a/client/CMT.cpp b/client/CMT.cpp
index c47222eaa..077bcd987 100644
--- a/client/CMT.cpp
+++ b/client/CMT.cpp
@@ -129,8 +129,8 @@ void init()
CGI->soundh->init();
CGI->soundh->setVolume(GDefaultOptions.soundVolume);
CGI->musich = new CMusicHandler;
- CGI->musich->init();
- CGI->musich->setVolume(GDefaultOptions.musicVolume);
+ //CGI->musich->init();
+ //CGI->musich->setVolume(GDefaultOptions.musicVolume);
tlog0<<"\tInitializing sound: "<flags << std::endl;
+
if(screen2)
SDL_FreeSurface(screen2);
screen2 = CSDL_Ext::copySurface(screen);
SDL_EnableUNICODE(1);
SDL_WM_SetCaption(NAME.c_str(),""); //set window title
SDL_ShowCursor(SDL_DISABLE);
+
+ screenBuf = bufOnScreen ? screen : screen2;
}
void listenForEvents()
@@ -421,26 +431,37 @@ void listenForEvents()
{
ev = new SDL_Event();
+ //tlog0 << "Waiting... ";
int ret = SDL_WaitEvent(ev);
- if(ret == 0 || (ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
+ //tlog0 << "got " << (int)ev->type;
+ if(/*ret == 0 || */(ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
{
- LOCPLINT->pim->lock();
+ if(LOCPLINT)
+ LOCPLINT->pim->lock();
client->close();
console->end();
SDL_Delay(750);
tlog0 << "Ending...\n";
exit(EXIT_SUCCESS);
}
- else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
+ else if(LOCPLINT && ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
{
boost::unique_lock lock(*LOCPLINT->pim);
bool full = !(screen->flags&SDL_FULLSCREEN);
setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,full);
GH.totalRedraw();
}
+ else if(ev->type == SDL_USEREVENT && ev->user.code == 1)
+ {
+ setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
+ delete ev;
+ continue;
+ }
+ //tlog0 << " pushing ";
eventsM.lock();
events.push(ev);
eventsM.unlock();
+ //tlog0 << " done\n";
}
}
@@ -456,7 +477,11 @@ void startGame(StartInfo * options)
if(screen->w != conf.cc.resx || screen->h != conf.cc.resy)
{
- setScreenRes(conf.cc.resx,conf.cc.resy,conf.cc.bpp,conf.cc.fullscreen);
+ //push special event to order event reading thread to change resolution
+ SDL_Event ev;
+ ev.type = SDL_USEREVENT;
+ ev.user.code = 1;
+ SDL_PushEvent(&ev);
}
CClient cl;
diff --git a/client/CMessage.cpp b/client/CMessage.cpp
index 9623ae547..8b11cdef3 100644
--- a/client/CMessage.cpp
+++ b/client/CMessage.cpp
@@ -102,12 +102,12 @@ void CMessage::dispose()
SDL_Surface * CMessage::drawBox1(int w, int h, int playerColor) //draws box for window
{
//prepare surface
- SDL_Surface * ret = SDL_CreateRGBSurface(screen->flags, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
+ SDL_Surface * ret = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
for (int i=0; ih)//background
{
- for (int j=0; jw-1)
+ for (int j=0; jw)
{
- SDL_BlitSurface(background,&genRect(background->h,background->w-1,1,0),ret,&genRect(h,w,j,i)); //FIXME taking address of temporary
+ SDL_BlitSurface(background,&genRect(background->h,background->w,0,0),ret,&genRect(h,w,j,i)); //FIXME taking address of temporary
}
}
drawBorder(playerColor, ret, w, h);
@@ -515,7 +515,7 @@ void CMessage::drawBorder(int playerColor, SDL_Surface * ret, int w, int h, int
SDL_BlitSurface
(piecesOfBox[playerColor][6],NULL,ret,&genRect(piecesOfBox[playerColor][6]->h,piecesOfBox[playerColor][6]->w,x+i,y+0));
SDL_BlitSurface
- (piecesOfBox[playerColor][7],NULL,ret,&genRect(piecesOfBox[playerColor][7]->h,piecesOfBox[playerColor][7]->w,x+i,y+h-piecesOfBox[playerColor][7]->h));
+ (piecesOfBox[playerColor][7],NULL,ret,&genRect(piecesOfBox[playerColor][7]->h,piecesOfBox[playerColor][7]->w,x+i,y+h-piecesOfBox[playerColor][7]->h+1));
}
//obwodka I-szego rzedu pionowa //border of 1st series, vertical
for (int i=0; ih; i+=piecesOfBox[playerColor][4]->h)
@@ -531,9 +531,9 @@ void CMessage::drawBorder(int playerColor, SDL_Surface * ret, int w, int h, int
SDL_BlitSurface
(piecesOfBox[playerColor][1],NULL,ret,&genRect(piecesOfBox[playerColor][1]->h,piecesOfBox[playerColor][1]->w,x+w-piecesOfBox[playerColor][1]->w,y+0));
SDL_BlitSurface
- (piecesOfBox[playerColor][2],NULL,ret,&genRect(piecesOfBox[playerColor][2]->h,piecesOfBox[playerColor][2]->w,x+0,y+h-piecesOfBox[playerColor][2]->h));
+ (piecesOfBox[playerColor][2],NULL,ret,&genRect(piecesOfBox[playerColor][2]->h,piecesOfBox[playerColor][2]->w,x+0,y+h-piecesOfBox[playerColor][2]->h+1));
SDL_BlitSurface
- (piecesOfBox[playerColor][3],NULL,ret,&genRect(piecesOfBox[playerColor][3]->h,piecesOfBox[playerColor][3]->w,x+w-piecesOfBox[playerColor][3]->w,y+h-piecesOfBox[playerColor][3]->h));
+ (piecesOfBox[playerColor][3],NULL,ret,&genRect(piecesOfBox[playerColor][3]->h,piecesOfBox[playerColor][3]->w,x+w-piecesOfBox[playerColor][3]->w,y+h-piecesOfBox[playerColor][3]->h+1));
}
ComponentResolved::ComponentResolved()
diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp
index 061766be6..2db62a35b 100644
--- a/client/CPlayerInterface.cpp
+++ b/client/CPlayerInterface.cpp
@@ -175,10 +175,8 @@ void CPlayerInterface::yourTurn()
while(makingTurn) // main loop
{
- updateWater();
pim->lock();
-
//if there are any waiting dialogs, show them
if(dialogs.size() && !showingDialog->get())
{
@@ -1504,6 +1502,9 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
if(cb->isVisible(*it))
adventureInt->minimap.showTile(*it);
}
+
+ if(obj->ID == TOWNI_TYPE)
+ adventureInt->townList.genList();
}
}
diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp
index d91737af2..dbe3d6a8e 100644
--- a/client/CPreGame.cpp
+++ b/client/CPreGame.cpp
@@ -23,6 +23,8 @@
#include "../hch/CMusicHandler.h"
#include "../hch/CVideoHandler.h"
#include "AdventureMapButton.h"
+#include "GUIClasses.h"
+#include "../hch/CCreatureHandler.h"
/*
* CPreGame.cpp, part of VCMI engine
*
@@ -212,7 +214,6 @@ CSelectionScreen::CSelectionScreen( EState Type )
break;
case loadGame:
- card->difficulty->select(current->seldiff, 0);
sel->recActions = 255;
start = new AdventureMapButton(CGI->generaltexth->zelp[103], bind(&CSelectionScreen::startGame, this), 414, 535, "SCNRLOD.DEF", SDLK_b);
break;
@@ -669,6 +670,7 @@ void SelectionTab::clickLeft( tribool down, bool previousState )
InfoCard::InfoCard( EState Type )
{
OBJ_CONSTRUCTION;
+ used = RCLICK;
sizes = CDefHandler::giveDef("SCNRMPSZ.DEF");
sFlags = CDefHandler::giveDef("ITGFLAGS.DEF");
type = Type;
@@ -779,10 +781,10 @@ void InfoCard::showAll( SDL_Surface * to )
//print flags
int fx=64, ex=244, myT;
- if (curMap->howManyTeams)
+ //if (curMap->howManyTeams)
myT = curMap->players[playerColor].team;
- else
- myT = -1;
+ //else
+ // myT = -1;
for (std::vector::const_iterator i = curOpts->playerInfos.begin(); i != curOpts->playerInfos.end(); i++)
{
int *myx = ((i->color == playerColor || curMap->players[i->color].team == myT) ? &fx : &ex);
@@ -815,12 +817,47 @@ void InfoCard::showAll( SDL_Surface * to )
void InfoCard::changeSelection( const CMapInfo *to )
{
- //current = to;
+ if(type == loadGame)
+ difficulty->select(curMap->seldiff, 0);
GH.totalRedraw();
}
-OptionsTab::OptionsTab( EState Type/*, StartInfo &Opts */)
- //:opts(Opts)
+void InfoCard::clickRight( tribool down, bool previousState )
+{
+ static const Rect flagArea(19, 397, 335, 23);
+ if(down && isItInLoc(flagArea, GH.current->motion.x, GH.current->motion.y))
+ showTeamsPopup();
+}
+
+void InfoCard::showTeamsPopup()
+{
+ SDL_Surface *bmp = CMessage::drawBox1(256, 90 + 50 * curMap->howManyTeams);
+ CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[657], 128, 30, FONT_MEDIUM, tytulowy, bmp); //{Team Alignments}
+
+ for(int i = 0; i < curMap->howManyTeams; i++)
+ {
+ std::vector flags;
+ std::string hlp = CGI->generaltexth->allTexts[656]; //Team %d
+ hlp.replace(hlp.find("%d"), 2, boost::lexical_cast(i+1));
+ CSDL_Ext::printAtMiddle(hlp, 128, 65 + 50*i, FONT_SMALL, zwykly, bmp);
+
+ for(int j = 0; j < PLAYER_LIMIT; j++)
+ if((curMap->players[j].canHumanPlay || curMap->players[j].canComputerPlay)
+ && curMap->players[j].team == i)
+ flags.push_back(j);
+
+ int curx = 128 - 9*flags.size();
+ for(int j = 0; j < flags.size(); j++)
+ {
+ blitAt(sFlags->ourImages[flags[j]].bitmap, curx, 75 + 50*i, bmp);
+ curx += 18;
+ }
+ }
+
+ GH.pushInt(new CInfoPopup(bmp, true));
+}
+
+OptionsTab::OptionsTab( EState Type)
{
OBJ_CONSTRUCTION;
bg = new CPicture(BitmapHandler::loadBitmap("ADVOPTBK.bmp"), 3, 6, true);
@@ -1068,12 +1105,13 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry( OptionsTab *owner, PlayerSet
else
flag = NULL;
+ defActions &= ~SHARE_POS;
town = new SelectedBox(TOWN, s.serial);
- town->pos = pos + Point(119, 2);
+ town->pos += pos + Point(119, 2);
hero = new SelectedBox(HERO, s.serial);
- hero->pos = pos + Point(195, 2);
+ hero->pos += pos + Point(195, 2);
bonus = new SelectedBox(BONUS, s.serial);
- bonus->pos = pos + Point(271, 2);
+ bonus->pos += pos + Point(271, 2);
}
void OptionsTab::PlayerOptionsEntry::showAll( SDL_Surface * to )
@@ -1104,70 +1142,57 @@ void OptionsTab::PlayerOptionsEntry::selectButtons(bool onlyHero)
void OptionsTab::SelectedBox::showAll( SDL_Surface * to )
{
PlayerSettings &s = curOpts->playerInfos[player];
- SDL_Surface *toBlit = NULL;
- const std::string *toPrint = NULL;
+ SDL_Surface *toBlit = getImg();
+ const std::string *toPrint = getText();
+ blitAt(toBlit, pos, to);
+ printAtMiddleLoc(*toPrint, 23, 39, FONT_TINY, zwykly, to);
+}
+OptionsTab::SelectedBox::SelectedBox( SelType Which, ui8 Player )
+:which(Which), player(Player)
+{
+ SDL_Surface *img = getImg();
+ pos.w = img->w;
+ pos.h = img->h;
+ used = RCLICK;
+}
+
+SDL_Surface * OptionsTab::SelectedBox::getImg() const
+{
+ PlayerSettings &s = curOpts->playerInfos[player];
switch(which)
{
case TOWN:
- {
- if (s.castle < F_NUMBER && s.castle >= 0)
- {
- toBlit = graphics->getPic(s.castle, true, false);
- toPrint = &CGI->townh->towns[s.castle].Name();
- }
- else if (s.castle == -1)
- {
- toBlit = CGP->rTown;
- toPrint = &CGI->generaltexth->allTexts[522];
- }
- else if (s.castle == -2)
- {
- toBlit = CGP->nTown;
- toPrint = &CGI->generaltexth->allTexts[523];
- }
- }
- break;
+ if (s.castle < F_NUMBER && s.castle >= 0)
+ return graphics->getPic(s.castle, true, false);
+ else if (s.castle == -1)
+ return CGP->rTown;
+ else if (s.castle == -2)
+ return CGP->nTown;
case HERO:
+ if (s.hero == -1)
{
- if (s.hero == -1)
- {
- toBlit = CGP->rHero;
- toPrint = &CGI->generaltexth->allTexts[522];
- }
- else if (s.hero == -2)
- {
- if(s.heroPortrait >= 0)
- {
- toBlit = graphics->portraitSmall[s.heroPortrait];
- if(s.heroName.length())
- toPrint = &s.heroName;
- else
- toPrint = &CGI->heroh->heroes[s.heroPortrait]->name;
- }
- else
- {
- toBlit = CGP->nHero;
- toPrint = &CGI->generaltexth->allTexts[523];
- }
- }
+ return CGP->rHero;
+ }
+ else if (s.hero == -2)
+ {
+ if(s.heroPortrait >= 0)
+ return graphics->portraitSmall[s.heroPortrait];
else
- {
- toBlit = graphics->portraitSmall[s.hero];
- toPrint = &s.heroName;
- }
+ return CGP->nHero;
+ }
+ else
+ {
+ return graphics->portraitSmall[s.hero];
}
break;
case BONUS:
{
int pom;
- toPrint = &CGI->generaltexth->arraytxt[214 + s.bonus];
-
switch (s.bonus)
{
case -1:
pom=10;
- toPrint = &CGI->generaltexth->allTexts[522];
break;
case 0:
pom=9;
@@ -1178,17 +1203,213 @@ void OptionsTab::SelectedBox::showAll( SDL_Surface * to )
case 2:
pom=CGI->townh->towns[s.castle].bonus;
break;
+ default:
+ assert(0);
}
- toBlit = CGP->bonuses->ourImages[pom].bitmap;
+ return CGP->bonuses->ourImages[pom].bitmap;
}
- break;
+ default:
+ return NULL;
}
-
- blitAt(toBlit, pos, to);
- printAtMiddleLoc(*toPrint, 23, 39, FONT_TINY, zwykly, to);
}
-OptionsTab::SelectedBox::SelectedBox( SelType Which, ui8 Player )
-:which(Which), player(Player)
+const std::string * OptionsTab::SelectedBox::getText() const
{
+ PlayerSettings &s = curOpts->playerInfos[player];
+ switch(which)
+ {
+ case TOWN:
+ if (s.castle < F_NUMBER && s.castle >= 0)
+ return &CGI->townh->towns[s.castle].Name();
+ else if (s.castle == -1)
+ return &CGI->generaltexth->allTexts[522];
+ else if (s.castle == -2)
+ return &CGI->generaltexth->allTexts[523];
+ case HERO:
+ if (s.hero == -1)
+ return &CGI->generaltexth->allTexts[522];
+ else if (s.hero == -2)
+ {
+ if(s.heroPortrait >= 0)
+ {
+ if(s.heroName.length())
+ return &s.heroName;
+ else
+ return &CGI->heroh->heroes[s.heroPortrait]->name;
+ }
+ else
+ return &CGI->generaltexth->allTexts[523];
+ }
+ else
+ {
+ //if(s.heroName.length())
+ // return &s.heroName;
+ //else
+ return &CGI->heroh->heroes[s.hero]->name;
+ }
+ case BONUS:
+ switch (s.bonus)
+ {
+ case -1:
+ return &CGI->generaltexth->allTexts[522];
+ default:
+ return &CGI->generaltexth->arraytxt[214 + s.bonus];
+ }
+ default:
+ return NULL;
+ }
+}
+
+void OptionsTab::SelectedBox::clickRight( tribool down, bool previousState )
+{
+ if(indeterminate(down) || !down) return;
+ PlayerSettings &s = curOpts->playerInfos[player];
+ SDL_Surface *bmp = NULL;
+ const std::string *title = NULL, *subTitle = NULL;
+
+ subTitle = getText();
+
+ int val;
+ switch(which)
+ {
+ case TOWN: val = s.castle; break;
+ case HERO:
+ val = s.hero;
+ if(val < 0)
+ {
+ int p9 = curMap->players[s.color].p9;
+ if(p9 != 255)
+ val = p9;
+ }
+ break;
+ case BONUS: val = s.bonus; break;
+ }
+
+ if(val == -1 || which == BONUS) //random or bonus box
+ {
+ bmp = CMessage::drawBox1(256, 190);
+ std::string *description = NULL;
+
+ switch(which)
+ {
+ case TOWN:
+ title = &CGI->generaltexth->allTexts[103];
+ description = &CGI->generaltexth->allTexts[104];
+ break;
+ case HERO:
+ title = &CGI->generaltexth->allTexts[101];
+ description = &CGI->generaltexth->allTexts[102];
+ break;
+ case BONUS:
+ {
+ switch(val)
+ {
+ case brandom:
+ title = &CGI->generaltexth->allTexts[86]; //{Random Bonus}
+ description = &CGI->generaltexth->allTexts[94]; //Gold, wood and ore, or an artifact is randomly chosen as your starting bonus
+ break;
+ case bartifact:
+ title = &CGI->generaltexth->allTexts[83]; //{Artifact Bonus}
+ description = &CGI->generaltexth->allTexts[90]; //An artifact is randomly chosen and equipped to your starting hero
+ break;
+ case bgold:
+ title = &CGI->generaltexth->allTexts[84]; //{Gold Bonus}
+ subTitle = &CGI->generaltexth->allTexts[87]; //500-1000
+ description = &CGI->generaltexth->allTexts[92]; //At the start of the game, 500-1000 gold is added to your Kingdom's resource pool
+ break;
+ case bresource:
+ {
+ title = &CGI->generaltexth->allTexts[85]; //{Resource Bonus}
+ switch(CGI->townh->towns[s.castle].primaryRes)
+ {
+ case 1:
+ subTitle = &CGI->generaltexth->allTexts[694];
+ description = &CGI->generaltexth->allTexts[690];
+ break;
+ case 3:
+ subTitle = &CGI->generaltexth->allTexts[695];
+ description = &CGI->generaltexth->allTexts[691];
+ break;
+ case 4:
+ subTitle = &CGI->generaltexth->allTexts[692];
+ description = &CGI->generaltexth->allTexts[688];
+ break;
+ case 5:
+ subTitle = &CGI->generaltexth->allTexts[693];
+ description = &CGI->generaltexth->allTexts[689];
+ break;
+ case 127:
+ subTitle = &CGI->generaltexth->allTexts[89]; //5-10 wood / 5-10 ore
+ description = &CGI->generaltexth->allTexts[93]; //At the start of the game, 5-10 wood and 5-10 ore are added to your Kingdom's resource pool
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ if(description)
+ CSDL_Ext::printAtMiddleWB(*description, 125, 145, FONT_SMALL, 37, zwykly, bmp);
+ }
+ else if(val == -2)
+ {
+ return;
+ }
+ else if(which == TOWN)
+ {
+ bmp = CMessage::drawBox1(256, 319);
+ title = &CGI->generaltexth->allTexts[80];
+
+ CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[79], 135, 137, FONT_MEDIUM, tytulowy, bmp);
+
+ const CTown &t = CGI->townh->towns[val];
+ //print creatures
+ int x = 60, y = 159;
+ for(int i = 0; i < 7; i++)
+ {
+ int c = t.basicCreatures[i];
+ blitAt(graphics->smallImgs[c], x, y, bmp);
+ CSDL_Ext::printAtMiddleWB(CGI->creh->creatures[c].nameSing, x + 16, y + 45, FONT_TINY, 10, zwykly, bmp);
+
+ if(i == 2)
+ {
+ x = 40;
+ y += 76;
+ }
+ else
+ {
+ x += 52;
+ }
+ }
+
+ }
+ else if(val >= 0)
+ {
+ const CHero *h = CGI->heroh->heroes[val];
+ bmp = CMessage::drawBox1(320, 255);
+ title = &CGI->generaltexth->allTexts[77];
+
+ CSDL_Ext::printAtMiddle(*title, 167, 36, FONT_MEDIUM, tytulowy, bmp);
+ CSDL_Ext::printAtMiddle(*subTitle + " - " + h->heroClass->name, 160, 99, FONT_SMALL, zwykly, bmp);
+
+ blitAt(getImg(), 136, 56, bmp);
+
+ //print specialty
+ CSDL_Ext::printAtMiddle(CGI->generaltexth->allTexts[78], 166, 132, FONT_MEDIUM, tytulowy, bmp);
+ blitAt(graphics->un44->ourImages[val].bitmap, 140, 150, bmp);
+
+ GH.pushInt(new CInfoPopup(bmp, true));
+ return;
+ }
+
+ if(title)
+ CSDL_Ext::printAtMiddle(*title, 135, 36, FONT_MEDIUM, tytulowy, bmp);
+ if(subTitle)
+ CSDL_Ext::printAtMiddle(*subTitle, 127, 103, FONT_SMALL, zwykly, bmp);
+
+ blitAt(getImg(), 104, 60, bmp);
+
+ GH.pushInt(new CInfoPopup(bmp, true));
}
\ No newline at end of file
diff --git a/client/CPreGame.h b/client/CPreGame.h
index 52b485cd2..faa4c6ce5 100644
--- a/client/CPreGame.h
+++ b/client/CPreGame.h
@@ -61,6 +61,8 @@ public:
void changeSelection(const CMapInfo *to);
void showAll(SDL_Surface * to);
+ void clickRight(tribool down, bool previousState);
+ void showTeamsPopup();
InfoCard(EState Type);
~InfoCard();
};
@@ -106,8 +108,13 @@ public:
{
SelType which;
ui8 player; //serial nr
- void showAll(SDL_Surface * to);
+
+ SDL_Surface *getImg() const;
+ const std::string *getText() const;
+
SelectedBox(SelType Which, ui8 Player);
+ void showAll(SDL_Surface * to);
+ void clickRight(tribool down, bool previousState);
};
struct PlayerOptionsEntry : public CIntObject
diff --git a/client/Client.h b/client/Client.h
index ec19221a7..0f7404666 100644
--- a/client/Client.h
+++ b/client/Client.h
@@ -101,7 +101,7 @@ public:
void heroVisitCastle(int obj, int heroID){};
void stopHeroVisitCastle(int obj, int heroID){};
void giveHeroArtifact(int artid, int hid, int position){}; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
- void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb = 0){}; //use hero=NULL for no hero
+ void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb = 0, const CGTownInstance *town = NULL){}; //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb = 0){}; //if any of armies is hero, hero will be used
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function cb = 0){}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
void setAmount(int objid, ui32 val){};
diff --git a/client/GUIBase.cpp b/client/GUIBase.cpp
index ede2ae747..2167357f4 100644
--- a/client/GUIBase.cpp
+++ b/client/GUIBase.cpp
@@ -536,6 +536,16 @@ void CIntObject::enable(bool activation)
recActions = 255;
}
+bool CIntObject::isItInLoc( const SDL_Rect &rect, int x, int y )
+{
+ return isItIn(&rect, x - pos.x, y - pos.y);
+}
+
+bool CIntObject::isItInLoc( const SDL_Rect &rect, const Point &p )
+{
+ return isItIn(&rect, p.x - pos.x, p.y - pos.y);
+}
+
CPicture::CPicture( SDL_Surface *BG, int x, int y, bool Free )
{
bg = BG;
diff --git a/client/GUIBase.h b/client/GUIBase.h
index 0ba99cef0..cbdc648e4 100644
--- a/client/GUIBase.h
+++ b/client/GUIBase.h
@@ -331,6 +331,8 @@ public:
void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color kolor, SDL_Surface * dst, bool refresh = false);
void printAtMiddleWBLoc(const std::string & text, int x, int y, EFonts font, int charpr, SDL_Color kolor, SDL_Surface * dst, bool refrsh = false);
void blitAtLoc(SDL_Surface * src, int x, int y, SDL_Surface * dst);
+ bool isItInLoc(const SDL_Rect &rect, int x, int y);
+ bool isItInLoc(const SDL_Rect &rect, const Point &p);
};
//class for binding keys to left mouse button clicks
diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp
index 400531aca..3a92c00eb 100644
--- a/client/GUIClasses.cpp
+++ b/client/GUIClasses.cpp
@@ -683,6 +683,11 @@ CInfoPopup::CInfoPopup(SDL_Surface *Bitmap, bool Free)
{
free=Free;
bitmap=Bitmap;
+
+ pos.x = screen->w/2 - bitmap->w/2;
+ pos.y = screen->h/2 - bitmap->h/2;
+ pos.h = bitmap->h;
+ pos.w = bitmap->w;
}
void CInfoPopup::close()
@@ -1402,6 +1407,7 @@ CTownList::CTownList(int Size, int x, int y, std::string arrupg, std::string arr
void CTownList::genList()
{
+ items.clear();
int howMany = LOCPLINT->cb->howManyTowns();
for (int i=0;iformat->BytesPerPixel == 3 || dst->format->BytesPerPixel == 4); // 24/32 bpp dst only
@@ -225,8 +228,11 @@ void CSDL_Ext::printAt( const std::string & text, int x, int y, EFonts font, SDL
Uint8 *px = NULL;
Uint8 *src = NULL;
+ //if text is in {} braces, we'll ommit them
+ const int first = (text[0] == '{' ? 1 : 0);
+ const int beyondEnd = (text[text.size()-1] == '}' ? text.size()-1 : text.size());
- for(int txti = 0; txti < text.size(); txti++)
+ for(int txti = first; txti < beyondEnd; txti++)
{
const unsigned char c = text[txti];
src = f->chars[c].pixels;
diff --git a/client/VCMI_client.vcproj b/client/VCMI_client.vcproj
index e25807ab7..9d70c94fa 100644
--- a/client/VCMI_client.vcproj
+++ b/client/VCMI_client.vcproj
@@ -512,6 +512,10 @@
RelativePath="..\hch\CVideoHandler.h"
>
+
+
diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp
index f15f5513d..597ef3c6c 100644
--- a/hch/CObjectHandler.cpp
+++ b/hch/CObjectHandler.cpp
@@ -1406,7 +1406,26 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
{
if(getOwner() != h->getOwner())
{
- return;
+ //TODO ally check
+ if(army)
+ {
+ const CGHeroInstance *defendingHero = NULL;
+ if(visitingHero)
+ defendingHero = visitingHero;
+ else if(garrisonHero)
+ defendingHero = garrisonHero;
+
+ const CArmedInstance *defendingArmy = this;
+ if(defendingHero)
+ defendingArmy = defendingHero;
+
+ bool outsideTown = (defendingHero == visitingHero && garrisonHero);
+ cb->startBattleI(h, defendingArmy, getSightCenter(), h, defendingHero, false, boost::bind(&CGTownInstance::fightOver, this, h, _1), (outsideTown ? NULL : this));
+ }
+ else
+ {
+ cb->setOwner(id, h->tempOwner);
+ }
}
cb->heroVisitCastle(id,h->id);
}
@@ -1440,6 +1459,14 @@ void CGTownInstance::getOutOffsets( std::vector &offsets ) const
offsets += int3(-1,3,0), int3(-3,3,0);
}
+void CGTownInstance::fightOver( const CGHeroInstance *h, BattleResult *result ) const
+{
+ if(result->winner == 0)
+ {
+ cb->setOwner(id, h->tempOwner);
+ }
+}
+
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
{
if(visitors.find(h->id)==visitors.end())
diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h
index 8031acace..d830e20a1 100644
--- a/hch/CObjectHandler.h
+++ b/hch/CObjectHandler.h
@@ -397,6 +397,7 @@ public:
//////////////////////////////////////////////////////////////////////////
+ void fightOver(const CGHeroInstance *h, BattleResult *result) const;
void onHeroVisit(const CGHeroInstance * h) const;
void onHeroLeave(const CGHeroInstance * h) const;
void initObj();
diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp
index 2409771b9..224fddd5e 100644
--- a/lib/CGameState.cpp
+++ b/lib/CGameState.cpp
@@ -1403,8 +1403,8 @@ bool CGameState::battleCanFlee(int player)
const CGHeroInstance *h1 = getHero(curB->hero1);
const CGHeroInstance *h2 = getHero(curB->hero2);
- if(h1->hasBonusOfType(HeroBonus::ENEMY_CANT_ESCAPE) //eg. one of heroes is wearing shakles of war
- || h2->hasBonusOfType(HeroBonus::ENEMY_CANT_ESCAPE))
+ if(h1 && h1->hasBonusOfType(HeroBonus::ENEMY_CANT_ESCAPE) //eg. one of heroes is wearing shakles of war
+ || h2 && h2->hasBonusOfType(HeroBonus::ENEMY_CANT_ESCAPE))
return false;
return true;
@@ -1557,7 +1557,7 @@ void CGameState::loadTownDInfos()
void CGameState::getNeighbours(int3 tile, std::vector &vec, const boost::logic::tribool &onLand)
{
- int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0),
+ static int3 dirs[] = { int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0),
int3(1,1,0),int3(-1,1,0),int3(1,-1,0),int3(-1,-1,0) };
vec.clear();
@@ -1704,6 +1704,8 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
else
blockLandSea = boost::logic::indeterminate;
+ const std::vector > > &FoW = getPlayer(hero->tempOwner)->fogOfWarMap;
+
//graph initialization
std::vector< std::vector > graph;
graph.resize(map->width);
@@ -1726,7 +1728,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
if ((tinfo->tertype == TerrainTile::rock) //it's rock
|| ((blockLandSea) && (tinfo->tertype == TerrainTile::water)) //it's sea and we cannot walk on sea
|| ((!blockLandSea) && (tinfo->tertype != TerrainTile::water)) //it's land and we cannot walk on land
- || !getPlayer(hero->tempOwner)->fogOfWarMap[i][j][src.z] //tile is covered by the FoW
+ || !FoW[i][j][src.z] //tile is covered by the FoW
)
{
node.accesible = false;
@@ -1750,10 +1752,10 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
{
size_t i = 0;
for(; i < t->visitableObjects.size(); i++)
- if(t->visitableObjects[i]->ID == 8) //it's a Boat
+ if(t->visitableObjects[i]->ID == 8 || t->visitableObjects[i]->ID == HEROI_TYPE) //it's a Boat
break;
- d.accesible = (i < t->visitableObjects.size()); //dest is accessible only if there is boat
+ d.accesible = (i < t->visitableObjects.size()); //dest is accessible only if there is boat/hero
}
else if(!blockLandSea && t->tertype != TerrainTile::water) //hero is moving by water
{
diff --git a/lib/CGameState.h b/lib/CGameState.h
index 49108cba8..6312b4f15 100644
--- a/lib/CGameState.h
+++ b/lib/CGameState.h
@@ -110,6 +110,7 @@ struct DLL_EXPORT BattleInfo
ui8 side1, side2; //side1 - attacker, side2 - defender
si32 round, activeStack;
ui8 siege; // = 0 ordinary battle = 1 a siege with a Fort = 2 a siege with a Citadel = 3 a siege with a Castle
+ si32 tid; //used during town siege - id of attacked town; -1 if not town defence
int3 tile; //for background and bonuses
si32 hero1, hero2;
CCreatureSet army1, army2;
diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h
index ce7fa58fa..482c66f8a 100644
--- a/lib/IGameCallback.h
+++ b/lib/IGameCallback.h
@@ -79,7 +79,7 @@ public:
virtual void heroVisitCastle(int obj, int heroID)=0;
virtual void stopHeroVisitCastle(int obj, int heroID)=0;
virtual void giveHeroArtifact(int artid, int hid, int position)=0; //pos==-1 - first free slot in backpack=0; pos==-2 - default if available or backpack
- virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb = 0)=0; //use hero=NULL for no hero
+ virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb = 0, const CGTownInstance *town = NULL)=0; //use hero=NULL for no hero
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb = 0)=0; //if any of armies is hero, hero will be used
virtual void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function cb = 0)=0; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
//virtual void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb)=0; //for hero<=>neutral army
diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp
index 986dfb855..ba8d72e7d 100644
--- a/lib/NetPacksLib.cpp
+++ b/lib/NetPacksLib.cpp
@@ -552,9 +552,26 @@ DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs )
{
CGObjectInstance *obj = gs->map->objects[id];
if(!obj)
+ {
tlog1 << "Wrong object ID - property cannot be set!\n";
- else
- obj->setProperty(what,val);
+ return;
+ }
+
+ if(what == 1)
+ {
+ if(obj->ID == TOWNI_TYPE)
+ {
+ CGTownInstance *t = static_cast(obj);
+ if(t->tempOwner < PLAYER_LIMIT)
+ gs->getPlayer(t->tempOwner)->towns -= t;
+
+ if(val < PLAYER_LIMIT)
+ gs->getPlayer(val)->towns.push_back(t);
+ }
+ }
+
+
+ obj->setProperty(what,val);
}
DLL_EXPORT void SetHoverName::applyGs( CGameState *gs )
diff --git a/lib/map.cpp b/lib/map.cpp
index 313ef6e02..ef21943ab 100644
--- a/lib/map.cpp
+++ b/lib/map.cpp
@@ -253,7 +253,7 @@ void CMapHeader::initFromMemory( unsigned char *bufor, int &i )
{
for(int rr=0; rr<8; ++rr)
{
- players[rr].team=bufor[i++];
+ players[rr].team = bufor[i++];
}
}
@@ -1991,7 +1991,7 @@ void Mapa::readEvents( unsigned char * bufor, int &i )
}
}
-bool Mapa::isInTheMap( int3 pos ) const
+bool Mapa::isInTheMap(const int3 &pos) const
{
if(pos.x<0 || pos.y<0 || pos.z<0 || pos.x >= width || pos.y >= height || pos.z > twoLevel)
return false;
@@ -2086,18 +2086,33 @@ const TerrainTile & Mapa::getTile( int3 tile ) const
return terrain[tile.x][tile.y][tile.z];
}
-bool Mapa::isWaterTile( int3 pos ) const
+bool Mapa::isWaterTile(const int3 &pos) const
{
return isInTheMap(pos) && getTile(pos).tertype == TerrainTile::water;
}
void CMapInfo::countPlayers()
{
- playerAmnt=humenPlayers=0;
- for (int i=0;i void serialize(Handler &h, const int version)
{
@@ -219,7 +219,6 @@ public:
LossCondition lossCondition;
CVictoryCondition victoryCondition; //victory conditions
std::vector players; // info about players - size 8
- std::vector teams; // teams[i] = team of player no i
ui8 howManyTeams;
std::vector allowedHeroes; //allowedHeroes[hero_ID] - if the hero is allowed
void initFromMemory(unsigned char *bufor, int &i);
@@ -232,7 +231,7 @@ public:
template void serialize(Handler &h, const int Version)
{
h & version & name & description & width & height & twoLevel & difficulty & levelLimit & areAnyPLayers;
- h & players & teams & lossCondition & victoryCondition & howManyTeams;
+ h & players & lossCondition & victoryCondition & howManyTeams;
}
};
@@ -338,8 +337,8 @@ struct DLL_EXPORT Mapa : public CMapHeader
TerrainTile &getTile(int3 tile);
const TerrainTile &getTile(int3 tile) const;
CGHeroInstance * getHero(int ID, int mode=0);
- bool isInTheMap(int3 pos) const;
- bool isWaterTile(int3 pos) const; //out-of-pos safe
+ bool isInTheMap(const int3 &pos) const;
+ bool isWaterTile(const int3 &pos) const; //out-of-pos safe
template void serialize(Handler &h, const int formatVersion)
{
h & static_cast(*this);
diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp
index a26b06bd8..a15f99373 100644
--- a/server/CGameHandler.cpp
+++ b/server/CGameHandler.cpp
@@ -322,10 +322,10 @@ static CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInf
return ret;
}
-void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb)
+void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb, const CGTownInstance *town)
{
BattleInfo *curB = new BattleInfo;
- setupBattle(curB, tile, army1->army, army2->army, hero1, hero2, creatureBank); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
+ setupBattle(curB, tile, army1->army, army2->army, hero1, hero2, creatureBank, town); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
NEW_ROUND;
//TODO: pre-tactic stuff, call scripts etc.
@@ -857,13 +857,12 @@ namespace CGH
}
}
-void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank )
+void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank, const CGTownInstance *town)
{
battleResult.set(NULL);
std::vector & stacks = (curB->stacks);
curB->tile = tile;
- curB->siege = 0; //TODO: add sieges
curB->army1=army1;
curB->army2=army2;
curB->hero1=(hero1)?(hero1->id):(-1);
@@ -873,6 +872,17 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet
curB->round = -2;
curB->activeStack = -1;
+ if(town)
+ {
+ curB->tid = town->id;
+ curB->siege = town->fortLevel();
+ }
+ else
+ {
+ curB->tid = -1;
+ curB->siege = 0;
+ }
+
//reading battleStartpos
std::ifstream positions;
positions.open("config" PATHSEPARATOR "battleStartpos.txt", std::ios_base::in|std::ios_base::binary);
@@ -1540,7 +1550,7 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
sendAndApply(&sha);
}
-void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb) //use hero=NULL for no hero
+void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb, const CGTownInstance *town) //use hero=NULL for no hero
{
engageIntoBattle(army1->tempOwner);
engageIntoBattle(army2->tempOwner);
@@ -1548,7 +1558,7 @@ void CGameHandler::startBattleI(const CArmedInstance *army1, const CArmedInstanc
if(army2->tempOwner < PLAYER_LIMIT)
states.setFlag(army2->tempOwner,&PlayerStatus::engagedIntoBattle,true);
- boost::thread(boost::bind(&CGameHandler::startBattle, this, army1, army2, tile, hero1, hero2, creatureBank, cb));
+ boost::thread(boost::bind(&CGameHandler::startBattle, this, army1, army2, tile, hero1, hero2, creatureBank, cb, town));
}
void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb )
diff --git a/server/CGameHandler.h b/server/CGameHandler.h
index aae6302e7..444fef53a 100644
--- a/server/CGameHandler.h
+++ b/server/CGameHandler.h
@@ -84,11 +84,11 @@ public:
bool isAllowedExchange(int id1, int id2);
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
void moveStack(int stack, int dest);
- void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb); //use hero=NULL for no hero
+ void startBattle(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void prepareAttack(BattleAttack &bat, CStack *att, CStack *def); //if last parameter is true, attack is by shooting, if false it's a melee attack
void prepareAttacked(BattleStackAttacked &bsa, CStack *def);
void checkForBattleEnd( std::vector &stacks );
- void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank );
+ void setupBattle( BattleInfo * curB, int3 tile, const CCreatureSet &army1, const CCreatureSet &army2, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank, const CGTownInstance *town);
CGameHandler(void);
@@ -122,7 +122,7 @@ public:
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
void moveArtifact(int hid, int oldPosition, int destPos);
void removeArtifact(int hid, int pos);
- void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb); //use hero=NULL for no hero
+ void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool creatureBank, boost::function cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, int3 tile, bool creatureBank, boost::function cb);
void startBattleI(const CArmedInstance *army1, const CArmedInstance *army2, bool creatureBank, boost::function cb = 0); //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
//void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function cb); //for hero<=>neutral army