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

* fixes for moving War Machines

* automatic merging same creatures stacks if needed when moving hero to town garrison
* minor improvements
This commit is contained in:
Michał W. Urbańczyk 2009-09-11 05:45:40 +00:00
parent a9617b3dfd
commit df87b34662
8 changed files with 125 additions and 45 deletions

View File

@ -199,27 +199,28 @@ void AdventureMapButton::hover (bool on)
}
}
void AdventureMapButton::activate()
{
// if (active) return;
// active=true;
activateLClick();
activateRClick();
activateHover();
activateKeys();
}
void AdventureMapButton::deactivate()
{
// if (!active) return;
// active=false;
deactivateLClick();
deactivateRClick();
deactivateHover();
deactivateKeys();
}
//void AdventureMapButton::activate()
//{
//// if (active) return;
//// active=true;
// activateLClick();
// activateRClick();
// activateHover();
// activateKeys();
//}
//void AdventureMapButton::deactivate()
//{
//// if (!active) return;
//// active=false;
// deactivateLClick();
// deactivateRClick();
// deactivateHover();
// deactivateKeys();
//}
void AdventureMapButton::init(const CFunctionList<void()> &Callback, const std::map<int,std::string> &Name, const std::string &HelpBox, bool playerColoredButton, const std::string &defName, std::vector<std::string> * add, int x, int y, int key)
{
used = LCLICK | RCLICK | HOVER | KEYBOARD;
callback = Callback;
blocked = actOnDown = false;
type=2;

View File

@ -42,8 +42,8 @@ public:
int curimg; //curently displayed image from imgs
virtual void show(SDL_Surface * to);
virtual void showAll(SDL_Surface * to);
virtual void activate()=0;
virtual void deactivate()=0;
//virtual void activate()=0;
//virtual void deactivate()=0;
CButtonBase(); //c-tor
virtual ~CButtonBase(); //d-tor
};
@ -63,8 +63,8 @@ public:
virtual void clickLeft(tribool down, bool previousState);
void hover (bool on);
void block(ui8 on); //if button is blocked then it'll change it's graphic to inactive (offset==2) and won't react on l-clicks
void activate(); // makes button active
void deactivate(); // makes button inactive (but doesn't delete)
//void activate(); // makes button active
//void deactivate(); // makes button inactive (but doesn't delete)
AdventureMapButton(); //c-tor
AdventureMapButton( const std::map<int,std::string> &, const std::string &HelpBox, const CFunctionList<void()> &Callback, int x, int y, const std::string &defName, int key=0, std::vector<std::string> * add = NULL, bool playerColoredButton = false );//c-tor

View File

