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

* Garrison dialogs for garrisons. Required a bit restructuring of the code to take removable units into account. All showGarrisonDialog methods and the GarrisonDialog struct now takes it as a parameter. Visiting ally towns would benefit from this other than garrisons.

* Garrison right-click information shown, but not taking detailed info into account.
* Town info dialogs centered around cursor.
This commit is contained in:
OnionKnight 2009-09-09 17:49:03 +00:00
parent 9e7771272d
commit 3d2ab9c753
16 changed files with 115 additions and 73 deletions

View File

@ -940,7 +940,7 @@ void CGeniusAI::heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector
callback(rand() % skills.size());
}
void GeniusAI::CGeniusAI::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd )
void GeniusAI::CGeniusAI::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd )
{
onEnd();
}

View File

@ -187,7 +187,7 @@ public:
virtual void tileRevealed(int3 pos);
virtual void tileHidden(int3 pos);
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd);
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd);
virtual void playerBlocked(int reason);
virtual void objectRemoved(const CGObjectInstance *obj); //eg. collected resource, picked artifact, beaten hero

View File

@ -90,7 +90,7 @@ public:
virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level){}
virtual void showShipyardDialog(const IShipyard *obj){} //obj may be town or shipyard; state: 0 - can buid, 1 - lack of resources, 2 - dest tile is blocked, 3 - no water
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void tileHidden(const std::set<int3> &pos){};
virtual void tileRevealed(const std::set<int3> &pos){};
virtual void newObject(const CGObjectInstance * obj){}; //eg. ship built in shipyard

View File

@ -609,8 +609,8 @@ void CTerrainRect::clickRight(tribool down, bool previousState)
if(LOCPLINT->cb->getTownInfo(obj, iah))
{
SDL_Surface *iwin = graphics->drawTownInfoWin(iah);
CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x-iwin->w,
GH.current->motion.y-iwin->h, true);
CInfoPopup * ip = new CInfoPopup(iwin, GH.current->motion.x - iwin->w/2,
GH.current->motion.y - iwin->h/2, true);
GH.pushInt(ip);
}
else
@ -621,13 +621,36 @@ void CTerrainRect::clickRight(tribool down, bool previousState)
else
{
CInfoPopup * ip = new CInfoPopup(graphics->townWins[obj->id],
GH.current->motion.x-graphics->townWins[obj->id]->w,
GH.current->motion.y-graphics->townWins[obj->id]->h,false
GH.current->motion.x - graphics->townWins[obj->id]->w/2,
GH.current->motion.y - graphics->townWins[obj->id]->h/2,false
);
GH.pushInt(ip);
}
break;
}
case 33: // Garrison
{
const CGGarrison *garr = dynamic_cast<const CGGarrison *>(obj);
if (garr != NULL) {
InfoAboutTown iah;
iah.fortLevel = 0;
iah.army = garr->army;
iah.name = std::string("Garrison");
iah.owner = garr->tempOwner;
iah.built = false;
iah.details = NULL; // TODO: Find a suitable way to show detailed info.
iah.tType = NULL;
SDL_Surface *iwin = graphics->drawTownInfoWin(iah);
CInfoPopup * ip = new CInfoPopup(iwin,
GH.current->motion.x - iwin->w/2,
GH.current->motion.y - iwin->h/2, true);
GH.pushInt(ip);
}
break;
}
default:
{
LOCPLINT->adventureInt->handleRightClick(obj->getHoverText(),down,this);

View File

@ -1476,7 +1476,7 @@ bool CPlayerInterface::shiftPressed() const
return SDL_GetKeyState(NULL)[SDLK_LSHIFT] || SDL_GetKeyState(NULL)[SDLK_RSHIFT];
}
void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd )
void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd )
{
{
boost::unique_lock<boost::mutex> un(showingDialog->mx);
@ -1491,7 +1491,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
SDL_Delay(20);
pim->lock();
}
CGarrisonWindow *cgw = new CGarrisonWindow(up,down);
CGarrisonWindow *cgw = new CGarrisonWindow(up,down,removableUnits);
cgw->quit->callback += onEnd;
GH.pushInt(cgw);
}

