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

Move hero/Next hero buttons being blocked when they should (#204)

This commit is contained in:
yupsi 2011-10-04 19:43:49 +00:00
parent 8c2dd9fdce
commit 583aca8912
5 changed files with 88 additions and 23 deletions

View File

@ -1099,7 +1099,13 @@ void CAdvMapInt::fsleepWake()
setHeroSleeping(h, newSleep); setHeroSleeping(h, newSleep);
updateSleepWake(h); updateSleepWake(h);
if (newSleep) if (newSleep)
{
fnextHero(); fnextHero();
//moveHero.block(true);
//uncomment to enable original HoMM3 behaviour:
//move button is disabled for hero going to sleep, even though it's enabled when you reselect him
}
} }
void CAdvMapInt::fmoveHero() void CAdvMapInt::fmoveHero()
@ -1134,19 +1140,10 @@ void CAdvMapInt::fsystemOptions()
void CAdvMapInt::fnextHero() void CAdvMapInt::fnextHero()
{ {
if(!LOCPLINT->wanderingHeroes.size()) //no wandering heroes int next = getNextHeroIndex(heroList.selected);
return; if (next < 0)
return;
int start = heroList.selected; heroList.select(next);
int i = start;
do
{
i++;
if(i >= LOCPLINT->wanderingHeroes.size())
i = 0;
} while ((!LOCPLINT->wanderingHeroes[i]->movement || isHeroSleeping(LOCPLINT->wanderingHeroes[i])) && i!=start);
heroList.select(i);
} }
void CAdvMapInt::fendTurn() void CAdvMapInt::fendTurn()
@ -1155,7 +1152,7 @@ void CAdvMapInt::fendTurn()
return; return;
for (int i = 0; i < LOCPLINT->wanderingHeroes.size(); i++) for (int i = 0; i < LOCPLINT->wanderingHeroes.size(); i++)
if (!isHeroSleeping(LOCPLINT->wanderingHeroes[i]) && (LOCPLINT->wanderingHeroes[i]->movement > 0)) // some other minimal threshold probably? if (!isHeroSleeping(LOCPLINT->wanderingHeroes[i]) && (LOCPLINT->wanderingHeroes[i]->movement > 0))
{ {
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], std::vector<SComponent*>(), boost::bind(&CAdvMapInt::endingTurn, this), 0, false); LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], std::vector<SComponent*>(), boost::bind(&CAdvMapInt::endingTurn, this), 0, false);
return; return;
@ -1175,6 +1172,54 @@ void CAdvMapInt::updateSleepWake(const CGHeroInstance *h)
sleepWake.update(); sleepWake.update();
} }
void CAdvMapInt::updateMoveHero(const CGHeroInstance *h, tribool hasPath)
{
//default value is for everywhere but CPlayerInterface::moveHero, because paths are not updated from there immediately
if (hasPath == tribool::indeterminate_value)
hasPath = LOCPLINT->paths[h].nodes.size() ? true : false;
if (!h)
{
moveHero.block(true);
return;
}
moveHero.block(!hasPath || (h->movement == 0));
}
int CAdvMapInt::getNextHeroIndex(int startIndex)
{
if (LOCPLINT->wanderingHeroes.size() == 0)
return -1;
if (startIndex < 0)
startIndex = 0;
int i = startIndex;
do
{
i++;
if (i >= LOCPLINT->wanderingHeroes.size())
i = 0;
}
while (((LOCPLINT->wanderingHeroes[i]->movement == 0) || isHeroSleeping(LOCPLINT->wanderingHeroes[i])) && (i != startIndex));
if ((LOCPLINT->wanderingHeroes[i]->movement > 0) && !isHeroSleeping(LOCPLINT->wanderingHeroes[i]))
return i;
else
return -1;
}
void CAdvMapInt::updateNextHero(const CGHeroInstance *h)
{
int start = heroList.getPosOfHero(h);
int next = getNextHeroIndex(start);
if (next < 0)
{
nextHero.block(true);
return;
}
const CGHeroInstance *nextH = LOCPLINT->wanderingHeroes[next];
bool noActiveHeroes = (next == start) && ((nextH->movement == 0) || isHeroSleeping(nextH));
nextHero.block(noActiveHeroes);
}
void CAdvMapInt::activate() void CAdvMapInt::activate()
{ {
if(isActive()) if(isActive())
@ -1279,6 +1324,7 @@ void CAdvMapInt::setHeroSleeping(const CGHeroInstance *hero, bool sleep)
LOCPLINT->sleepingHeroes += hero; LOCPLINT->sleepingHeroes += hero;
else else
LOCPLINT->sleepingHeroes -= hero; LOCPLINT->sleepingHeroes -= hero;
updateNextHero(NULL);
} }
void CAdvMapInt::show(SDL_Surface *to) void CAdvMapInt::show(SDL_Surface *to)
@ -1548,18 +1594,15 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
terrain.currentPath = NULL; terrain.currentPath = NULL;
if(sel->ID==TOWNI_TYPE) if(sel->ID==TOWNI_TYPE)
{ {
updateSleepWake(NULL);
int pos = vstd::findPos(LOCPLINT->towns,sel); int pos = vstd::findPos(LOCPLINT->towns,sel);
townList.selected = pos; townList.selected = pos;
townList.fixPos(); townList.fixPos();
updateSleepWake(NULL);
updateMoveHero(NULL);
} }
else //hero selected else //hero selected
{ {
const CGHeroInstance *h = static_cast<const CGHeroInstance*>(sel); const CGHeroInstance *h = static_cast<const CGHeroInstance*>(sel);
updateSleepWake(h);
if(LOCPLINT->getWHero(heroList.selected) != h) if(LOCPLINT->getWHero(heroList.selected) != h)
{ {
heroList.selected = heroList.getPosOfHero(h); heroList.selected = heroList.getPosOfHero(h);
@ -1567,6 +1610,9 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
} }
terrain.currentPath = LOCPLINT->getAndVerifyPath(h); terrain.currentPath = LOCPLINT->getAndVerifyPath(h);
updateSleepWake(h);
updateMoveHero(h);
} }
townList.draw(screen); townList.draw(screen);
heroList.draw(screen); heroList.draw(screen);
@ -1725,7 +1771,9 @@ void CAdvMapInt::tileLClicked(const int3 &mp)
{ {
CGPath &path = LOCPLINT->paths[currentHero]; CGPath &path = LOCPLINT->paths[currentHero];
terrain.currentPath = &path; terrain.currentPath = &path;
if(!LOCPLINT->cb->getPath2(mp, path)) //try getting path, erase if failed bool gotPath = LOCPLINT->cb->getPath2(mp, path); //try getting path, erase if failed
updateMoveHero(currentHero);
if (!gotPath)
LOCPLINT->eraseCurrentPathOf(currentHero); LOCPLINT->eraseCurrentPathOf(currentHero);
else else
return; return;

View File

@ -235,6 +235,7 @@ public:
bool isHeroSleeping(const CGHeroInstance *hero); bool isHeroSleeping(const CGHeroInstance *hero);
void setHeroSleeping(const CGHeroInstance *hero, bool sleep); void setHeroSleeping(const CGHeroInstance *hero, bool sleep);
int getNextHeroIndex(int startIndex); //for Next Hero button - cycles awake heroes with movement only
void setPlayer(int Player); void setPlayer(int Player);
void startHotSeatWait(int Player); void startHotSeatWait(int Player);
@ -248,7 +249,10 @@ public:
const CGHeroInstance * curHero() const; const CGHeroInstance * curHero() const;
const CGTownInstance * curTown() const; const CGTownInstance * curTown() const;
const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const; //checks if obj is our ashipyard and cursor is 0,0 -> returns shipyard or NULL else const IShipyard * ourInaccessibleShipyard(const CGObjectInstance *obj) const; //checks if obj is our ashipyard and cursor is 0,0 -> returns shipyard or NULL else
void updateSleepWake(const CGHeroInstance *h); //button update //button updates
void updateSleepWake(const CGHeroInstance *h);
void updateMoveHero(const CGHeroInstance *h, tribool hasPath = tribool::indeterminate_value);
void updateNextHero(const CGHeroInstance *h);
}; };
extern CAdvMapInt *adventureInt; extern CAdvMapInt *adventureInt;