@ -571,7 +571,7 @@ void CTerrainRect::clickRight(tribool down, bool previousState)
if(!objs.size())
return;
const CGObjectInstance * obj = objs.front();
const CGObjectInstance * obj = objs.back();
switch(obj->ID)
{
case HEROI_TYPE:
@ -1728,6 +1728,8 @@ void CAdvMapInt::centerOn(int3 on)
LOCPLINT->adventureInt->position = on;
LOCPLINT->adventureInt->updateScreen=true;
updateMinimap=true;
underground.curimg = on.z; //change underground switch button image
underground.redraw();
}
void CAdvMapInt::keyPressed(const SDL_KeyboardEvent & key)
{

View File

@ -270,7 +270,7 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState)
else if(other->hero && other->highlight)
{
bool allow = true;
if(upg) //moving hero out of town - check if it is allowed
if(!upg) //moving hero out of town - check if it is allowed
{
if(!hero && LOCPLINT->cb->howManyHeroes(false) >= 8)
{
@ -505,7 +505,7 @@ CCastleInterface::~CCastleInterface()
SDL_FreeSurface(townInt);
SDL_FreeSurface(cityBg);
delete exit;
delete split;
//delete split;
delete hall;
delete fort;
delete garr;
@ -749,7 +749,7 @@ void CCastleInterface::showAll( SDL_Surface * to/*=NULL*/)
if(screen->w != 800 || screen->h !=600)
CMessage::drawBorder(LOCPLINT->playerID,to,828,628,pos.x-14,pos.y-15);
exit->show(to);
split->show(to);
//split->show(to);
}
void CCastleInterface::townChange()
@ -796,7 +796,7 @@ void CCastleInterface::activate()
garr->activate();
LOCPLINT->statusbar = statusbar;
exit->activate();
split->activate();
//split->activate();
for(size_t i=0;i<buildings.size();i++) //XXX pls use iterators or at() but not []
{
buildings[i]->activate();
@ -812,7 +812,7 @@ void CCastleInterface::deactivate()
townlist->deactivate();
garr->deactivate();
exit->deactivate();
split->deactivate();
//split->deactivate();
for(size_t i=0;i<buildings.size();i++) //XXX iterators
{
buildings[i]->deactivate();

View File

@ -386,6 +386,9 @@ CGarrisonInt::~CGarrisonInt()
}
delete sdown;
}
for(size_t i = 0; i<splitButtons.size(); i++)
delete splitButtons[i];
}
void CGarrisonInt::show(SDL_Surface * to)
@ -459,9 +462,6 @@ void CGarrisonInt::activeteSlots()
}
}
}
for(size_t i = 0; i<splitButtons.size(); i++)
splitButtons[i]->activate();
}
void CGarrisonInt::createSlots()
{
@ -3424,6 +3424,12 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
{
if(ourArt) //to prevent selecting empty slots (bugfix to what GrayFace reported)
{
if(ourArt->id == 3) //catapult cannot be highlighted
{
std::vector<SComponent *> catapult(1, new SComponent(SComponent::artifact, 3, 0));
LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[312], catapult); //The Catapult must be equipped.
return;
}
clicked = true;
ourOwner->commonInfo->activeArtPlace = this;
}
@ -3432,8 +3438,24 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
{
if(slotID >= 19) //we are an backpack slot - remove active artifact and put it to the last free pos in backpack
{ //TODO: putting artifacts in the middle of backpack (pushing following arts)
LOCPLINT->cb->swapArtifacts(ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, ourOwner->commonInfo->activeArtPlace->slotID, ourOwner->curHero, ourOwner->curHero->artifacts.size()+19);
const CArtifact *cur = ourOwner->commonInfo->activeArtPlace->ourArt;
assert(cur); //there is highlighted slot, it must contain an art
switch(cur->id)
{
case 3:
//should not happen, catapult cannot be selected
break;
case 4: case 5: case 6:
{
std::string text = CGI->generaltexth->allTexts[153];
boost::algorithm::replace_first(text, "%s", cur->Name());
LOCPLINT->showInfoDialog(text);
}
break;
default:
LOCPLINT->cb->swapArtifacts(ourOwner->commonInfo->activeArtPlace->ourOwner->curHero, ourOwner->commonInfo->activeArtPlace->slotID, ourOwner->curHero, ourOwner->curHero->artifacts.size()+19);
break;
}
}
//check if swap is possible
else if(this->fitsHere(ourOwner->commonInfo->activeArtPlace->ourArt) && ourOwner->commonInfo->activeArtPlace->fitsHere(this->ourArt))
@ -3495,8 +3517,12 @@ bool CArtPlace::fitsHere(const CArtifact * art)
{
if(!art)
return true; //you can have no artifact somewhere
if(slotID > 18 || vstd::contains(art->possibleSlots,slotID)) //backpack or right slot
if(slotID > 18 && art->id >= 3 && art->id <= 6 //everything can bee placed in backpack exept of War Machines
|| vstd::contains(art->possibleSlots,slotID))
{
return true;
}
return false;
}
CArtPlace::~CArtPlace()
@ -4075,7 +4101,7 @@ CExchangeWindow::CExchangeWindow(si32 hero1, si32 hero2) : bg(NULL)
ourBar = new CStatusBar(pos.x + 3, pos.y + 577, "TSTATBAR.bmp", 726);
//garrison interface
garr = new CGarrisonInt(pos.x + 69, pos.y + 131, 4, Point(418,0), bg, Point(69,131), heroInst[0],heroInst[1], true);
garr = new CGarrisonInt(pos.x + 69, pos.y + 131, 4, Point(418,0), bg, Point(69,131), heroInst[0],heroInst[1], true, true);
garr->splitButtons.push_back(new AdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),pos.x+10,pos.y+132,"TSBTNS.DEF"));
garr->splitButtons.push_back(new AdventureMapButton(CGI->generaltexth->tcommands[3],"",boost::bind(&CGarrisonInt::splitClick,garr),pos.x+740,pos.y+132,"TSBTNS.DEF"));

