From 346af5396121ed54ede174c079ce7365ee3e175b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Sat, 16 Aug 2008 08:47:41 +0000 Subject: [PATCH] * showing creature amount in the CCreInfoWindow * fixes and improvements in dismiss/upgrade dialogs * possibility of moving hero into the garrison * viewing hero window in the town screen --- CBattleInterface.cpp | 2 +- CCallback.cpp | 6 ++ CCallback.h | 2 + CCastleInterface.cpp | 131 ++++++++++++++++++++++++++++++++-- CCastleInterface.h | 21 +++++- CGameInterface.h | 1 + CGameState.cpp | 21 ++++++ CHeroWindow.cpp | 4 +- CHeroWindow.h | 6 +- CLua.cpp | 2 +- CPlayerInterface.cpp | 152 ++++++++++++++++++++++++++++++++-------- CPlayerInterface.h | 15 ++-- client/Client.cpp | 11 +++ lib/NetPacks.h | 10 +++ mapHandler.cpp | 6 +- mapHandler.h | 4 +- server/CGameHandler.cpp | 68 ++++++++++++++++++ 17 files changed, 411 insertions(+), 51 deletions(-) diff --git a/CBattleInterface.cpp b/CBattleInterface.cpp index d9e632054..66e47c794 100644 --- a/CBattleInterface.cpp +++ b/CBattleInterface.cpp @@ -1237,7 +1237,7 @@ void CBattleHex::clickRight(boost::logic::tribool down) pom->morale = h->getCurrentMorale(); pom->currentHealth = myst.firstHPleft; } - (new CCreInfoWindow(myst.creature->idNumber,0,pom,boost::function(),boost::function(),NULL)) + (new CCreInfoWindow(myst.creature->idNumber,0,myst.amount,pom,boost::function(),boost::function(),NULL)) ->activate(); } delete pom; diff --git a/CCallback.cpp b/CCallback.cpp index 19cb80ce1..fd840b2fe 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -498,3 +498,9 @@ bool CCallback::battleCanShoot(int ID, int dest) //TODO: finish return true; return false; } + +void CCallback::swapGarrisonHero( const CGTownInstance *town ) +{ + if(town->tempOwner != player) return; + *cl->serv << ui16(508) << si32(town->id); +} \ No newline at end of file diff --git a/CCallback.h b/CCallback.h index bfb979826..0f28e99f0 100644 --- a/CCallback.h +++ b/CCallback.h @@ -39,6 +39,7 @@ public: virtual bool dismissCreature(const CArmedInstance *obj, int stackPos)=0; virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1)=0; //if newID==-1 then best possible upgrade will be made virtual void endTurn()=0; + virtual void swapGarrisonHero(const CGTownInstance *town)=0; //get info virtual bool verifyPath(CPath * path, bool blockSea)=0; @@ -111,6 +112,7 @@ public: bool dismissCreature(const CArmedInstance *obj, int stackPos); bool upgradeCreature(const CArmedInstance *obj, int stackPos, int newID=-1); void endTurn(); + void swapGarrisonHero(const CGTownInstance *town); //get info bool verifyPath(CPath * path, bool blockSea); diff --git a/CCastleInterface.cpp b/CCastleInterface.cpp index bda748917..d3ef1e2c0 100644 --- a/CCastleInterface.cpp +++ b/CCastleInterface.cpp @@ -14,6 +14,9 @@ #include "hch/CGeneralTextHandler.h" #include "CCallback.h" #include "client/Graphics.h" +#include "CHeroWindow.h" +#include +#include extern TTF_Font * GEOR16; CBuildingRect::CBuildingRect(Structure *Str) :str(Str), moi(false), offset(0) @@ -170,7 +173,116 @@ void CBuildingRect::mouseMoved (SDL_MouseMotionEvent & sEvent) //if(border) // blitAt(border,pos.x,pos.y); } +void CHeroGSlot::hover (bool on) +{ + if(!on) return; + CHeroGSlot *other = upg ? &owner->hslotup : &owner->hslotdown; + std::string temp; + if(hero) + { + if(highlight)//view NNN + { + temp = CGI->townh->tcommands[4]; + boost::algorithm::replace_first(temp,"%s",hero->name); + } + else if(other->hero && other->highlight)//exchange + { + temp = CGI->townh->tcommands[7]; + boost::algorithm::replace_first(temp,"%s",hero->name); + boost::algorithm::replace_first(temp,"%s",other->hero->name); + } + else// select NNN (in ZZZ) + { + if(upg)//down - visiting + { + temp = CGI->townh->tcommands[32]; + boost::algorithm::replace_first(temp,"%s",hero->name); + } + else //up - garrison + { + temp = CGI->townh->tcommands[12]; + boost::algorithm::replace_first(temp,"%s",hero->name); + } + } + } + else //we are empty slot + { + if(other->highlight && other->hero) //move NNNN + { + temp = CGI->townh->tcommands[6]; + boost::algorithm::replace_first(temp,"%s",other->hero->name); + } + else //empty + { + temp = CGI->generaltexth->allTexts[507]; + } + } + if(temp.size()) + LOCPLINT->statusbar->print(temp); +} +void CHeroGSlot::clickRight (boost::logic::tribool down) +{ +} +void CHeroGSlot::clickLeft(boost::logic::tribool down) +{ + if(!down) + { + CHeroGSlot *other = upg ? &owner->hslotup : &owner->hslotdown; + if(hero && highlight) + { + highlight = false; + LOCPLINT->openHeroWindow(hero); + LOCPLINT->adventureInt->heroWindow->quitButton->callback += boost::bind(&CCastleInterface::showAll,owner,screen,true); + } + else if(hero) + { + highlight = true; + owner->showAll(); + } + else if(other->hero, other->highlight) + { + other->highlight = highlight = false; + LOCPLINT->cb->swapGarrisonHero(owner->town); + } + hover(false);hover(true); //refresh statusbar + } +} +void CHeroGSlot::activate() +{ + ClickableL::activate(); + ClickableR::activate(); + Hoverable::activate(); +} +void CHeroGSlot::deactivate() +{ + ClickableL::deactivate(); + ClickableR::deactivate(); + Hoverable::deactivate(); +} +void CHeroGSlot::show() +{ + if(hero) //there is hero + blitAt(graphics->portraitLarge[hero->portrait],pos); + else if(!upg) //up garrison + blitAt((static_cast(LOCPLINT->curint))->flag->ourImages[(static_cast(LOCPLINT->curint))->town->getOwner()].bitmap,pos); + if(highlight) + blitAt(graphics->bigImgs[-1],pos); +} +CHeroGSlot::CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h, CCastleInterface * Owner) +{ + owner = Owner; + pos.x = x; + pos.y = y; + pos.w = 58; + pos.h = 64; + hero = h; + upg = updown; + highlight = false; +} +CHeroGSlot::~CHeroGSlot() +{ +} std::string getBgName(int type) //TODO - co z tym zrobiæ? { switch (type) @@ -213,6 +325,7 @@ public: } srthlp ; CCastleInterface::CCastleInterface(const CGTownInstance * Town, bool Activate) +:hslotup(241,387,0,Town->garrisonHero,this),hslotdown(241,483,1,Town->visitingHero,this) { hall = NULL; townInt = BitmapHandler::loadBitmap("TOWNSCRN.bmp"); @@ -375,7 +488,7 @@ void CCastleInterface::enterHall() hallInt->activate(); hallInt->show(); } -void CCastleInterface::showAll(SDL_Surface * to) +void CCastleInterface::showAll( SDL_Surface * to/*=NULL*/, bool forceTotalRedraw /*= false*/) { if (!to) to=screen; @@ -445,11 +558,15 @@ void CCastleInterface::showAll(SDL_Surface * to) pom++; blitAt(graphics->bigTownPic->ourImages[pom].bitmap,15,387,to); - //flag - if(town->getOwner()ourImages[town->getOwner()].bitmap,241,387,to); + hslotup.show(); + hslotdown.show(); + pom=false; + if(forceTotalRedraw && !showing) + pom = showing = true; show(); + if(pom) + showing = false; } void CCastleInterface::townChange() { @@ -466,7 +583,7 @@ void CCastleInterface::show(SDL_Surface * to) if (!to) to=screen; count++; - if(count==4) + if(count==8) { count=0; animval++; @@ -503,6 +620,8 @@ void CCastleInterface::activate() split->activate(); for(int i=0;iactivate(); + hslotdown.activate(); + hslotup.activate(); } void CCastleInterface::deactivate() { @@ -513,6 +632,8 @@ void CCastleInterface::deactivate() split->deactivate(); for(int i=0;ideactivate(); + hslotdown.deactivate(); + hslotup.deactivate(); } void CCastleInterface::addBuilding(int bid) diff --git a/CCastleInterface.h b/CCastleInterface.h index 4e1ec91f7..324940945 100644 --- a/CCastleInterface.h +++ b/CCastleInterface.h @@ -28,6 +28,24 @@ public: void mouseMoved (SDL_MouseMotionEvent & sEvent); }; +class CHeroGSlot : public ClickableL, public ClickableR, public Hoverable +{ +public: + CCastleInterface *owner; + const CGHeroInstance *hero; + int upg; //0 - up garrison, 1 - down garrison + bool highlight; + + void hover (bool on); + void clickRight (boost::logic::tribool down); + void clickLeft(boost::logic::tribool down); + void activate(); + void deactivate(); + void show(); + CHeroGSlot(int x, int y, int updown, const CGHeroInstance *h,CCastleInterface * Owner); + ~CHeroGSlot(); +}; + class CCastleInterface : public IShowable, public IActivable { public: @@ -44,6 +62,7 @@ public: CDefEssential* bicons; //150x70 buildings imgs CTownList * townlist; + CHeroGSlot hslotup, hslotdown; CGarrisonInt * garr; AdventureMapButton *exit; AdventureMapButton *split; @@ -54,7 +73,7 @@ public: ~CCastleInterface(); void townChange(); void show(SDL_Surface * to=NULL); - void showAll(SDL_Surface * to=NULL); + void showAll(SDL_Surface * to=NULL, bool forceTotalRedraw = false); void buildingClicked(int building); void enterHall(); void close(); diff --git a/CGameInterface.h b/CGameInterface.h index b2acb6b89..6d27ce018 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -59,6 +59,7 @@ public: virtual void garrisonChanged(const CGObjectInstance * obj){}; virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector &skills, boost::function &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id + virtual void heroInGarrisonChange(const CGTownInstance *town){}; //battle call-ins virtual void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right virtual void battlefieldPrepared(int battlefieldType, std::vector obstacles){}; //called when battlefield is prepared, prior the battle beginning diff --git a/CGameState.cpp b/CGameState.cpp index 92d2118e7..20d665843 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -431,6 +431,27 @@ void CGameState::applyNL(IPack * pack) static_cast(map->objects[sac->tid])->strInfo.creatures = sac->creatures; break; } + case 508: + { + SetHeroesInTown *sac = static_cast(pack); + CGTownInstance *t = getTown(sac->tid); + CGHeroInstance *v = getHero(sac->visiting), *g = getHero(sac->garrison); + t->visitingHero = v; + t->garrisonHero = g; + if(v) + { + v->visitedTown = t; + v->inTownGarrison = false; + map->addBlockVisTiles(v); + } + if(g) + { + g->visitedTown = t; + g->inTownGarrison = true; + map->removeBlockVisTiles(g); + } + break; + } case 1001://set object property { SetObjectProperty *p = static_cast(pack); diff --git a/CHeroWindow.cpp b/CHeroWindow.cpp index a9cf74f03..1072c2535 100644 --- a/CHeroWindow.cpp +++ b/CHeroWindow.cpp @@ -518,7 +518,7 @@ void CHeroWindow::quit() } deactivate(); - LOCPLINT->adventureInt->activate(); + LOCPLINT->curint->activate(); SDL_FreeSurface(curBack); curBack = NULL; @@ -544,7 +544,7 @@ void CHeroWindow::quit() void CHeroWindow::activate() { - LOCPLINT->curint = this; + //LOCPLINT->curint = this; quitButton->activate(); dismissButton->activate(); questlogButton->activate(); diff --git a/CHeroWindow.h b/CHeroWindow.h index 34cfb8b2e..b5c00d691 100644 --- a/CHeroWindow.h +++ b/CHeroWindow.h @@ -91,9 +91,6 @@ class CHeroWindow: public IActivable, public IShowable, public virtual CIntObjec CDefHandler *flags; //buttons - AdventureMapButton * quitButton, * dismissButton, * questlogButton, //general - * gar1button, * gar2button, * gar3button, //garrison / formation handling - * leftArtRoll, * rightArtRoll; AdventureMapButton * gar4button; //splitting //std::vector< AdventureMapButton * > heroList; //list of heroes std::vector heroListMi; //new better list of heroes @@ -114,6 +111,9 @@ class CHeroWindow: public IActivable, public IShowable, public virtual CIntObjec LRClickableAreaWText * spellPointsArea; std::vector secSkillAreas; public: + AdventureMapButton * quitButton, * dismissButton, * questlogButton, //general + * gar1button, * gar2button, * gar3button, //garrison / formation handling + * leftArtRoll, * rightArtRoll; int player; CHeroWindow(int playerColor); //c-tor ~CHeroWindow(); //d-tor diff --git a/CLua.cpp b/CLua.cpp index 80245ef9b..b650876bd 100644 --- a/CLua.cpp +++ b/CLua.cpp @@ -291,12 +291,12 @@ void CVisitableOPH::onNAHeroVisit(int objid, int heroID, bool alreadyVisited) } case 100: //give 1000 exp { - cb->changePrimSkill(heroID,w,vvv); InfoWindow iw; iw.components.push_back(Component(0,4,vvv,0)); iw.player = cb->getHeroOwner(heroID); iw.text << std::pair(11,ot); cb->showInfoDialog(&iw); + cb->changePrimSkill(heroID,w,vvv); break; } } diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index 50b6bd6e1..3132b3df1 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -137,8 +137,9 @@ void CGarrisonSlot::clickRight (tribool down) pom->luck = h->getCurrentLuck(); pom->morale = h->getCurrentMorale(); } - (new CCreInfoWindow(creature->idNumber,0,pom,boost::function(),boost::function(),NULL)) + (new CCreInfoWindow(creature->idNumber,0,count,pom,boost::function(),boost::function(),NULL)) ->activate(); + //LOCPLINT->curint->deactivate(); } delete pom; } @@ -160,16 +161,18 @@ void CGarrisonSlot::clickLeft(tribool down) if(pom.oldID>=0) { (new CCreInfoWindow - (creature->idNumber,1,NULL, + (creature->idNumber,1,count,NULL, boost::bind(&CCallback::upgradeCreature,LOCPLINT->cb,getObj(),ID,pom.newID[0]), //if upgrade is possible we'll bind proper function in callback boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID),&pom)) ->activate(); + LOCPLINT->curint->deactivate(); } else { (new CCreInfoWindow - (creature->idNumber,1,NULL,0, boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID),NULL) ) + (creature->idNumber,1,count,NULL,0, boost::bind(&CCallback::dismissCreature,LOCPLINT->cb,getObj(),ID),NULL) ) ->activate(); + LOCPLINT->curint->deactivate(); } owner->highlighted = NULL; show(); @@ -387,6 +390,8 @@ void CGarrisonInt::deleteSlots() delete (*sup)[i]; } } + delete sup; + sup = NULL; } if(sdown) { @@ -397,6 +402,8 @@ void CGarrisonInt::deleteSlots() delete (*sdown)[i]; } } + delete sdown; + sdown = NULL; } } void CGarrisonInt::recreateSlots() @@ -484,6 +491,7 @@ void CInfoWindow::close() { deactivate(); delete this; + LOCPLINT->showingDialog->setn(false); } void CInfoWindow::show(SDL_Surface * to) { @@ -494,8 +502,11 @@ void CInfoWindow::show(SDL_Surface * to) CInfoWindow::~CInfoWindow() { - for (int i=0;i(false); } CPlayerInterface::~CPlayerInterface() { delete pim; + delete showingDialog; } void CPlayerInterface::init(ICallback * CB) { @@ -1929,11 +1942,53 @@ void CPlayerInterface::showSelDialog(std::string &text, std::vector } void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector& skills, boost::function &callback) { + { + boost::unique_lock un(showingDialog->mx); + while(showingDialog->data) + showingDialog->cond.wait(un); + } boost::unique_lock un(*pim); CLevelWindow *lw = new CLevelWindow(hero,pskill,skills,callback); curint->deactivate(); lw->activate(); } +void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) +{ + boost::unique_lock un(*pim); + //redraw infowindow + SDL_FreeSurface(graphics->townWins[town->subID]); + graphics->townWins[town->subID] = infoWin(town); + if(town->garrisonHero) + { + CGI->mh->hideObject(town->garrisonHero); + for(int i=0; iheroList.items.size();i++) + { + if(adventureInt->heroList.items[i].first == town->garrisonHero) + { + adventureInt->heroList.items.erase(adventureInt->heroList.items.begin()+i); + if(adventureInt->heroList.selected >= adventureInt->heroList.items.size()) + adventureInt->heroList.selected--; + break; + } + } + } + if(town->visitingHero) + { + CGI->mh->printObject(town->visitingHero); + adventureInt->heroList.items.push_back(std::pair(town->visitingHero,NULL)); + } + + CCastleInterface *c = dynamic_cast(curint); + if(c) + { + c->garr->highlighted = NULL; + c->hslotup.hero = town->garrisonHero; + c->garr->odown = c->hslotdown.hero = town->visitingHero; + c->garr->set2 = town->visitingHero ? &town->visitingHero->army : NULL; + c->garr->recreateSlots(); + c->showAll(); + } +} void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) { boost::unique_lock un(*pim); @@ -2098,6 +2153,7 @@ void CPlayerInterface::showInfoDialog(std::string &text, std::vector } void CPlayerInterface::showInfoDialog(std::string &text, std::vector & components) { + showingDialog->set(true); curint->deactivate(); //dezaktywacja starego interfejsu std::vector > > pom; @@ -2108,18 +2164,24 @@ void CPlayerInterface::showInfoDialog(std::string &text, std::vectoractivate(); LOCPLINT->objsToBlit.push_back(temp); } -void CPlayerInterface::showYesNoDialog(std::string &text, std::vector & components, CFunctionList onYes, CFunctionList onNo, bool deactivateCur) +void CPlayerInterface::showYesNoDialog(std::string &text, std::vector & components, CFunctionList onYes, CFunctionList onNo, bool deactivateCur, bool DelComps) { if(deactivateCur) curint->deactivate(); //dezaktywacja starego interfejsu std::vector > > pom; - pom.push_back(std::pair >("IOKAY.DEF",onYes)); - pom.push_back(std::pair >("ICANCEL.DEF",onNo)); + pom.push_back(std::pair >("IOKAY.DEF",0)); + pom.push_back(std::pair >("ICANCEL.DEF",0)); CInfoWindow * temp = new CInfoWindow(text,playerID,32,components,pom); - if(onYes) - temp->buttons[0]->callback += boost::bind(&CInfoWindow::close,temp); - if(onNo) - temp->buttons[1]->callback += boost::bind(&CInfoWindow::close,temp); + temp->delComps = DelComps; + for(int i=0;ibuttons[0]->callback += onYes.funcs[i]; + for(int i=0;ibuttons[1]->callback += onNo.funcs[i]; + + //if(onYes) + // temp->buttons[0]->callback += boost::bind(&CInfoWindow::close,temp); + //if(onNo) + // temp->buttons[1]->callback += boost::bind(&CInfoWindow::close,temp); temp->activate(); LOCPLINT->objsToBlit.push_back(temp); } @@ -2141,7 +2203,7 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero) { adventureInt->heroWindow->setHero(hero); this->objsToBlit.push_back(adventureInt->heroWindow); - adventureInt->hide(); + curint->deactivate(); adventureInt->heroWindow->activate(); } CStatusBar::CStatusBar(int x, int y, std::string name, int maxw) @@ -2797,7 +2859,7 @@ void CRecrutationWindow::show(SDL_Surface * to) curx = pos.x + 192 + 102 - (102*creatures.size()/2) - (18*(creatures.size()-1)/2); for(int i=0;iblitPic(screen,curx-50,pos.y+130-65,!(c%2)); + creatures[i].pic->blitPic(screen,curx-50,pos.y+130-65,!(c%4)); curx += 120; } c++; @@ -2966,8 +3028,11 @@ void CCreInfoWindow::show(SDL_Surface * to) { char pom[15]; blitAt(bitmap,pos.x,pos.y,screen); - anim->blitPic(screen,pos.x+21,pos.y+48,(type) && anf%4); - anf++; + anim->blitPic(screen,pos.x+21,pos.y+48,(type) && !(anf%4)); + if(++anf==4) + anf=0; + if(count.size()) + printTo(count.c_str(),pos.x+114,pos.y+174,GEOR16,zwykly); if(upgrade) upgrade->show(); if(dismiss) @@ -2976,9 +3041,11 @@ void CCreInfoWindow::show(SDL_Surface * to) ok->show(); } -CCreInfoWindow::CCreInfoWindow(int Cid, int Type, StackState *State, boost::function Upg, boost::function Dsm, UpgradeInfo *ui) +CCreInfoWindow::CCreInfoWindow(int Cid, int Type, int creatureCount, StackState *State, boost::function Upg, boost::function Dsm, UpgradeInfo *ui) :ok(0),dismiss(0),upgrade(0),type(Type),dsm(Dsm),dependant(0) { + active = false; + anf = 0; c = &CGI->creh->creatures[Cid]; bitmap = BitmapHandler::loadBitmap("CRSTKPU.bmp"); pos.x = screen->w/2 - bitmap->w/2; @@ -2991,6 +3058,13 @@ CCreInfoWindow::CCreInfoWindow(int Cid, int Type, StackState *State, boost::func if(!type) anim->anim->setType(1); char pom[25];int hlp=0; + + if(creatureCount) + { + SDL_itoa(creatureCount,pom,10); + count = pom; + } + printAtMiddle(c->namePl,149,30,GEOR13,zwykly,bitmap); //creature name //atttack @@ -3063,24 +3137,41 @@ CCreInfoWindow::CCreInfoWindow(int Cid, int Type, StackState *State, boost::func { if(Upg && ui) { + for(std::set >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) //calculate upgrade cost + { + upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second*creatureCount)); + } + CFunctionList fs[2]; fs[0] += Upg; fs[0] += boost::bind(&CCreInfoWindow::close,this); - std::vector upgResCost; - for(std::set >::iterator i=ui->cost[0].begin(); i!=ui->cost[0].end(); i++) + + CCastleInterface *pom; + if(pom=dynamic_cast(LOCPLINT->curint)) //if town screen is opened it needs to be redrawn { - upgResCost.push_back(new SComponent(SComponent::resource,i->first,i->second)); //will be deleted by CInfoWindow::close + fs[1] += boost::bind(&CCastleInterface::showAll,pom,screen,true); } - boost::function fff = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[207],upgResCost,fs[0],fs[1],false); - upgrade = new AdventureMapButton("",CGI->preth->zelp[446].second,fff,pos.x+76,pos.y+237,"IVIEWCR.DEF"); + fs[1] += boost::bind(&CCreInfoWindow::activate,this); + CFunctionList cfl = boost::bind(&CCreInfoWindow::deactivate,this); + cfl += boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[207],boost::ref(upgResCost),fs[0],fs[1],false,false); + upgrade = new AdventureMapButton("",CGI->preth->zelp[446].second,cfl,pos.x+76,pos.y+237,"IVIEWCR.DEF"); } if(Dsm) { CFunctionList fs[2]; - fs[0] += Dsm; - fs[0] += boost::bind(&CCreInfoWindow::close,this); - boost::function fff = boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector(),fs[0],fs[1],false); - dismiss = new AdventureMapButton("",CGI->preth->zelp[445].second,fff,pos.x+21,pos.y+237,"IVIEWCR2.DEF"); + //on dismiss confirmed + fs[0] += Dsm; //dismiss + fs[0] += boost::bind(&CCreInfoWindow::close,this);//close this window + + CCastleInterface *pom; + if(pom=dynamic_cast(LOCPLINT->curint)) //if town screen is opened it needs to be redrawn + { + fs[1] += boost::bind(&CCastleInterface::showAll,pom,screen,true); + } + fs[1] += boost::bind(&CCreInfoWindow::activate,this); + CFunctionList cfl = boost::bind(&CCreInfoWindow::deactivate,this); + cfl += boost::bind(&CPlayerInterface::showYesNoDialog,LOCPLINT,CGI->generaltexth->allTexts[12],std::vector(),fs[0],fs[1],false,false); + dismiss = new AdventureMapButton("",CGI->preth->zelp[445].second,cfl,pos.x+21,pos.y+237,"IVIEWCR2.DEF"); } ok = new AdventureMapButton("",CGI->preth->zelp[445].second,boost::bind(&CCreInfoWindow::close,this),pos.x+216,pos.y+237,"IOKAY.DEF"); } @@ -3096,9 +3187,13 @@ CCreInfoWindow::~CCreInfoWindow() delete upgrade; delete ok; delete dismiss; + for(int i=0; iobjsToBlit.push_back(this); @@ -3108,8 +3203,6 @@ void CCreInfoWindow::activate() dismiss->activate(); if(upgrade) upgrade->activate(); - if(type) - LOCPLINT->curint->deactivate(); } void CCreInfoWindow::close() { @@ -3119,7 +3212,6 @@ void CCreInfoWindow::close() if(type) LOCPLINT->curint->activate(); delete this; - } void CCreInfoWindow::clickRight(boost::logic::tribool down) { @@ -3137,6 +3229,8 @@ void CCreInfoWindow::keyPressed (SDL_KeyboardEvent & key) } void CCreInfoWindow::deactivate() { + if(!active) return; + active = false; if(!type) ClickableR::deactivate(); LOCPLINT->objsToBlit.erase(std::find(LOCPLINT->objsToBlit.begin(),LOCPLINT->objsToBlit.end(),this)); diff --git a/CPlayerInterface.h b/CPlayerInterface.h index c64576bb7..c967f5941 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -24,6 +24,8 @@ class CCreatureSet; class CGObjectInstance; class CSlider; struct UpgradeInfo; +template struct CondSh; + namespace boost { class mutex; @@ -158,8 +160,9 @@ public: }; class CInfoWindow : public CSimpleWindow //text + comp. + ok button -{ //window deletes its components when closed +{ //window able to delete its components when closed public: + bool delComps; //whether comps will be deleted std::vector buttons; std::vector components; virtual void close(); @@ -303,6 +306,7 @@ class CPlayerInterface : public CGameInterface { public: //minor interfaces + CondSh *showingDialog; boost::mutex *pim; bool makingTurn; SDL_Event * current; @@ -311,7 +315,6 @@ public: CCastleInterface * castleInt; FPSmanager * mainFPSmng; IStatusBar *statusbar; - //to commucate with engine CCallback * cb; @@ -339,6 +342,7 @@ public: void garrisonChanged(const CGObjectInstance * obj); void buildChanged(const CGTownInstance *town, int buildingID, int what); //what: 1 - built, 2 - demolished void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector &skills, boost::function &callback); + void heroInGarrisonChange(const CGTownInstance *town); //for battles void battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right void battlefieldPrepared(int battlefieldType, std::vector obstacles); //called when battlefield is prepared, prior the battle beginning @@ -367,7 +371,7 @@ public: int3 repairScreenPos(int3 pos); void removeObjToBlit(IShowable* obj); void showInfoDialog(std::string &text, std::vector & components); - void showYesNoDialog(std::string &text, std::vector & components, CFunctionList onYes, CFunctionList onNo, bool deactivateCur); + void showYesNoDialog(std::string &text, std::vector & components, CFunctionList onYes, CFunctionList onNo, bool deactivateCur, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close CPlayerInterface(int Player, int serial);//c-tor ~CPlayerInterface();//d-tor @@ -521,17 +525,20 @@ public: class CCreInfoWindow : public IShowable, public KeyInterested, public ClickableR { public: + bool active; int type;//0 - rclick popup; 1 - normal window SDL_Surface *bitmap; char anf; + std::string count; //creature count in text format boost::function dsm; CCreaturePic *anim; CCreature *c; CInfoWindow *dependant; //it may be dialog asking whther upgrade/dismiss stack (if opened) + std::vector upgResCost; //cost of upgrade (if not possible then empty) AdventureMapButton *dismiss, *upgrade, *ok; - CCreInfoWindow(int Cid, int Type, StackState *State, boost::function Upg, boost::function Dsm, UpgradeInfo *ui); + CCreInfoWindow(int Cid, int Type, int creatureCount, StackState *State, boost::function Upg, boost::function Dsm, UpgradeInfo *ui); ~CCreInfoWindow(); void activate(); void close(); diff --git a/client/Client.cpp b/client/Client.cpp index d4fd58704..c773694af 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -337,6 +337,17 @@ void CClient::process(int what) //TODO: do we need to inform interface? break; } + case 508: + { + SetHeroesInTown inTown; + *serv >> inTown; + std::cout << "Setting heroes in town " << inTown.tid << std::endl; + gs->apply(&inTown); + CGTownInstance *t = gs->getTown(inTown.tid); + if(vstd::contains(playerint,t->tempOwner)) + playerint[t->tempOwner]->heroInGarrisonChange(t); + break; + } case 1001: { SetObjectProperty sop; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index d300bb261..c73c0739c 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -154,6 +154,16 @@ struct SetAvailableCreatures : public CPack //506 h & tid & creatures; } }; +struct SetHeroesInTown : public CPack //508 +{ + SetHeroesInTown(){type = 508;}; + si32 tid, visiting, garrison; //id of town, visiting hero, hero in garrison + + template void serialize(Handler &h, const int version) + { + h & tid & visiting & garrison; + } +}; struct NewTurn : public CPack //101 { struct Hero diff --git a/mapHandler.cpp b/mapHandler.cpp index e6ebe8491..1b2fd5d0f 100644 --- a/mapHandler.cpp +++ b/mapHandler.cpp @@ -1107,7 +1107,7 @@ std::string CMapHandler::getDefName(int id, int subid) #endif } -bool CMapHandler::printObject(CGObjectInstance *obj) +bool CMapHandler::printObject(const CGObjectInstance *obj) { CDefHandler * curd = obj->defInfo->handler; for(int fx=0; fxourImages[0].bitmap->w/32; ++fx) @@ -1119,7 +1119,7 @@ bool CMapHandler::printObject(CGObjectInstance *obj) cr.h = 32; cr.x = fx*32; cr.y = fy*32; - std::pair toAdd = std::make_pair(obj, cr); + std::pair toAdd = std::make_pair(obj, cr); if((obj->pos.x + fx - curd->ourImages[0].bitmap->w/32+1)>=0 && (obj->pos.x + fx - curd->ourImages[0].bitmap->w/32+1)pos.y + fy - curd->ourImages[0].bitmap->h/32+1)>=0 && (obj->pos.y + fy - curd->ourImages[0].bitmap->h/32+1)defInfo->handler; for(int fx=0; fxourImages[0].bitmap->w/32; ++fx) diff --git a/mapHandler.h b/mapHandler.h index e2e2eaf3b..d018bd219 100644 --- a/mapHandler.h +++ b/mapHandler.h @@ -86,8 +86,8 @@ public: //std::vector< CGObjectInstance * > getVisitableObjs(int3 pos); //returns vector of visitable objects at certain position CGObjectInstance * createObject(int id, int subid, int3 pos, int owner=254); //creates a new object with a certain id and subid std::string getDefName(int id, int subid); //returns name of def for object with given id and subid - bool printObject(CGObjectInstance * obj); //puts appropriate things to ttiles, so obj will be visible on map - bool hideObject(CGObjectInstance * obj); //removes appropriate things from ttiles, so obj will be no longer visible on map (but still will exist) + bool printObject(const CGObjectInstance * obj); //puts appropriate things to ttiles, so obj will be visible on map + bool hideObject(const CGObjectInstance * obj); //removes appropriate things from ttiles, so obj will be no longer visible on map (but still will exist) bool removeObject(CGObjectInstance * obj); //removes object from each place in VCMI (I hope) void init(); void calculateBlockedPos(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 355fd94f8..58e038004 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -666,6 +666,72 @@ void CGameHandler::handleConnection(std::set players, CConnection &c) upgend: break; } + case 508: //garrison swap + { + si32 tid; + c >> tid; + CGTownInstance *town = gs->getTown(tid); + if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies + { + CCreatureSet csn = town->visitingHero->army, cso = town->army; + while(!cso.slots.empty())//while there are unmoved creatures + { + int pos = csn.getSlotFor(cso.slots.begin()->first); + if(pos<0) + goto handleConEnd; + if(csn.slots.find(pos)!=csn.slots.end()) //add creatures to the existing stack + { + csn.slots[pos].second += cso.slots.begin()->second.second; + } + else //move stack on the free pos + { + csn.slots[pos].first = cso.slots.begin()->second.first; + csn.slots[pos].second = cso.slots.begin()->second.second; + } + cso.slots.erase(cso.slots.begin()); + } + SetGarrisons sg; + sg.garrs[town->visitingHero->id] = csn; + sg.garrs[town->id] = csn; + sendAndApply(&sg); + + SetHeroesInTown intown; + intown.tid = tid; + intown.visiting = -1; + intown.garrison = town->visitingHero->id; + sendAndApply(&intown); + } + else if (town->garrisonHero && !town->visitingHero) //move hero out of the garrison + { + //town will be empty + SetGarrisons sg; + sg.garrs[tid] = CCreatureSet(); + sendAndApply(&sg); + + SetHeroesInTown intown; + intown.tid = tid; + intown.garrison = -1; + intown.visiting = town->garrisonHero->id; + sendAndApply(&intown); + } + else if (town->garrisonHero && town->visitingHero) //swap visiting and garrison hero + { + SetGarrisons sg; + sg.garrs[town->id] = town->visitingHero->army; + sendAndApply(&sg); + + SetHeroesInTown intown; + intown.tid = tid; + intown.garrison = town->visitingHero->id; + intown.visiting = town->garrisonHero->id; + sendAndApply(&intown); + } + else + { + std::cout << "Warning, wrong garrison swap command for " << tid << std::endl; + } + break; + } case 2001: { ui32 qid, answer; @@ -759,6 +825,8 @@ upgend: { end2 = true; } +handleConEnd: + ; } void CGameHandler::moveStack(int stack, int dest) {