View File

@ -488,6 +488,7 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
CGI->mh->printObject(town->visitingHero); CGI->mh->printObject(town->visitingHero);
wanderingHeroes.push_back(town->visitingHero); wanderingHeroes.push_back(town->visitingHero);
} }
adventureInt->updateNextHero(NULL);
if(CCastleInterface *c = castleInt) if(CCastleInterface *c = castleInt)
{ {
@ -1142,6 +1143,7 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
//but no authentic button click/sound ;-) //but no authentic button click/sound ;-)
} }
int i = 1;
//evil... //evil...
eventsM.unlock(); eventsM.unlock();
pim->unlock(); pim->unlock();
@ -1159,7 +1161,7 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
const TerrainTile * curTile = cb->getTile(CGHeroInstance::convertPosition(h->pos, false)); const TerrainTile * curTile = cb->getTile(CGHeroInstance::convertPosition(h->pos, false));
for(int i=path.nodes.size()-1; i>0 && (stillMoveHero.data == CONTINUE_MOVE || curTile->blocked); i--) for(i=path.nodes.size()-1; i>0 && (stillMoveHero.data == CONTINUE_MOVE || curTile->blocked); i--)
{ {
//changing z coordinate means we're moving through subterranean gate -> it's done automatically upon the visit, so we don't have to request that move here //changing z coordinate means we're moving through subterranean gate -> it's done automatically upon the visit, so we don't have to request that move here
if(path.nodes[i-1].coord.z != path.nodes[i].coord.z) if(path.nodes[i-1].coord.z != path.nodes[i].coord.z)
@ -1209,6 +1211,13 @@ bool CPlayerInterface::moveHero( const CGHeroInstance *h, CGPath path )
cb->getGsMutex().lock_shared(); cb->getGsMutex().lock_shared();
pim->lock(); pim->lock();
eventsM.lock(); eventsM.lock();
if (adventureInt)
{
// (i == 0) means hero went through all the path
adventureInt->updateMoveHero(h, (i != 0));
adventureInt->updateNextHero(h);
}
return result; return result;
} }
@ -1336,6 +1345,8 @@ void CPlayerInterface::recreateHeroTownList()
std::vector<const CGTownInstance*> townInfo = cb->getTownsInfo(); std::vector<const CGTownInstance*> townInfo = cb->getTownsInfo();
for(size_t i = 0; i < townInfo.size(); i++) for(size_t i = 0; i < townInfo.size(); i++)
towns.push_back(townInfo[i]); towns.push_back(townInfo[i]);
adventureInt->updateNextHero(NULL);
} }
const CGHeroInstance * CPlayerInterface::getWHero( int pos ) const CGHeroInstance * CPlayerInterface::getWHero( int pos )

View File

@ -141,7 +141,7 @@ public:
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones) std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
std::vector<const CGTownInstance *> towns; //our heroes on the adventure map (not the garrisoned ones) std::vector<const CGTownInstance *> towns; //our heroes on the adventure map (not the garrisoned ones)
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
std::vector<const CGHeroInstance *> sleepingHeroes; std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
struct SpellbookLastSetting struct SpellbookLastSetting
{ {

View File

@ -1355,6 +1355,8 @@ void CHeroList::updateHList(const CGHeroInstance *toRemove)
else else
select(selected); select(selected);
} }
adventureInt->updateNextHero(NULL);
} }
void CHeroList::updateMove(const CGHeroInstance* which) //draws move points bar void CHeroList::updateMove(const CGHeroInstance* which) //draws move points bar