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

Now hero movement should be working.

- fixed/added #22, #24, #25, #8, #11, partially #19
- minor improvements
This commit is contained in:
Michał W. Urbańczyk 2007-10-05 18:16:22 +00:00
parent 49565e6b45
commit e02f752211
9 changed files with 256 additions and 42 deletions

View File

@ -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 (from<items.size()-5)
from=items.size()-5;
draw();
}
}
else
throw 0;
}
}
void CTownList::clickRight(tribool down)
{
@ -379,7 +451,7 @@ void CTownList::draw()
blitAtWR(CGI->townh->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);
}

View File

@ -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; i<gs->players[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<int, PlayerState>::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;i<path->nodes.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)
{

View File

@ -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[]);
};

View File

@ -41,12 +41,17 @@ int internalFunc(void * callback)
break;
case 'H': //position of hero
readed>>heronum;
std::cout<<"Position of hero "<<heronum<<": "<<CGI->heroh->heroInstances[heronum]->pos<<std::endl;
break;
case 'M': //move hero
readed>>heronum>>dest;
cb->moveHero(heronum, dest);
std::cout<<"Position of hero "<<heronum<<": "<<CGI->heroh->heroInstances[heronum]->getPosition(false)<<std::endl;
break;
case 'M': //move heroa
{
readed>>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);

View File

@ -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
}

View File

@ -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;i<path->nodes.size();i++)
{
path->nodes[i].coord = CHeroInstance::convertPosition(path->nodes[i].coord,true);
}
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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<int> 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
};