53
int3.h
View File

@ -15,20 +15,28 @@
*/
class CCreature;
//a few typedefs for CCreatureSet
typedef si32 TSlot, TQuantity;
typedef ui32 TCreature;
typedef std::pair<TCreature, TQuantity> TStack;
typedef std::map<TSlot, TStack> TSlots;
class CCreatureSet //seven combined creatures
{
public:
std::map<si32, std::pair<ui32,si32> > slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
bool formation; //false - wide, true - tight
bool setCreature (si32 slot, ui32 type, si32 quantity) //slots 0 to 6
TSlots slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
ui8 formation; //false - wide, true - tight
bool setCreature (TSlot slot, TCreature type, TQuantity quantity) //slots 0 to 6
{
slots[slot] = std::pair<ui32, si32>(type, quantity); //brutal force
slots[slot] = TStack(type, quantity); //brutal force
if (slots.size() > 7) return false;
else return true;
}
si32 getSlotFor(ui32 creature, ui32 slotsAmount=7) const //returns -1 if no slot available
TSlot getSlotFor(TCreature creature, ui32 slotsAmount=7) const //returns -1 if no slot available
{
for(std::map<si32,std::pair<ui32,si32> >::const_iterator i=slots.begin(); i!=slots.end(); ++i)
for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
{
if(i->second.first == creature)
{
@ -44,6 +52,37 @@ public:
}
return -1; //no slot available
}
bool mergableStacks(std::pair<TSlot, TSlot> &out, TSlot preferable = -1) //looks for two same stacks, returns slot positions
{
//try to match creature to our preferred stack
if(preferable >= 0 && slots.find(preferable) != slots.end())
{
TCreature id = slots[preferable].first;
for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
{
if(id == j->second.first)
{
out.first = preferable;
out.second = j->first;
return true;
}
}
}
for(TSlots::const_iterator i=slots.begin(); i!=slots.end(); ++i)
{
for(TSlots::const_iterator j=slots.begin(); j!=slots.end(); ++j)
{
if(i->second.first == j->second.first)
{
out.first = i->first;
out.second = j->first;
return true;
}
}
}
return false;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & slots & formation;
@ -54,7 +93,7 @@ public:
}
void sweep()
{
for(std::map<si32,std::pair<ui32,si32> >::iterator i=slots.begin(); i!=slots.end(); ++i)
for(TSlots::iterator i=slots.begin(); i!=slots.end(); ++i)
{
if(!i->second.second)
{

View File

@ -2097,6 +2097,7 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
|| dp.turns > turn
|| (dp.turns >= turn && dp.moveRemains < remains)) //this route is faster
{
assert(&dp != cp->theNodeBefore); //two tiles can't point to each other
dp.moveRemains = remains;
dp.turns = turn;
dp.theNodeBefore = cp;

View File

@ -2162,10 +2162,21 @@ bool CGameHandler::garrisonSwap( si32 tid )
int pos = csn.getSlotFor(cso.slots.begin()->second.first);
if(pos<0)
{
complain("Cannot make garrison swap, not enough free slots!");
return false;
//try to merge two other stacks to make place
std::pair<TSlot, TSlot> toMerge;
if(csn.mergableStacks(toMerge, cso.slots.begin()->first))
{
//merge
csn.slots[toMerge.second].second += csn.slots[toMerge.first].second;
csn.slots[toMerge.first] = cso.slots.begin()->second;
}
else
{
complain("Cannot make garrison swap, not enough free slots!");
return false;
}
}
if(csn.slots.find(pos)!=csn.slots.end()) //add creatures to the existing stack
else if(csn.slots.find(pos) != csn.slots.end()) //add creatures to the existing stack
{
csn.slots[pos].second += cso.slots.begin()->second.second;
}