From e02f7522113d471e9c0cd0dea82cca96dffc0b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Fri, 5 Oct 2007 18:16:22 +0000 Subject: [PATCH] Now hero movement should be working. - fixed/added #22, #24, #25, #8, #11, partially #19 - minor improvements --- CAdvmapInterface.cpp | 88 ++++++++++++++++++++++++++++++++++++---- CCallback.cpp | 96 ++++++++++++++++++++++++++++++++++++-------- CCallback.h | 8 +++- CConsoleHandler.cpp | 15 ++++--- CGameInterface.cpp | 7 ++-- CPathfinder.cpp | 42 +++++++++++++++++-- CPathfinder.h | 2 + hch/CHeroHandler.cpp | 33 ++++++++++++++- hch/CHeroHandler.h | 7 +++- 9 files changed, 256 insertions(+), 42 deletions(-) diff --git a/CAdvmapInterface.cpp b/CAdvmapInterface.cpp index b66b2764f..fddd9f17a 100644 --- a/CAdvmapInterface.cpp +++ b/CAdvmapInterface.cpp @@ -178,12 +178,13 @@ void CHeroList::select(int which) { selected = which; if (which>=items.size()) - which=items.size(); - draw(); + return; LOCPLINT->adventureInt->centerOn(items[which].first->pos); LOCPLINT->adventureInt->selection.type = HEROI_TYPE; LOCPLINT->adventureInt->selection.selected = items[which].first; LOCPLINT->adventureInt->terrain.currentPath = items[which].second; + draw(); + LOCPLINT->adventureInt->townList.draw(); } void CHeroList::clickLeft(tribool down) { @@ -308,7 +309,7 @@ void CHeroList::draw() blitAtWR(mana->ourImages[pom].bitmap,posmanx,posmany+i*32); //mana SDL_Surface * temp = LOCPLINT->cb->getHeroInfo(LOCPLINT->playerID,iT,0)->type->portraitSmall; blitAtWR(temp,posporx,pospory+i*32); - if (selected == iT) + if ((selected == iT) && (LOCPLINT->adventureInt->selection.type == HEROI_TYPE)) { blitAtWR(selection,posporx,pospory+i*32); } @@ -332,10 +333,16 @@ CTownList::CTownList() arrupp.x=747; arrupp.y=196; + arrupp.w=arrup->ourImages[0].bitmap->w; + arrupp.h=arrup->ourImages[0].bitmap->h; arrdop.x=747; arrdop.y=372; + arrdop.w=arrdo->ourImages[0].bitmap->w; + arrdop.h=arrdo->ourImages[0].bitmap->h; posporx = 747; - pospory = 211; + pospory = 212; + + pressed = indeterminate; from = 0; @@ -350,12 +357,77 @@ void CTownList::genList() } void CTownList::select(int which) { + selected = which; + if (which>=items.size()) + return; + LOCPLINT->adventureInt->centerOn(items[which]->pos); + LOCPLINT->adventureInt->selection.type = TOWNI_TYPE; + LOCPLINT->adventureInt->selection.selected = items[which]; + LOCPLINT->adventureInt->terrain.currentPath = NULL; + draw(); + LOCPLINT->adventureInt->heroList.draw(); } void CTownList::mouseMoved (SDL_MouseMotionEvent & sEvent) { } void CTownList::clickLeft(tribool down) { + if (down) + { + /***************************ARROWS*****************************************/ + if(isItIn(&arrupp,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y) && from>0) + { + blitAtWR(arrup->ourImages[1].bitmap,arrupp.x,arrupp.y); + pressed = true; + return; + } + else if(isItIn(&arrdop,LOCPLINT->current->motion.x,LOCPLINT->current->motion.y) && (items.size()-from>5)) + { + blitAtWR(arrdo->ourImages[1].bitmap,arrdop.x,arrdop.y); + pressed = false; + return; + } + /***************************HEROES*****************************************/ + int hx = LOCPLINT->current->motion.x, hy = LOCPLINT->current->motion.y; + hx-=pos.x; + hy-=pos.y; hy-=arrup->ourImages[0].bitmap->h; + float ny = (float)hy/(float)32; + if (ny>5 || ny<0) + return; + select(ny+from); + } + else + { + if (indeterminate(pressed)) + return; + if (pressed) //up + { + blitAtWR(arrup->ourImages[0].bitmap,arrupp.x,arrupp.y); + pressed = indeterminate; + if (!down) + { + from--; + if (from<0) + from=0; + draw(); + } + } + else if (!pressed) //down + { + blitAtWR(arrdo->ourImages[0].bitmap,arrdop.x,arrdop.y); + pressed = indeterminate; + if (!down) + { + from++; + if (fromtownh->getPic(items[i]->type),posporx,pospory+i*32); - if (selected == iT) + if ((selected == iT) && (LOCPLINT->adventureInt->selection.type == TOWNI_TYPE)) { blitAtWR(CGI->townh->getPic(-2),posporx,pospory+i*32); } @@ -598,8 +670,8 @@ void CTerrainRect::clickLeft(tribool down) { if ( (currentPath->endPos()) == mp) { //move - LOCPLINT->cb->moveHero(0,currentPath->endPos(),0, 1);//todo - move selected hero - return; + CPath sended(*currentPath); //temporary path - engine will operate on it + LOCPLINT->cb->moveHero( ((const CHeroInstance*)LOCPLINT->adventureInt->selection.selected)->type->ID,&sended,1,0); } else { @@ -608,7 +680,7 @@ void CTerrainRect::clickLeft(tribool down) } } const CHeroInstance * currentHero = LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.selected].first; - int3 bufpos = currentHero->pos; + int3 bufpos = currentHero->getPosition(false); //bufpos.x-=1; currentPath = LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.selected].second = CGI->pathf->getPath(bufpos,mp,currentHero,1); } diff --git a/CCallback.cpp b/CCallback.cpp index f62140561..c58e4ac09 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -40,36 +40,67 @@ void CCallback::newTurn() } } } -bool CCallback::moveHero(int ID, int3 destPoint, int idtype, unsigned char posType) +bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType) { - if(ID<0 || ID>CGI->heroh->heroInstances.size()) - return false; - if(destPoint.x<0 || destPoint.x>CGI->ac->map.width) - return false; - if(destPoint.y<0 || destPoint.y>CGI->ac->map.height) - return false; - if(destPoint.z<0 || destPoint.z>CGI->mh->ttiles[0][0].size()-1) - return false; - if(posType==1) + CHeroInstance * hero = NULL; + + if (idtype==0) { - destPoint.x+=1; + if (player==-1) + hero=gs->players[player+1].heroes[ID]; + else + hero=gs->players[player].heroes[ID]; } - CPath * ourPath = CGI->pathf->getPath(CGI->heroh->heroInstances[ID]->pos, destPoint, CGI->heroh->heroInstances[ID]); + else if (idtype==1 && player>=0) //szukamy lokalnie + { + for (int i=0; iplayers[player].heroes.size();i++) + { + if (gs->players[player].heroes[i]->type->ID == ID) + hero = gs->players[player].heroes[i]; + } + } + else //idtype==1; player<0 + { + + for(std::map::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j) + { + for (int 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::exception("Unknown path format"); + + CPath * ourPath = path; if(!ourPath) return false; for(int i=ourPath->nodes.size()-1; i>0; i--) { int3 stpos, endpos; - stpos = int3(ourPath->nodes[i].coord.x, ourPath->nodes[i].coord.y, CGI->heroh->heroInstances[ID]->pos.z); - endpos = int3(ourPath->nodes[i-1].coord.x, ourPath->nodes[i-1].coord.y, CGI->heroh->heroInstances[ID]->pos.z); + stpos = int3(ourPath->nodes[i].coord.x, ourPath->nodes[i].coord.y, hero->pos.z); + endpos = int3(ourPath->nodes[i-1].coord.x, ourPath->nodes[i-1].coord.y, hero->pos.z); HeroMoveDetails curd; curd.src = stpos; curd.dst = endpos; - curd.heroID = ID; - curd.owner = CGI->heroh->heroInstances[ID]->owner; + curd.ho = hero->ourObject; + curd.owner = hero->owner; if(player!=-1) { - gs->players[player].heroes[ID]->pos = endpos; + hero->pos = endpos; } //if(CGI->heroh->heroInstances[ID]->movement>=CGI->mh->getCost(stpos, endpos, CGI->heroh->heroInstances[ID])) { //performing move @@ -86,6 +117,7 @@ bool CCallback::moveHero(int ID, int3 destPoint, int idtype, unsigned char posTy } //else //return true; //move ended - no more movement points + hero->pos = curd.dst; } return true; } @@ -162,6 +194,36 @@ int CCallback::getDate(int mode) return ((gs->day-1)/28)+1; } } +bool CCallback::verifyPath(CPath * path, bool blockSea) +{ + for (int i=0;inodes.size();i++) + { + if ( CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].blocked + && (! (CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].visitable))) + return false; //path is wrong - one of the tiles is blocked + + if (blockSea) + { + if (i==0) + continue; + + if ( + ((CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].terType==EterrainType::water) + && + (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].terType!=EterrainType::water)) + || + ((CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].terType!=EterrainType::water) + && + (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].terType==EterrainType::water)) + + ) + return false; + } + + + } + return true; +} std::vector < std::string > CCallback::getObjDescriptions(int3 pos) { diff --git a/CCallback.h b/CCallback.h index 76d1cc89b..2b9de87de 100644 --- a/CCallback.h +++ b/CCallback.h @@ -3,10 +3,12 @@ class CGameState; class CHeroInstance; class CTownInstance; +class CPath; +class CObjectInstance; struct HeroMoveDetails { int3 src, dst; //source and destination points - int heroID; //position in vector + CObjectInstance * ho; //object instance of this hero int owner; }; class CCallback @@ -22,7 +24,8 @@ protected: int player; public: - bool moveHero(int ID, int3 destPoint, int idtype=0, unsigned char posType=0);//idtype: 0-position in vector; 1-ID of hero + 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 std::vector < std::string > getObjDescriptions(int3 pos); //returns descriptions of objects at pos in order from the lowest to the highest int howManyTowns(); @@ -32,6 +35,7 @@ public: const CHeroInstance * getHeroInfo(int player, int val, bool mode); //mode = 0 -> val = serial; mode = 1 -> val = ID int getResourceAmount(int type); int getDate(int mode=0); //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month + bool verifyPath(CPath * path, bool blockSea); friend int _tmain(int argc, _TCHAR* argv[]); }; diff --git a/CConsoleHandler.cpp b/CConsoleHandler.cpp index 72898b81e..8c684ccf2 100644 --- a/CConsoleHandler.cpp +++ b/CConsoleHandler.cpp @@ -41,12 +41,17 @@ int internalFunc(void * callback) break; case 'H': //position of hero readed>>heronum; - std::cout<<"Position of hero "<heroh->heroInstances[heronum]->pos<>heronum>>dest; - cb->moveHero(heronum, dest); + std::cout<<"Position of hero "<heroh->heroInstances[heronum]->getPosition(false)<>heronum>>dest; + const CHeroInstance * hero = cb->getHeroInfo(0,heronum,0); + CPath * path = CGI->pathf->getPath(hero->getPosition(false),dest,hero); + cb->moveHero(heronum, path, 0, 0); + delete path; + break; + } case 'D': //pos description readed>>src; CGI->mh->getObjDescriptions(src); diff --git a/CGameInterface.cpp b/CGameInterface.cpp index 2614d7822..a2ccb39bd 100644 --- a/CGameInterface.cpp +++ b/CGameInterface.cpp @@ -208,8 +208,8 @@ inline void delObjRect(const int & x, const int & y, const int & z, const int & void CPlayerInterface::heroMoved(const HeroMoveDetails & details) { //initializing objects and performing first step of move - CObjectInstance * ho = CGI->heroh->heroInstances[details.heroID]->ourObject; //object representing this hero - int3 hp = CGI->heroh->heroInstances[details.heroID]->pos; + CObjectInstance * ho = details.ho; //object representing this hero + int3 hp = details.src; if(details.dst.x+1 == details.src.x && details.dst.y+1 == details.src.y) //tl { ho->moveDir = 1; @@ -736,8 +736,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details) delObjRect(hp.x, hp.y-1, hp.z, ho->id); delObjRect(hp.x, hp.y, hp.z, ho->id); } - CGI->heroh->heroInstances[details.heroID]->pos = details.dst; //actualizing hero position - CGI->heroh->heroInstances[details.heroID]->ourObject->pos = details.dst; //copy of hero's position + ho->pos = details.dst; //copy of hero's position ho->moveDir = 0; //move ended //move finished } diff --git a/CPathfinder.cpp b/CPathfinder.cpp index c7541e35f..8a53fbb16 100644 --- a/CPathfinder.cpp +++ b/CPathfinder.cpp @@ -15,11 +15,30 @@ int3 CPath::endPos() CPath * CPathfinder::getPath(int3 src, int3 dest, const CHeroInstance * hero, unsigned char type) //TODO: test it (seems to be finished, but relies on unwritten functions :() { - if(src.z!=dest.z) //first check - return NULL; - if(type==1) //calibrating + //check input + if ((src.x < 0)||(src.y < 0)||(src.z < 0)||(dest.x < 0)||(dest.y < 0)||(dest.z < 0)) { - src.x-=1; + return NULL; + } + if ((src.x >= CGI->mh->sizes.x)||(src.y >= CGI->mh->sizes.y)||(src.z >= CGI->mh->sizes.z) + ||(dest.x >= CGI->mh->sizes.x)||(dest.y >= CGI->mh->sizes.y)||(dest.z >= CGI->mh->sizes.z)) + { + return NULL; + } + + int3 hpos = hero->getPosition(false); + + tribool blockLandSea; //true - blocks sea, false - blocks land, indeterminate - allows all + if (!hero->canWalkOnSea()) + { + if (CGI->mh->ttiles[hpos.x][hpos.y][hpos.z].terType==EterrainType::water) + blockLandSea=false; + else + blockLandSea=true; + } + else + { + blockLandSea = indeterminate; } //graph initialization @@ -39,6 +58,10 @@ CPath * CPathfinder::getPath(int3 src, int3 dest, const CHeroInstance * hero, un graph[i][j]->coord.x = i; graph[i][j]->coord.y = j; graph[i][j]->coord.z = dest.z; + if ((blockLandSea) && (CGI->mh->ttiles[i][j][src.z].terType==EterrainType::water)) + graph[i][j]->accesible = false; + else if ((!blockLandSea) && (CGI->mh->ttiles[i][j][src.z].terType!=EterrainType::water)) + graph[i][j]->accesible = false; } } @@ -165,3 +188,14 @@ CPath * CPathfinder::getPath(int3 src, int3 dest, const CHeroInstance * hero, un } return ret; } + +void CPathfinder::convertPath(CPath * path, unsigned int mode) //mode=0 -> from 'manifest' to 'object' +{ + if (mode==0) + { + for (int i=0;inodes.size();i++) + { + path->nodes[i].coord = CHeroInstance::convertPosition(path->nodes[i].coord,true); + } + } +} \ No newline at end of file diff --git a/CPathfinder.h b/CPathfinder.h index 5b65dbf21..813454d94 100644 --- a/CPathfinder.h +++ b/CPathfinder.h @@ -31,6 +31,8 @@ private: public: CPath * getPath(int3 src, int3 dest, const CHeroInstance * hero, unsigned char type=0); //calculates path between src and dest; returns pointer to CPath or NULL if path does not exists; type - type of calculation: 0 - positions are normal positions of hero; 1 - given places are tiles blocked by hero CPath * getPath(const int3 & src, const int3 & dest, const CHeroInstance * hero, int (*getDist)(int3 & a, int3 & b), unsigned char type=0); //calculates path between src and dest; returns pointer to CPath or NULL if path does not exists; uses getDist to calculate distance; type - type of calculation: 0 - positions are normal positions of hero; 1 - given places are tiles blocked by hero + + static void convertPath(CPath * path, unsigned int mode); //mode=0 -> from 'manifest' to 'object' }; #endif //CPATHFINDER_H \ No newline at end of file diff --git a/hch/CHeroHandler.cpp b/hch/CHeroHandler.cpp index b65e8abc6..e14175781 100644 --- a/hch/CHeroHandler.cpp +++ b/hch/CHeroHandler.cpp @@ -439,6 +439,37 @@ unsigned int CHeroInstance::getLowestCreatureSpeed() return sl; } +int3 CHeroInstance::convertPosition(int3 src, bool toh3m) //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest +{ + if (toh3m) + { + src.x+=1; + return src; + } + else + { + src.x-=1; + return src; + } +} +int3 CHeroInstance::getPosition(bool h3m) const +{ + if (h3m) + return pos; + else return convertPosition(pos,false); +} +void CHeroInstance::setPosition(int3 Pos, bool h3m) +{ + if (h3m) + pos = Pos; + else + pos = convertPosition(Pos,true); +} +bool CHeroInstance::canWalkOnSea() const +{ + //TODO: write it - it should check if hero is flying, or something similiar + return false; +} void CHeroHandler::initTerrainCosts() { std::ifstream inp; @@ -458,4 +489,4 @@ void CHeroHandler::initTerrainCosts() } } inp.close(); -} +} \ No newline at end of file diff --git a/hch/CHeroHandler.h b/hch/CHeroHandler.h index 2a8c58c8b..1f1379ec6 100644 --- a/hch/CHeroHandler.h +++ b/hch/CHeroHandler.h @@ -57,7 +57,7 @@ public: std::string name; //may be custom std::string biography; //may be custom int portrait; //may be custom - int3 pos; //position on adventure map + int3 pos; //position of object (hero pic is on the left) CCreatureSet army; //army int mana; // remaining spell points std::vector primSkills; //0-attack, 1-defence, 2-spell power, 3-knowledge @@ -69,6 +69,11 @@ public: unsigned int getLowestCreatureSpeed(); unsigned int getAdditiveMoveBonus(); unsigned float getMultiplicativeMoveBonus(); + static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest + int3 getPosition(bool h3m) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation' + void setPosition(int3 Pos, bool h3m); //as above, but sets position + + bool canWalkOnSea() const; //TODO: artifacts, known spells, commander, blessings, curses, morale/luck special modifiers };