View File

@ -149,7 +149,7 @@ public:
void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level);
void showShipyardDialog(const IShipyard *obj); //obj may be town or shipyard;
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, int soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd);
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd);
void tileHidden(const std::set<int3> &pos); //called when given tiles become hidden under fog of war
void tileRevealed(const std::set<int3> &pos); //called when fog of war disappears from given tiles
void newObject(const CGObjectInstance * obj);

View File

@ -97,7 +97,7 @@ public:
void showInfoDialog(InfoWindow *iw){};
void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback){};
ui32 showBlockingDialog(BlockingDialog *iw){return 0;}; //synchronous version of above
void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb){};
void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb){};
void giveResource(int player, int which, int val){};
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet *creatures){};
void showCompInfo(ShowInInfobox * comp){};

View File

@ -222,52 +222,66 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
refr = true;
delete pom2;
}
else if((owner->splitting || LOCPLINT->shiftPressed())
&& (!creature
|| (creature == owner->highlighted->creature))
) //we want to split
{
owner->p2 = ID; //store the second stack pos
owner->pb = upg;//store the second stack owner (up or down army)
owner->splitting = false;
int totalAmount = owner->highlighted->count;
if(creature)
totalAmount += count;
int last = -1;
if(upg != owner->highlighted->upg) //not splitting within same army
else {
// Only allow certain moves if troops aren't removable.
if (owner->removableUnits
|| (upg == 0 && (owner->highlighted->upg == 1 && !creature))
|| (upg == 1 && owner->highlighted->upg == 1))
{
if(owner->highlighted->getObj()->army.slots.size() == 1
&& owner->highlighted->getObj()->needsLastStack() )
//we want to split
if((owner->splitting || LOCPLINT->shiftPressed())
&& (!creature
|| (creature == owner->highlighted->creature)))
{
last = 0;
owner->p2 = ID; //store the second stack pos
owner->pb = upg;//store the second stack owner (up or down army)
owner->splitting = false;
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);
GH.pushInt(spw);
refr = true;
}
if(getObj()->army.slots.size() == 1
&& getObj()->needsLastStack() )
else if(creature != owner->highlighted->creature) //swap
{
last += 2;
LOCPLINT->cb->swapCreatures(
(!upg)?(owner->oup):(owner->odown),
(!owner->highlighted->upg)?(owner->oup):(owner->odown),
ID,owner->highlighted->ID);
}
else //merge
{
LOCPLINT->cb->mergeStacks(
(!owner->highlighted->upg)?(owner->oup):(owner->odown),
(!upg)?(owner->oup):(owner->odown),
owner->highlighted->ID,ID);
}
}
CSplitWindow * spw = new CSplitWindow(owner->highlighted->creature->idNumber, totalAmount, owner, last, count);
GH.pushInt(spw);
refr = true;
}
else if(creature != owner->highlighted->creature) //swap
{
LOCPLINT->cb->swapCreatures(
(!upg)?(owner->oup):(owner->odown),
(!owner->highlighted->upg)?(owner->oup):(owner->odown),
ID,owner->highlighted->ID);
}
else //merge
{
LOCPLINT->cb->mergeStacks(
(!owner->highlighted->upg)?(owner->oup):(owner->odown),
(!upg)?(owner->oup):(owner->odown),
owner->highlighted->ID,ID);
else { // Highlight
if(creature)
owner->highlighted = this;
show(screen2);
refr = true;
}
}
}
else //highlight
@ -559,9 +573,9 @@ void CGarrisonInt::splitStacks(int am2)
}
CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *&pomsur, const Point& SurOffset,
const CArmedInstance *s1, const CArmedInstance *s2, bool smallImgs)
const CArmedInstance *s1, const CArmedInstance *s2, bool _removableUnits, bool smallImgs)
:interx(inx),garOffset(garsOffset),highlighted(NULL),sur(pomsur),surOffset(SurOffset),sup(NULL),
sdown(NULL),oup(s1),odown(s2), smallIcons(smallImgs)
sdown(NULL),oup(s1),odown(s2), removableUnits(_removableUnits), smallIcons(smallImgs)
{
active = false;
splitting = false;
@ -3320,7 +3334,7 @@ void CGarrisonWindow::show(SDL_Surface * to)
printAtMiddle(CGI->generaltexth->allTexts[709],pos.x+275,pos.y+30,GEOR16,tytulowy,to);
}
CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance *down )
CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits )
{
bg = BitmapHandler::loadBitmap("GARRISON.bmp");
SDL_SetColorKey(bg,SDL_SRCCOLORKEY,SDL_MapRGB(bg->format,0,255,255));
@ -3330,7 +3344,7 @@ CGarrisonWindow::CGarrisonWindow( const CArmedInstance *up, const CGHeroInstance
pos.w = screen->w;
pos.h = screen->h;
garr = new CGarrisonInt(pos.x+92, pos.y+127, 4, Point(0,96), bg, Point(93,127), up, down);
garr = new CGarrisonInt(pos.x+92, pos.y+127, 4, Point(0,96), bg, Point(93,127), up, down, removableUnits);
garr->splitButtons.push_back(new AdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),pos.x+88,pos.y+314,"IDV6432.DEF"));
quit = new AdventureMapButton(CGI->generaltexth->tcommands[8],"",boost::bind(&CGarrisonWindow::close,this),pos.x+399,pos.y+314,"IOK6432.DEF",SDLK_RETURN);
}

