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