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

* it's possible to stop hero movement

* fixed horde buildings displaying in town hall
This commit is contained in:
Michał W. Urbańczyk 2009-03-12 18:50:36 +00:00
parent a08aaba29d
commit 5bbc50fc12
8 changed files with 121 additions and 100 deletions

View File

@ -402,7 +402,7 @@ endchkpt:
{ //move
CPath sended(*currentPath); //temporary path - engine will operate on it
LOCPLINT->pim->unlock();
mres = LOCPLINT->cb->moveHero( ((const CGHeroInstance*)LOCPLINT->adventureInt->selection)->type->ID,&sended,1,0);
mres = LOCPLINT->moveHero(static_cast<const CGHeroInstance*>(LOCPLINT->adventureInt->selection),&sended);
LOCPLINT->pim->lock();
if(mres)
{
@ -1249,7 +1249,7 @@ void CAdvMapInt::fmoveHero()
return;
CPath sended(*(terrain.currentPath)); //temporary path - engine will operate on it
LOCPLINT->pim->unlock();
LOCPLINT->cb->moveHero( ((const CGHeroInstance*)LOCPLINT->adventureInt->selection)->type->ID,&sended,1,0);
LOCPLINT->moveHero(static_cast<const CGHeroInstance*>(LOCPLINT->adventureInt->selection),&sended);
LOCPLINT->pim->lock();
}
void CAdvMapInt::fshowSpellbok()

View File

@ -54,79 +54,26 @@ template <ui16 N> bool isType(CPack *pack)
return pack->getType() == N;
}
bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
bool CCallback::moveHero(const CGHeroInstance *h, int3 dst) const
{
CGHeroInstance * hero = NULL;
*cl->serv << &MoveHero(dst,h->id);
if (idtype==0)
{
if (player==-1)
hero=gs->players[player+1].heroes[ID];
else
hero=gs->players[player].heroes[ID];
}
else if (idtype==1 && player>=0) //looking for it in local area
{
for (size_t i=0; i < gs->players[player].heroes.size(); ++i)
{//wait till there is server answer
boost::unique_lock<boost::mutex> lock(*mess.mx);
while(std::find_if(mess.res->begin(),mess.res->end(),&isType<501>) == mess.res->end())
mess.cv->wait(lock);
std::set<CPack*>::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),&isType<501>);
TryMoveHero *tmh = dynamic_cast<TryMoveHero*>(*itr);
mess.res->erase(itr);
if(!tmh->result)
{
if (gs->players[player].heroes[i]->type->ID == ID)
hero = gs->players[player].heroes[i];
}
}
else //idtype==1; player<0
{
for(std::map<ui8, PlayerState>::iterator j=gs->players.begin(); j!=gs->players.end(); ++j)
{
for (size_t i=0; i < (*j).second.heroes.size(); ++i)
{
if ((*j).second.heroes[i]->type->ID == ID)
{
hero = (*j).second.heroes[i];
}
}
}
}
if (!hero)
return false; //can't find hero
if(!verifyPath(path,!hero->canWalkOnSea()))//TODO: not check sea, if hero has flying or walking on water
return false; //invalid path
//check path format
if (pathType==0)
CPathfinder::convertPath(path,pathType);
if (pathType>1)
throw std::string("Unknown path format");
CPath * ourPath = path;
if(!ourPath)
return false;
for(int i=ourPath->nodes.size()-1; i>0; i--)
{
int3 stpos(ourPath->nodes[i].coord.x, ourPath->nodes[i].coord.y, hero->pos.z),
endpos(ourPath->nodes[i-1].coord.x, ourPath->nodes[i-1].coord.y, hero->pos.z);
HeroMoveDetails curd(stpos,endpos,hero);
*cl->serv << &MoveHero(endpos,hero->id);
{//wait till there is server answer
boost::unique_lock<boost::mutex> lock(*mess.mx);
while(std::find_if(mess.res->begin(),mess.res->end(),&isType<501>) == mess.res->end())
mess.cv->wait(lock);
std::set<CPack*>::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),&isType<501>);
TryMoveHero *tmh = dynamic_cast<TryMoveHero*>(*itr);
mess.res->erase(itr);
if(!tmh->result)
{
delete tmh;
return false;
}
delete tmh;
return false;
}
delete tmh;
}
return true;
}
void CCallback::selectionMade(int selection, int asker)
{
*cl->serv << &QueryReply(asker,selection);
@ -700,7 +647,7 @@ void CCallback::recruitHero(const CGTownInstance *town, const CGHeroInstance *he
{
if(gs->players[player].availableHeroes[i] == hero)
{
*cl->serv << &HireHero(town->id,i);
*cl->serv << &HireHero(i,town->id);
return;
}
}

View File

@ -31,8 +31,7 @@ struct TerrainTile;
class ICallback
{
public:
virtual bool moveHero(int ID, CPath * path, int idtype, int pathType=0)=0;//idtype: 0 - position in vector of heroes (of that player); 1 - ID of hero
//pathType: 0 - nodes are manifestation pos, 1 - nodes are object pos
virtual bool moveHero(const CGHeroInstance *h, int3 dst) const =0; //dst must be free, neighbouring tile (this function can move hero only by one tile)
virtual int swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)=0;//swaps creatures between two posiibly different garrisons // TODO: AI-unsafe code - fix it!
virtual int mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)=0;//joins first stack tothe second (creatures must be same type)
virtual int splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val)=0;//split creatures from the first stack
@ -118,8 +117,7 @@ protected:
public:
//commands
bool moveHero(int ID, CPath * path, int idtype, int pathType=0);//idtype: 0 - position in vector of heroes (of that player); 1 - ID of hero
//pathType: 0 - nodes are manifestation pos, 1 - nodes are object pos
bool moveHero(const CGHeroInstance *h, int3 dst) const; //dst must be free, neighbouring tile (this function can move hero only by one tile)
void selectionMade(int selection, int asker);
int swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2);
int mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2); //first goes to the second

