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:
parent
a08aaba29d
commit
5bbc50fc12
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
13
CMT.cpp
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user