From cebd5db8b2501b39091df29b8603c981074efb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Thu, 26 Mar 2009 23:05:40 +0000 Subject: [PATCH] * it's possible to revisit object under hero by pressing Space * splitting window allows to rebalance two stack with the same creatures * slightly improved sliders * minor improvements --- AdventureMapButton.cpp | 9 +- CAdvmapInterface.cpp | 11 ++ CGameState.cpp | 3 + CHeroWindow.cpp | 2 +- CMessage.cpp | 343 +++++++++++++++++++--------------------- CMessage.h | 32 +++- CPlayerInterface.cpp | 74 ++++++--- CPlayerInterface.h | 4 +- client/Graphics.cpp | 1 - hch/CObjectHandler.cpp | 4 +- server/CGameHandler.cpp | 68 +++++--- server/CGameHandler.h | 1 + 12 files changed, 314 insertions(+), 238 deletions(-) diff --git a/AdventureMapButton.cpp b/AdventureMapButton.cpp index 552766b4b..b5c46b12e 100644 --- a/AdventureMapButton.cpp +++ b/AdventureMapButton.cpp @@ -309,8 +309,9 @@ void CSlider::mouseMoved (const SDL_MouseMotionEvent & sEvent) if( std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2+40 || std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2 ) return; float v = sEvent.x - pos.x - 24; - v/= (pos.w - 48); v*=amount; + v/= (pos.w - 48); + v += 0.5f; if(v!=value) { moveTo(v); @@ -371,11 +372,11 @@ void CSlider::clickLeft (tribool down) { if(down) { - float pw = LOCPLINT->current->motion.x-pos.x-16; - float rw = pw / ((float)(pos.w-32)); + float pw = LOCPLINT->current->motion.x-pos.x-24; + float rw = pw / ((float)(pos.w-48)); if (rw>1) return; if (rw<0) return; - moveTo(rw*amount); + moveTo(rw*amount+0.5f); return; } if(moving) diff --git a/CAdvmapInterface.cpp b/CAdvmapInterface.cpp index 66f62f308..deba7baff 100644 --- a/CAdvmapInterface.cpp +++ b/CAdvmapInterface.cpp @@ -1535,6 +1535,17 @@ void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key) case SDLK_DOWN: Dir = DOWN; break; + case SDLK_SPACE: //space - try to revisit current object with selected hero + { + const CGHeroInstance *h = dynamic_cast(selection); + if(h && key.state == SDL_PRESSED) + { + LOCPLINT->pim->unlock(); + LOCPLINT->cb->moveHero(h,h->pos); + LOCPLINT->pim->lock(); + } + } + return; default: return; } diff --git a/CGameState.cpp b/CGameState.cpp index 7b025daab..d05142b51 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -1412,6 +1412,9 @@ void CGameState::getNeighbours(int3 tile, std::vector &vec, const boost::l int CGameState::getMovementCost(const CGHeroInstance *h, int3 src, int3 dest, int remainingMovePoints, bool checkLast) { + if(src == dest) //same tile + return 0; + TerrainTile &s = map->terrain[src.x][src.y][src.z], &d = map->terrain[dest.x][dest.y][dest.z]; diff --git a/CHeroWindow.cpp b/CHeroWindow.cpp index e463f1cc7..2b65d01f3 100644 --- a/CHeroWindow.cpp +++ b/CHeroWindow.cpp @@ -88,7 +88,7 @@ CHeroWindow::CHeroWindow(int playerColor): primSkillAreas[v]->pos.y = pos.y + 111; primSkillAreas[v]->pos.w = 42; primSkillAreas[v]->pos.h = 42; - primSkillAreas[v]->text = CGI->generaltexth->arraytxt[2+v].substr(1, CGI->generaltexth->arraytxt[2+v].size()-2); + primSkillAreas[v]->text = CGI->generaltexth->arraytxt[2+v]; primSkillAreas[v]->type = v; primSkillAreas[v]->bonus = -1; // to be initilized when hero is being set primSkillAreas[v]->baseType = 0; diff --git a/CMessage.cpp b/CMessage.cpp index 56f2288ca..253fef28d 100644 --- a/CMessage.cpp +++ b/CMessage.cpp @@ -21,6 +21,11 @@ extern SDL_Surface * screen; extern TTF_Font * TNRB16, *TNR, *GEOR13; using namespace NMessage; + +const int COMPONENT_TO_SUBTITLE = 5; +const int BETWEEN_COMPS_ROWS = 10; +const int BEFORE_COMPONENTS = 30; + template std::pair max(const std::pair &x, const std::pair &y) { std::pair ret; @@ -36,11 +41,7 @@ namespace NMessage SDL_Surface * background = NULL; } -CMessage::CMessage() -{ - //if (!NMessage::background) - // init(); -} + void CMessage::init() { { @@ -160,26 +161,6 @@ std::vector * CMessage::breakText(std::string text, size_t line, bo } return ret; } -std::pair CMessage::getMaxSizes(std::vector< std::vector > * komp) -{ - std::pair ret; - for (size_t i=0;isize();i++) - { - int sumaw=0; - int maxh=0; - for(size_t j=0;j<(*komp)[i].size();j++) - { - sumaw += (*komp)[i][j]->getImg()->w; - if (maxh < (*komp)[i][j]->getImg()->h) - maxh = (*komp)[i][j]->getImg()->h; - } - if(sumaw>ret.first) - ret.first = sumaw; - ret.second+=maxh; - } - - return ret; -} std::pair CMessage::getMaxSizes(std::vector > * txtg) { @@ -201,15 +182,16 @@ std::pair CMessage::getMaxSizes(std::vector > } return ret; } -SDL_Surface * CMessage::blitTextOnSur(std::vector > * txtg, int & curh, SDL_Surface * ret) +SDL_Surface * CMessage::blitTextOnSur(std::vector > * txtg, int & curh, SDL_Surface * ret, int xCenterPos) { for (size_t i=0; isize();i++) { - int lw=0; + int lw=0; //line width for (size_t j=0;j<(*txtg)[i].size();j++) - lw+=(*txtg)[i][j]->w; //lw - laczna szerokosc linii - int pw = ret->w/2; - pw -= lw/2; //poczatek tekstu (x) + lw+=(*txtg)[i][j]->w; + + int pw = (xCenterPos < 0) ? ret->w/2 : xCenterPos; + pw -= lw/2; //x coord for the start of the text int tw = pw; for (size_t j=0;j<(*txtg)[i].size();j++) //blit text @@ -217,84 +199,15 @@ SDL_Surface * CMessage::blitTextOnSur(std::vector > * blitAt((*txtg)[i][j],tw,curh+i*19,ret); tw+=(*txtg)[i][j]->w; SDL_FreeSurface((*txtg)[i][j]); + (*txtg)[i][j] = NULL; } } curh+=txtg->size()*19; return ret; } -SDL_Surface * CMessage::blitCompsOnSur(std::vector & comps, int maxw, int inter, int & curh, SDL_Surface * ret) -{ - std::vector * brdtext; - if (comps.size()) - { - brdtext = breakText(comps[0]->subtitle,12,true,true); - } - else - { - brdtext = NULL; - } - comps[0]->pos.x = (ret->w/2) - ((comps[0]->getImg()->w)/2); - comps[0]->pos.y = curh; - blitAt(comps[0]->getImg(),comps[0]->pos.x,comps[0]->pos.y,ret); - curh += comps[0]->getImg()->h + 5; //obrazek + przerwa - for (size_t i=0; i < brdtext->size(); ++i) //descr. - { - SDL_Surface * tesu = TTF_RenderText_Blended(GEOR13,(*brdtext)[i].c_str(),zwykly); - blitAt(tesu,((comps[0]->getImg()->w - tesu->w)/2)+comps[0]->pos.x,curh,ret); - curh+=tesu->h; - SDL_FreeSurface(tesu); - } - return ret; -} -SDL_Surface* CMessage::blitCompsOnSur(SDL_Surface * _or, std::vector< std::vector > * komp, int inter, int &curh, SDL_Surface *ret) -{ - for (size_t i=0;isize();i++) - { - int totalw=0, maxh=0; - for(size_t j=0;j<(*komp)[i].size();j++) - { - totalw+=(*komp)[i][j]->getImg()->w; - if(maxh<(*komp)[i][j]->getImg()->h) - { - maxh=(*komp)[i][j]->getImg()->h; - } - } - if(_or) - { - totalw += (inter*2+_or->w) * ((*komp)[i].size() - 1); - } - else - { - totalw += (inter) * ((*komp)[i].size() - 1); - } - - curh+=maxh/2; - int curw = (ret->w/2)-(totalw/2); - for(size_t j=0;j<(*komp)[i].size();j++) - { - blitAt((*komp)[i][j]->getImg(),curw,curh-((*komp)[i][j]->getImg()->h/2),ret); - (*komp)[i][j]->pos.x = curw; - (*komp)[i][j]->pos.y = curh-((*komp)[i][j]->getImg()->h/2); - CSDL_Ext::printAtMiddle((*komp)[i][j]->subtitle,curw+(*komp)[i][j]->getImg()->w/2,curh+((*komp)[i][j]->getImg()->h/2)+10,GEOR13,zwykly,ret); - curw += (*komp)[i][j]->getImg()->w; - if(j<((*komp)[i].size()-1)) - { - if(_or) - { - curw+=inter; - blitAt(_or,curw,curh-(_or->h/2),ret); - curw+=_or->w; - } - curw+=inter; - } - } - curh+=maxh/2; - curh += 20; //todo: check subtitle length - } - return ret; -} -std::vector > * CMessage::drawText(std::vector * brtext) +std::vector > * CMessage::drawText(std::vector * brtext, TTF_Font *font) { + if(!font) font = TNRB16; std::vector > * txtg = new std::vector >(); txtg->resize(brtext->size()); for (size_t i=0; isize();i++) //foreach line @@ -314,7 +227,7 @@ std::vector > * CMessage::drawText(std::vector > * CMessage::drawText(std::vectorsize();i++) @@ -345,26 +258,6 @@ CSimpleWindow * CMessage::genWindow(std::string text, int player, int Lmar, int delete txtg; return ret; } -std::vector< std::vector > * CMessage::breakComps(std::vector & comps,int maxw, SDL_Surface* _or) -{ - std::vector< std::vector > * ret = new std::vector< std::vector >(); - ret->resize(1); - int rvi = 0; - int curw = 0; - for(size_t i=0;igetImg()->w + 12 + (_or ? _or->w : 0)); - if (curw > maxw) - { - curw = 0; - rvi++; - ret->resize(rvi+1); - } - (*ret)[rvi].push_back(comps[i]); - } - return ret; -} - SDL_Surface * CMessage::drawBoxTextBitmapSub( int player, std::string text, SDL_Surface* bitmap, std::string sub, int charperline/*=30*/, int imgToBmp/*=55*/ ) { int curh; @@ -392,19 +285,34 @@ SDL_Surface * CMessage::drawBoxTextBitmapSub( int player, std::string text, SDL_ return ret; } + + + + void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int charperline) { - std::vector * brtext = breakText(text,charperline,true,true); + SDL_Surface * _or = NULL; + if(dynamic_cast(ret)) //it's selection window, so we'll blit "or" between components + _or = TTF_RenderText_Blended(GEOR13,CGI->generaltexth->allTexts[4].c_str(),zwykly); + + std::vector * brtext = breakText(text,charperline,true,true); //text std::vector > * txtg = drawText(brtext); std::pair txts = getMaxSizes(txtg); + + ComponentsToBlit comps(ret->components,500,_or); + if(ret->buttons.size()) txts.second += 20 + //before button ok->ourImages[0].bitmap->h; //button + if (ret->components.size()) - txts.second += 30 //space to first component - + ret->components[0]->getImg()->h - + 5 //img <-> subtitle - + 20; //subtitle //TODO: check how much place will be needed for subtitle + { + txts.second += 30 + comps.h; //space to first component + + } + + amax(txts.first,comps.w); + ret->bitmap = drawBox1(txts.first+70,txts.second+70,0); ret->pos.h=ret->bitmap->h; ret->pos.w=ret->bitmap->w; @@ -412,22 +320,11 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int ret->pos.y=screen->h/2-(ret->pos.h/2); int curh = 30; //gorny margines blitTextOnSur(txtg,curh,ret->bitmap); + if (ret->components.size()) { - curh += 30; - if(ret->components.size()==1) - { - blitCompsOnSur(ret->components,200,0,curh,ret->bitmap); - } - else - { - SDL_Surface * _or = 0; - if(dynamic_cast(ret)) //it's selection window, so we'll blit "or" between components - _or = TTF_RenderText_Blended(GEOR13,CGI->generaltexth->allTexts[4].c_str(),zwykly); - std::vector< std::vector > * komp = breakComps(reinterpret_cast&>(ret->components),500,_or); - blitCompsOnSur(_or,komp,10,curh,ret->bitmap); - delete komp; - } + curh += BEFORE_COMPONENTS; + comps.blitCompsOnSur(_or, 10, curh, ret->bitmap); } if(ret->buttons.size()) { @@ -450,38 +347,8 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, int player, int } delete brtext; delete txtg; -} -CSelWindow * CMessage::genSelWindow(std::string text, int player, int charperline, std::vector & comps, int owner) -{ - //CSelWindow * ret = new CSelWindow(); - //std::vector * tekst = breakText(text,charperline); - //std::vector > * txtg = drawText(tekst); - //std::pair txts = getMaxSizes(txtg); - //txts.first+=45; //side margins - //int curh = 50; //top margin - ////std::pair txts2 = getMaxSizes(komp); - //ret->pos.h = txts.second //wys. tekstu - // //+ txts2.second //wys komponentow - // + 20 //podpis pod komponentami - // + 55 //gorny margines - // + 60 //text <=> comps - // + 20 //comps <=> button - // + ok->ourImages[0].bitmap->h //button - // + 30; //bottom margin - //ret->pos.w = std::max(txts.first,txts.second); - //ret->bitmap = drawBox1(ret->pos.w,ret->pos.h,player); - //blitTextOnSur(txtg,curh,ret->bitmap); - //curh += 50; - //blitCompsOnSur(_or,komp,10,curh,ret->bitmap); - //curh += 30; //to buttton - //ret->buttons[0]->pos.x = (ret->bitmap->w/2) - (ret->buttons[0]->imgs[0][0]->w/2); - //ret->buttons[0]->pos.y = curh; - //ret->buttons[0]->show(); - //curh += ret->buttons[0]->imgs[0][0]->h; - //SDL_FreeSurface(_or); - //delete komp; - //delete tekst; - return NULL; + if(_or) + SDL_FreeSurface(_or); } SDL_Surface * CMessage::genMessage @@ -513,7 +380,6 @@ SDL_Surface * CMessage::genMessage if (title.length()) { - //SDL_Surface * titleText = TTF_RenderText_Shaded(TNRB16,title.c_str(),tytulowy,tlo); SDL_Surface * titleText = TTF_RenderText_Blended(TNRB16,title.c_str(),tytulowy); //draw title @@ -526,7 +392,6 @@ SDL_Surface * CMessage::genMessage { int by = 37+i*21; if (title.length()) by+=40; - //SDL_Surface * tresc = TTF_RenderText_Shaded(TNRB16,(*tekst)[i].c_str(),zwykly,tlo); SDL_Surface * tresc = TTF_RenderText_Blended(TNRB16,(*tekst)[i].c_str(),zwykly); SDL_Rect trescRect = genRect(tresc->h,tresc->w,((ret->w/2)-(tresc->w/2)),by); SDL_BlitSurface(tresc,NULL,ret,&trescRect); @@ -577,4 +442,128 @@ void CMessage::drawBorder(int playerColor, SDL_Surface * ret, int w, int h, int (piecesOfBox[playerColor][2],NULL,ret,&genRect(piecesOfBox[playerColor][2]->h,piecesOfBox[playerColor][2]->w,x+0,y+h-piecesOfBox[playerColor][2]->h)); 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)); +} + +ComponentResolved::ComponentResolved() +{ + comp = NULL; + img = NULL; + txt = NULL; +} + +ComponentResolved::ComponentResolved( SComponent *Comp ) +{ + comp = Comp; + img = comp->getImg(); + std::vector * brtext = CMessage::breakText(comp->subtitle,11,true,true); //text + txt = CMessage::drawText(brtext,GEOR13); + delete brtext; + comp->pos.w = img->w; + comp->pos.h = img->h + COMPONENT_TO_SUBTITLE + CMessage::getMaxSizes(txt).second; +} + +ComponentResolved::~ComponentResolved() +{ + for(size_t i = 0; i < txt->size(); i++) + for(size_t j = 0; j < (*txt)[i].size(); j++) + if((*txt)[i][j]) + SDL_FreeSurface((*txt)[i][j]); + delete txt; +} + +ComponentsToBlit::~ComponentsToBlit() +{ + for(size_t i=0; i & SComps, int maxw, SDL_Surface* _or) +{ + w = h = 0; + if(!SComps.size()) + return; + + comps.resize(1); + int curw = 0; + int curr = 0; + + for(size_t i=0;igetImg()->w + 12 + (_or ? _or->w : 0)); + if (curw + toadd > maxw) + { + amax(w,curw); + curw = SComps[i]->getImg()->w; + comps.resize(curr+1); + } + else + { + curw += toadd; + } + + comps[curr].push_back(new ComponentResolved(SComps[i])); + } + + for(size_t i=0;icomp->pos.h); + h += maxh + BETWEEN_COMPS_ROWS; + } +} + +void ComponentsToBlit::blitCompsOnSur( SDL_Surface * _or, int inter, int &curh, SDL_Surface *ret ) +{ + for (size_t i=0;icomp->pos.w; + amax(maxh,cur->comp->pos.h); + } + if(_or) + { + totalw += (inter*2+_or->w) * ((comps)[i].size() - 1); + } + else + { + totalw += (inter) * ((comps)[i].size() - 1); + } + + curh+=maxh/2; + int curw = (ret->w/2)-(totalw/2); + for(size_t j=0;j<(comps)[i].size();j++) + { + ComponentResolved *cur = (comps)[i][j]; + + //blit img + int hlp = curh-(cur->comp->pos.h)/2; + blitAt(cur->img,curw,hlp,ret); + cur->comp->pos.x = curw; + cur->comp->pos.y = hlp; + + //blit subtitle + hlp += cur->img->h + COMPONENT_TO_SUBTITLE; + CMessage::blitTextOnSur(cur->txt, hlp, ret, cur->comp->pos.x + cur->comp->pos.w/2 ); + + //if there is subsequent component blit "or" + curw += cur->img->w; + if(j<((comps)[i].size()-1)) + { + if(_or) + { + curw+=inter; + blitAt(_or,curw,curh-(_or->h/2),ret); + curw+=_or->w; + } + curw+=inter; + } + } + curh+=maxh/2; + } } \ No newline at end of file diff --git a/CMessage.h b/CMessage.h index 43dc617a7..c1800b8b5 100644 --- a/CMessage.h +++ b/CMessage.h @@ -22,19 +22,36 @@ namespace NMessage extern SDL_Surface * background ; } +struct ComponentResolved +{ + SComponent *comp; + + SDL_Surface *img; + std::vector > * txt; + + ComponentResolved(); + ComponentResolved(SComponent *Comp); + ~ComponentResolved(); +}; + +struct ComponentsToBlit +{ + std::vector< std::vector > comps; + int w, h; + + void blitCompsOnSur(SDL_Surface * _or, int inter, int &curh, SDL_Surface *ret); + ComponentsToBlit(std::vector & SComps, int maxw, SDL_Surface* _or); + ~ComponentsToBlit(); +}; + class CMessage { public: static std::pair getMaxSizes(std::vector > * txtg); - static std::pair getMaxSizes(std::vector< std::vector > * komp); - static std::vector > * drawText(std::vector * brtext); - static SDL_Surface * blitTextOnSur(std::vector > * txtg, int & curh, SDL_Surface * ret); - static SDL_Surface * blitCompsOnSur(std::vector & comps, int maxw, int inter, int & curh, SDL_Surface * ret); - static SDL_Surface * blitCompsOnSur(SDL_Surface *_or, std::vector< std::vector > *komp, int inter, int &curh, SDL_Surface *ret); + static std::vector > * drawText(std::vector * brtext, TTF_Font *font = NULL); + static SDL_Surface * blitTextOnSur(std::vector > * txtg, int & curh, SDL_Surface * ret, int xCenterPos=-1); //xPos==-1 works as if ret->w/2 static void drawIWindow(CInfoWindow * ret, std::string text, int player, int charperline); - static std::vector< std::vector > * breakComps(std::vector &comps, int maxw, SDL_Surface* _or=NULL); - static CSelWindow * genSelWindow(std::string text, int player, int charperline, std::vector & comps, int owner); static CSimpleWindow * genWindow(std::string text, int player, int Lmar=35, int Rmar=35, int Tmar=35, int Bmar=35);//supports h3 text formatting; player sets color of window, Lmar/Rmar/Tmar/Bmar are Left/Right/Top/Bottom margins static SDL_Surface * genMessage(std::string title, std::string text, EWindowType type=infoOnly, std::vector *addPics=NULL, void * cb=NULL); @@ -42,7 +59,6 @@ public: static void drawBorder(int playerColor, SDL_Surface * ret, int w, int h, int x=0, int y=0); static SDL_Surface * drawBoxTextBitmapSub(int player, std::string text, SDL_Surface* bitmap, std::string sub, int charperline=30, int imgToBmp=55); static std::vector * breakText(std::string text, size_t line=30, bool userBreak=true, bool ifor=true); //line - chars per line - CMessage(); static void init(); static void dispose(); }; diff --git a/CPlayerInterface.cpp b/CPlayerInterface.cpp index d1e0d8d7e..1957588f4 100644 --- a/CPlayerInterface.cpp +++ b/CPlayerInterface.cpp @@ -217,16 +217,37 @@ void CGarrisonSlot::clickLeft(tribool down) refr = true; delete pom2; } - else if(!creature - && (owner->splitting - || SDL_GetKeyState(NULL)[SDLK_LSHIFT] - || SDL_GetKeyState(NULL)[SDLK_RSHIFT]))//split + else if((owner->splitting || LOCPLINT->shiftPressed()) + && (!creature + || (creature == owner->highlighted->creature)) + ) { - owner->p2 = ID; - owner->pb = upg; + owner->p2 = ID; //store the second stack pos + owner->pb = upg;//store the second stack owner (up or down army) owner->splitting = false; LOCPLINT->curint->deactivate(); - CSplitWindow * spw = new CSplitWindow(owner->highlighted->creature->idNumber,owner->highlighted->count, owner); + + int totalAmount = owner->highlighted->count; + if(creature) + totalAmount += count; + + int last = -1; + if(upg != owner->highlighted->upg) //not splitting within same army + { + if(owner->highlighted->getObj()->army.slots.size() == 1 + && owner->highlighted->getObj()->needsLastStack() ) + { + last = 0; + } + if(getObj()->army.slots.size() == 1 + && getObj()->needsLastStack() ) + { + last += 2; + } + } + + + CSplitWindow * spw = new CSplitWindow(owner->highlighted->creature->idNumber, totalAmount, owner, last, count); spw->activate(); refr = true; } @@ -293,25 +314,24 @@ void CGarrisonSlot::show() { if(creature) { - char* buf = new char[15]; + char buf[15]; SDL_itoa(count,buf,10); blitAt(graphics->bigImgs[creature->idNumber],pos); printToWR(buf,pos.x+56,pos.y+62,GEOR16,zwykly); - if(owner->highlighted==this) + + if((owner->highlighted==this) + || (owner->splitting && owner->highlighted->creature == creature)) + { blitAt(graphics->bigImgs[-1],pos); - //if(owner->update) - // updateRect(&pos,screen); - delete [] buf; + } } - else + else //empty slot { SDL_Rect jakis1 = genRect(pos.h,pos.w,owner->offx+ID*(pos.w+owner->interx),owner->offy+upg*(pos.h+owner->intery)), jakis2 = pos; SDL_BlitSurface(owner->sur,&jakis1,screen,&jakis2); if(owner->splitting) blitAt(graphics->bigImgs[-1],pos); - //if(owner->update) - // SDL_UpdateRect(screen,pos.x,pos.y,pos.w,pos.h); } } CGarrisonInt::~CGarrisonInt() @@ -1260,7 +1280,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details) if(adventureInt == curint) adventureInt->minimap.draw(); - if(details.style>0) + if(details.style>0 || details.src == details.dst) return; //initializing objects and performing first step of move @@ -2537,6 +2557,11 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CPath * path ) return result; } +bool CPlayerInterface::shiftPressed() const +{ + return SDL_GetKeyState(NULL)[SDLK_LSHIFT] || SDL_GetKeyState(NULL)[SDLK_RSHIFT]; +} + CStatusBar::CStatusBar(int x, int y, std::string name, int maxw) { bg=BitmapHandler::loadBitmap(name); @@ -3355,8 +3380,9 @@ CRecrutationWindow::~CRecrutationWindow() delete bar; } -CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner) +CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner, int Last, int val) { + last = Last; which = 1; c=cid; slider = NULL; @@ -3370,9 +3396,10 @@ CSplitWindow::CSplitWindow(int cid, int max, CGarrisonInt *Owner) pos.h = bitmap->h; ok = new AdventureMapButton("","",boost::bind(&CSplitWindow::split,this),pos.x+20,pos.y+263,"IOK6432.DEF",SDLK_RETURN); cancel = new AdventureMapButton("","",boost::bind(&CSplitWindow::close,this),pos.x+214,pos.y+263,"ICN6432.DEF",SDLK_ESCAPE); - slider = new CSlider(pos.x+21,pos.y+194,257,boost::bind(&CSplitWindow::sliderMoved,this,_1),1,max,0,true); - a1 = max; - a2 = 0; + int sliderPositions = max - (last>=0) - (last==2); + slider = new CSlider(pos.x+21,pos.y+194,257,boost::bind(&CSplitWindow::sliderMoved,this,_1),1,sliderPositions,val,true); + a1 = max-val; + a2 = val; anim = new CCreaturePic(&CGI->creh->creatures[cid]); anim->anim->setType(1); @@ -3419,9 +3446,10 @@ void CSplitWindow::close() } void CSplitWindow::sliderMoved(int to) { - a2 = to; + int all = a1+a2; + a2 = to + (last==1 || last==2); if(slider) - a1 = slider->amount - to; + a1 = all - a2; } void CSplitWindow::show(SDL_Surface * to) { @@ -3453,7 +3481,7 @@ void CSplitWindow::keyPressed (const SDL_KeyboardEvent & key) else { int number = key.keysym.sym - SDLK_0; - if (number < 0 || number > 9) //not a number presses + if (number < 0 || number > 9) //not a number pressed { return; } diff --git a/CPlayerInterface.h b/CPlayerInterface.h index 83e318b4a..8f2f214aa 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -563,6 +563,7 @@ public: //-------------// + bool shiftPressed() const; void redrawHeroWin(const CGHeroInstance * hero); void updateWater(); void showComp(SComponent comp); //TODO: comment me @@ -721,8 +722,9 @@ public: SDL_Surface *bitmap; //background int a1, a2, c; //TODO: comment me bool which; //TODO: comment me + int last; //0/1/2 - at least one creature must be in the src/dst/both stacks; -1 - no restrictions - CSplitWindow(int cid, int max, CGarrisonInt *Owner); //c-tor + CSplitWindow(int cid, int max, CGarrisonInt *Owner, int Last = -1, int val=0); //c-tor; val - initial amount of second stack ~CSplitWindow(); //d-tor void activate(); void split(); diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 382a429cb..e4b3fa0b5 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -408,7 +408,6 @@ void Graphics::loadHeroFlags() { using namespace boost::assign; timeHandler th; -// std::vector Graphics::*point; //TODO use me std::pair Graphics::*, std::vector > pr[4]; pr[0].first = &Graphics::flags1; pr[0].second+=("ABF01L.DEF"),("ABF01G.DEF"),("ABF01R.DEF"),("ABF01D.DEF"),("ABF01B.DEF"), diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index cbc6f8de1..7f0e97805 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -708,8 +708,8 @@ std::vector > CGHeroInstance::getCurrentMoraleModifie if(archangelInArmy) { char buf[100]; - sprintf(buf,VLC->generaltexth->arraytxt[117].c_str(),VLC->creh->creatures[13].namePl); - ret.push_back(std::pair(-1,VLC->generaltexth->arraytxt[116])); //%s in group +1 + sprintf(buf,VLC->generaltexth->arraytxt[117].c_str(),VLC->creh->creatures[13].namePl.c_str()); + ret.push_back(std::pair(-1,buf)); //%s in group +1 } } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 5547e67be..3d4de9213 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -38,9 +38,6 @@ extern bool end2; bnr.round = gs->curB->round + 1;\ sendAndApply(&bnr); - -#define COMPLAIN(text) sendMessageToAll(text);tlog1<movement-cost); //take move points BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects) { - if(obj->blockVisit) + if(obj != h && obj->blockVisit) { blockvis = true; break; @@ -1498,8 +1495,9 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s if(what==1) //swap { - std::swap(S1.slots[p1],S2.slots[p2]); + std::swap(S1.slots[p1],S2.slots[p2]); //swap slots + //if one of them is empty, remove entry if(!S1.slots[p1].second) S1.slots.erase(p1); if(!S2.slots[p2].second) @@ -1509,7 +1507,7 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s { if(S1.slots[p1].first != S2.slots[p2].first) //not same creature { - COMPLAIN("Cannot merge different creatures stacks!"); + complain("Cannot merge different creatures stacks!"); return; } @@ -1518,30 +1516,51 @@ void CGameHandler::arrangeStacks(si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, s } else if(what==3) //split { - if( vstd::contains(S2.slots,p2) //dest. slot not free - || !vstd::contains(S1.slots,p1) //no creatures to split - || S1.slots[p1].second < val //not enough creatures - || val<1 //val must be positive - ) + //general conditions checking + if((!vstd::contains(S1.slots,p1) && complain("no creatures to split")) + || (val<1 && complain("no creatures to split")) ) { - COMPLAIN("Cannot split that stack!"); - return; + return; + } + + + if(vstd::contains(S2.slots,p2)) //dest. slot not free - it must be "rebalancing"... + { + int total = S1.slots[p1].second + S2.slots[p2].second; + if( (total < val && complain("Cannot split that stack, not enough creatures!")) + || (S2.slots[p2].first != S1.slots[p1].first && complain("Cannot rebalance different creatures stacks!")) + ) + { + return; + } + + S2.slots[p2].second = val; + S1.slots[p1].second = total - val; + } + else //split one stack to the two + { + if(S1.slots[p1].second < val)//not enough creatures + { + complain("Cannot split that stack, not enough creatures!"); + return; + } + S2.slots[p2].first = S1.slots[p1].first; + S2.slots[p2].second = val; + S1.slots[p1].second -= val; } - S2.slots[p2].first = S1.slots[p1].first; - S2.slots[p2].second = val; - S1.slots[p1].second -= val; if(!S1.slots[p1].second) //if we've moved all creatures - S1.slots.erase(p1); + S1.slots.erase(p1); } if((s1->needsLastStack() && !S1.slots.size()) //it's not allowed to take last stack from hero army! || (s2->needsLastStack() && !S2.slots.size()) ) { - COMPLAIN("Cannot take the last stack!"); + complain("Cannot take the last stack!"); return; //leave without applying changes to garrison } + //apply changes SetGarrisons sg; sg.garrs[id1] = S1; if(s1 != s2) @@ -1578,7 +1597,7 @@ void CGameHandler::disbandCreature(si32 id, ui8 pos) CArmedInstance *s1 = static_cast(gs->map->objects[id]); if(!vstd::contains(s1->army.slots,pos)) { - COMPLAIN("Illegal call to disbandCreature - no such stack in army!"); + complain("Illegal call to disbandCreature - no such stack in army!"); return; } s1->army.slots.erase(pos); @@ -1594,7 +1613,7 @@ void CGameHandler::buildStructure(si32 tid, si32 bid) if(gs->canBuildStructure(t,bid) != 7) { - COMPLAIN("Cannot build that building!"); + complain("Cannot build that building!"); return; } @@ -1797,7 +1816,7 @@ void CGameHandler::garrisonSwap(si32 tid) } else { - COMPLAIN("Cannot swap garrison hero!"); + complain("Cannot swap garrison hero!"); } } @@ -2394,4 +2413,11 @@ void CGameHandler::handleTimeEvents() gs->map->events.pop_front(); } } +} + +bool CGameHandler::complain( const std::string &problem ) +{ + sendMessageToAll("Server encountered a problem: " + problem); + tlog1 << problem << std::endl; + return true; } \ No newline at end of file diff --git a/server/CGameHandler.h b/server/CGameHandler.h index c18e12a6d..f8fa8a819 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -133,6 +133,7 @@ public: void save(const std::string &fname); void close(); void handleTimeEvents(); + bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true template void serialize(Handler &h, const int version) {