View File

@ -211,6 +211,7 @@ public:
int p2; //TODO: comment me
bool ignoreEvent, update, active, splitting, pb,
smallIcons; //true - 32x32 imgs, false - 58x64
bool removableUnits;
const CCreatureSet *set1; //top set of creatures
const CCreatureSet *set2; //bottom set of creatures
@ -230,7 +231,7 @@ public:
void splitClick(); //handles click on split button
void splitStacks(int am2); //TODO: comment me
CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *&pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool smallImgs = false); //c-tor
CGarrisonInt(int x, int y, int inx, const Point &garsOffset, SDL_Surface *&pomsur, const Point &SurOffset, const CArmedInstance *s1, const CArmedInstance *s2=NULL, bool _removableUnits = true, bool smallImgs = false); //c-tor
~CGarrisonInt(); //d-tor
};
@ -689,7 +690,7 @@ public:
void deactivate();
void show(SDL_Surface * to);
void showAll(SDL_Surface * to){show(to);};
CGarrisonWindow(const CArmedInstance *up, const CGHeroInstance *down); //c-tor
CGarrisonWindow(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits); //c-tor
~CGarrisonWindow(); //d-tor
};

View File

@ -117,12 +117,14 @@ SDL_Surface * Graphics::drawTownInfoWin( const InfoAboutTown & curh )
}
//blit town icon
pom = curh.tType->typeID*2;
if (!curh.fortLevel)
pom += F_NUMBER*2;
if(curh.built)
pom++;
blitAt(bigTownPic->ourImages[pom].bitmap,13,13,ret);
if (curh.tType) {
pom = curh.tType->typeID*2;
if (!curh.fortLevel)
pom += F_NUMBER*2;
if(curh.built)
pom++;
blitAt(bigTownPic->ourImages[pom].bitmap,13,13,ret);
}
if(curh.details)
{

View File

@ -327,7 +327,7 @@ void GarrisonDialog::applyCl(CClient *cl)
return;
boost::function<void()> callback = boost::bind(&CCallback::selectionMade,LOCPLINT->cb,0,id);
cl->playerint[h->getOwner()]->showGarrisonDialog(obj,h,callback);
cl->playerint[h->getOwner()]->showGarrisonDialog(obj,h,removableUnits,callback);
}
void BattleStart::applyCl( CClient *cl )

View File