View File

@ -1010,38 +1010,50 @@ CHallInterface::CHallInterface(CCastleInterface * owner)
boxes.resize(5);
for(size_t i=0;i<5;i++) //for each row
{
for(size_t j=0; j<CGI->buildh->hall[owner->town->subID].second[i].size();j++) //for each box
std::vector< std::vector< std::vector<int> > > &boxList = CGI->buildh->hall[owner->town->subID].second;
for(size_t j=0; j<boxList[i].size();j++) //for each box
{
size_t k=0;
for(;k<CGI->buildh->hall[owner->town->subID].second[i][j].size();k++)//we are looking for the first not build structure
for(;k<boxList[i][j].size();k++)//we are looking for the first not build structure
{
if(
(owner->town->builtBuildings.find(CGI->buildh->hall[owner->town->subID].second[i][j][k]))
==
(owner->town->builtBuildings.end()) )
int bid = boxList[i][j][k];
if(!vstd::contains(owner->town->builtBuildings,bid))
{
int x = 34 + 194*j,
y = 37 + 104*i,
ID = CGI->buildh->hall[owner->town->subID].second[i][j][k];
if(CGI->buildh->hall[owner->town->subID].second[i].size() == 2) //only two boxes in this row
ID = bid;
if(boxList[i].size() == 2) //only two boxes in this row
x+=194;
else if(CGI->buildh->hall[owner->town->subID].second[i].size() == 3) //only three boxes in this row
else if(boxList[i].size() == 3) //only three boxes in this row
x+=97;
boxes[i].push_back(new CBuildingBox(CGI->buildh->hall[owner->town->subID].second[i][j][k],pos.x+x,pos.y+y));
boxes[i].push_back(new CBuildingBox(bid,pos.x+x,pos.y+y));
//if this is horde dwelling for upgraded creatures and we already have one for basic creatures
if((bid == 25 && vstd::contains(owner->town->builtBuildings,24))
|| (bid == 19 && vstd::contains(owner->town->builtBuildings,18))
)
{
boxes[i].back()->state = 4; //already built
}
else
{
boxes[i].back()->state = LOCPLINT->cb->canBuildStructure(owner->town,ID);
}
boxes[i].back()->state = LOCPLINT->cb->canBuildStructure(owner->town,ID);
break;
}
}
if(k==CGI->buildh->hall[owner->town->subID].second[i][j].size()) //all buildings built - let's take the last one
if(k == boxList[i][j].size()) //all buildings built - let's take the last one
{
int x = 34 + 194*j,
y = 37 + 104*i;
if(CGI->buildh->hall[owner->town->subID].second[i].size() == 2)
if(boxList[i].size() == 2)
x+=194;
else if(CGI->buildh->hall[owner->town->subID].second[i].size() == 3)
else if(boxList[i].size() == 3)
x+=97;
boxes[i].push_back(new CBuildingBox(CGI->buildh->hall[owner->town->subID].second[i][j][k-1],pos.x+x,pos.y+y));
boxes[i].push_back(new CBuildingBox(boxList[i][j][k-1],pos.x+x,pos.y+y));
boxes[i][boxes[i].size()-1]->state = 4; //already exists
}
}

13
CMT.cpp
View File

@ -48,7 +48,7 @@
#endif
std::string NAME = NAME_VER + std::string(" (client)");
SDL_Surface * screen, * screen2;
std::queue<SDL_Event> events;
std::queue<SDL_Event*> events;
boost::mutex eventsM;
TTF_Font * TNRB16, *TNR, *GEOR13, *GEORXX, *GEORM, *GEOR16;
void processCommand(const std::string &message, CClient *&client);
@ -191,11 +191,12 @@ int main(int argc, char** argv)
boost::thread t(boost::bind(&CClient::run,&cl));
}
SDL_Event ev;
SDL_Event *ev = NULL;
while(1) //main SDL events loop
{
SDL_WaitEvent(&ev);
if((ev.type==SDL_QUIT) || (ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
ev = new SDL_Event();
SDL_WaitEvent(ev);
if((ev->type==SDL_QUIT) || (ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4 && (ev->key.keysym.mod & KMOD_ALT)))
{
cl.close();
#ifndef __unix__
@ -206,7 +207,7 @@ int main(int argc, char** argv)
tlog0 << "Ending...\n";
exit(EXIT_SUCCESS);
}
else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
else if(ev->type == SDL_KEYDOWN && ev->key.keysym.sym==SDLK_F4)
{
LOCPLINT->pim->lock();
bool full = !(screen->flags&SDL_FULLSCREEN);
@ -329,6 +330,6 @@ void processCommand(const std::string &message, CClient *&client)
}
else if(client && client->serv && client->serv->connected) //send to server
{
*client->serv << &PlayerMessage(255,message);
*client->serv << &PlayerMessage(LOCPLINT->playerID,message);
}
}

View File

@ -49,7 +49,7 @@ using namespace CSDL_Ext;
extern TTF_Font * GEOR16;
CPlayerInterface * LOCPLINT;
extern std::queue<SDL_Event> events;
extern std::queue<SDL_Event*> events;
extern boost::mutex eventsM;
@ -1145,13 +1145,26 @@ void CPlayerInterface::yourTurn()
(*i)->tick();
}
LOCPLINT->adventureInt->updateScreen = false;
eventsM.lock();
while(!events.empty())
while(true)
{
handleEvent(&events.front());
events.pop();
SDL_Event *ev = NULL;
{
boost::unique_lock<boost::mutex> lock(eventsM);
if(!events.size())
{
break;
}
else
{
ev = events.front();
events.pop();
}
}
handleEvent(ev);
delete ev;
}
eventsM.unlock();
if (curint == adventureInt) //stuff for advMapInt
{
adventureInt->update();
@ -1702,6 +1715,27 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
//move finished
adventureInt->minimap.draw();
adventureInt->heroList.updateMove(ho);
//check if user cancelled movement
{
boost::unique_lock<boost::mutex> un(eventsM);
while(events.size())
{
SDL_Event *ev = events.front();
events.pop();
switch(ev->type)
{
case SDL_MOUSEBUTTONDOWN:
stillMoveHero = false;
break;
case SDL_KEYDOWN:
if(ev->key.keysym.sym < SDLK_F1)
stillMoveHero = false;
break;
}
delete ev;
}
}
}
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
{
@ -2445,6 +2479,30 @@ void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
adventureInt->infoBar.draw();
}
bool CPlayerInterface::moveHero( const CGHeroInstance *h, CPath * path )
{
bool result = false;
if (!h || !path)
return false; //can't find hero
CPathfinder::convertPath(path,0);
stillMoveHero = true;
for(int i=path->nodes.size()-1; i>0; i--)
{
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(!stillMoveHero)
return result;
}
int3 endpos(path->nodes[i-1].coord.x, path->nodes[i-1].coord.y, h->pos.z);
result = cb->moveHero(h,endpos);
}
stillMoveHero = false;
return result;
}
CStatusBar::CStatusBar(int x, int y, std::string name, int maxw)
{
bg=BitmapHandler::loadBitmap(name);

View File

@ -450,6 +450,7 @@ public:
//to commucate with engine
CCallback * cb;
const BattleAction *curAction;
bool stillMoveHero;
std::list<CInfoWindow *> dialogs;
@ -515,6 +516,7 @@ public:
void removeObjToBlit(IShowable* obj);
void showInfoDialog(std::string &text, const std::vector<SComponent*> & components);
void showYesNoDialog(std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
bool moveHero(const CGHeroInstance *h, CPath * path);
CPlayerInterface(int Player, int serial);//c-tor
~CPlayerInterface();//d-tor

View File

@ -1,4 +1,4 @@
0.7 -> 0.71 (as for r751)
0.7 -> 0.71 (as for r754)
GENERAL:
* fixed scrolling behind window problem (now it's possible to scroll with CTRL + arrows)
* morale/luck system and corresponding sec. skills supported
@ -12,6 +12,7 @@ GENERAL:
* fixed crashes on loading maps with flag all mines/dwelling victory condition
* further fixes for leveling-up (stability and identical offered skills bug)
* support for numpad keyboard
* support for timed events
ADVENTURE INTERFACE:
* added "Next hero" button functionality
@ -22,6 +23,8 @@ ADVENTURE INTERFACE:
* orientation of hero can't be change if movement points are exhausted
* campfire, borderguard, bordergate, questguard will be accessible from the top
* new movement cost calculation algorithm
* fixed sight radious calculation
* it's possible to stop hero movement
BATTLES:
* partial support for battle obstacles