@ -2219,7 +2219,7 @@ void CGCreature::joinDecision(const CGHeroInstance *h, int cost, ui32 accept) co
}
else
{
cb->showGarrisonDialog(id,h->id,boost::bind(&IGameCallback::removeObject,cb,id)); //show garrison window and remove ourselves from map when player ends
cb->showGarrisonDialog(id,h->id,true,boost::bind(&IGameCallback::removeObject,cb,id)); //show garrison window and remove ourselves from map when player ends
}
}
}
@ -2245,7 +2245,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
if(h->tempOwner == tempOwner) //we're visiting our mine
{
cb->showGarrisonDialog(id,h->id,0);
cb->showGarrisonDialog(id,h->id,true,0);
return;
}
@ -3350,7 +3350,7 @@ void CGPandoraBox::giveContents( const CGHeroInstance *h, bool afterBattle ) con
SetGarrisons sg;
sg.garrs[id] = creatures;
cb->sendAndApply(&sg);
cb->showGarrisonDialog(id,h->id,boost::bind(&IGameCallback::removeObject,cb,id));
cb->showGarrisonDialog(id,h->id,true,boost::bind(&IGameCallback::removeObject,cb,id));
}
if(!afterBattle && message.size())
@ -3631,7 +3631,7 @@ void CGGarrison::onHeroVisit (const CGHeroInstance *h) const
if (h->tempOwner != tempOwner)
cb->setOwner(id, h->tempOwner);
//TODO: Garrison visit screen.
cb->showGarrisonDialog(id, h->id, removableUnits, 0);
}
void CGGarrison::fightOver (const CGHeroInstance *h, BattleResult *result) const

View File

@ -73,7 +73,7 @@ public:
virtual void showInfoDialog(InfoWindow *iw)=0;
virtual void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback)=0;
virtual ui32 showBlockingDialog(BlockingDialog *iw) =0; //synchronous version of above //TODO:
virtual void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
virtual void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb) =0; //cb will be called when player closes garrison window
virtual void giveResource(int player, int which, int val)=0;
virtual void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet *creatures)=0;
virtual void showCompInfo(ShowInInfobox * comp)=0;

View File

@ -722,10 +722,11 @@ struct GarrisonDialog : public Query//2004
GarrisonDialog(){type = 2004;}
void applyCl(CClient *cl);
si32 objid, hid;
bool removableUnits;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & id & objid & hid;
h & id & objid & hid & removableUnits;
}
};

View File

@ -1587,7 +1587,7 @@ void CGameHandler::giveCreatures (int objid, const CGHeroInstance * h, CCreature
SetGarrisons sg;
sg.garrs[objid] = *creatures;
sendAndApply(&sg);
showGarrisonDialog(objid, h->id, 0);
showGarrisonDialog(objid, h->id, true, 0);
return;
}
}
@ -3191,7 +3191,7 @@ ui32 CGameHandler::getQueryResult( ui8 player, int queryID )
return 0;
}
void CGameHandler::showGarrisonDialog( int upobj, int hid, const boost::function<void()> &cb )
void CGameHandler::showGarrisonDialog( int upobj, int hid, bool removableUnits, const boost::function<void()> &cb )
{
ui8 player = getOwner(hid);
GarrisonDialog gd;
@ -3205,6 +3205,7 @@ void CGameHandler::showGarrisonDialog( int upobj, int hid, const boost::function
allowedExchanges[QID] = std::pair<si32,si32>(upobj,hid);
states.addQuery(player,QID);
QID++;
gd.removableUnits = removableUnits;
sendAndApply(&gd);
}
}

View File

@ -113,7 +113,7 @@ public:
void showInfoDialog(InfoWindow *iw);
void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback);
ui32 showBlockingDialog(BlockingDialog *iw); //synchronous version of above
void showGarrisonDialog(int upobj, int hid, const boost::function<void()> &cb);
void showGarrisonDialog(int upobj, int hid, bool removableUnits, const boost::function<void()> &cb);
void giveResource(int player, int which, int val);
void giveCreatures (int objid, const CGHeroInstance * h, CCreatureSet *creatures);
void showCompInfo(ShowInInfobox * comp);