mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
REMOVED FILES: CPatgFinder.h/cpp
Updated project files for MSVC and automake (I hope I didn't break it) * Refactored pathfinding and integrated into CGameState. * Fixed issues with wrong calculating movement cost at server side * Hero infowindow won't be redrawed each time experience changes * Removed memory leaks with CPaths-s * Support for Sign objects * Bumped savegame formt version to ensure old not compatible saves won't be readed * Spellscrolls will disappear on visit (won't be treated as spellbooks anymore)
This commit is contained in:
parent
a0057c5014
commit
516b1e2b00
@ -6,7 +6,6 @@
|
|||||||
#include "CGameInfo.h"
|
#include "CGameInfo.h"
|
||||||
#include "CHeroWindow.h"
|
#include "CHeroWindow.h"
|
||||||
#include "CMessage.h"
|
#include "CMessage.h"
|
||||||
#include "CPathfinder.h"
|
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
#include "SDL_Extensions.h"
|
#include "SDL_Extensions.h"
|
||||||
#include "client/CBitmapHandler.h"
|
#include "client/CBitmapHandler.h"
|
||||||
@ -491,10 +490,11 @@ endchkpt:
|
|||||||
int3 bufpos = currentHero->getPosition(false);
|
int3 bufpos = currentHero->getPosition(false);
|
||||||
if (mres)
|
if (mres)
|
||||||
{
|
{
|
||||||
CPath * path;
|
CPath *& pathForCurhero = LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.selected].second;
|
||||||
path = CGI->pathf->getPath(bufpos, mp, currentHero);
|
if(pathForCurhero)
|
||||||
//assign
|
delete pathForCurhero;
|
||||||
currentPath = LOCPLINT->adventureInt->heroList.items[LOCPLINT->adventureInt->heroList.selected].second = path;
|
|
||||||
|
currentPath = pathForCurhero = LOCPLINT->cb->getPath(bufpos, mp, currentHero);;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "CCallback.h"
|
#include "CCallback.h"
|
||||||
#include "CGameInfo.h"
|
#include "CGameInfo.h"
|
||||||
#include "CGameState.h"
|
#include "CGameState.h"
|
||||||
#include "CPathfinder.h"
|
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
@ -670,4 +669,10 @@ const TerrainTile * CCallback::getTileInfo( int3 tile ) const
|
|||||||
int CCallback::canBuildStructure( const CGTownInstance *t, int ID )
|
int CCallback::canBuildStructure( const CGTownInstance *t, int ID )
|
||||||
{
|
{
|
||||||
return gs->canBuildStructure(t,ID);
|
return gs->canBuildStructure(t,ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPath * CCallback::getPath( int3 src, int3 dest, const CGHeroInstance * hero )
|
||||||
|
{
|
||||||
|
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||||
|
return gs->getPath(src,dest,hero);
|
||||||
}
|
}
|
@ -74,6 +74,7 @@ public:
|
|||||||
virtual std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const =0; //heroes that can be recruited
|
virtual std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const =0; //heroes that can be recruited
|
||||||
virtual const TerrainTile * getTileInfo(int3 tile) const = 0;
|
virtual const TerrainTile * getTileInfo(int3 tile) const = 0;
|
||||||
virtual int canBuildStructure(const CGTownInstance *t, int ID) =0;//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
virtual int canBuildStructure(const CGTownInstance *t, int ID) =0;//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
||||||
|
virtual CPath * getPath(int3 src, int3 dest, const CGHeroInstance * hero)=0;
|
||||||
|
|
||||||
//battle
|
//battle
|
||||||
virtual int battleGetBattlefieldType()=0; // 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
virtual int battleGetBattlefieldType()=0; // 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
||||||
@ -164,6 +165,7 @@ public:
|
|||||||
std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const; //heroes that can be recruited
|
std::vector<const CGHeroInstance *> getAvailableHeroes(const CGTownInstance * town) const; //heroes that can be recruited
|
||||||
const TerrainTile * getTileInfo(int3 tile) const;
|
const TerrainTile * getTileInfo(int3 tile) const;
|
||||||
int canBuildStructure(const CGTownInstance *t, int ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
int canBuildStructure(const CGTownInstance *t, int ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
||||||
|
CPath * getPath(int3 src, int3 dest, const CGHeroInstance * hero);
|
||||||
|
|
||||||
//battle
|
//battle
|
||||||
int battleGetBattlefieldType(); // 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
int battleGetBattlefieldType(); // 1. sand/shore 2. sand/mesas 3. dirt/birches 4. dirt/hills 5. dirt/pines 6. grass/hills 7. grass/pines 8. lava 9. magic plains 10. snow/mountains 11. snow/trees 12. subterranean 13. swamp/trees 14. fiery fields 15. rock lands 16. magic clouds 17. lucid pools 18. holy ground 19. clover field 20. evil fog 21. "favourable winds" text on magic plains background 22. cursed ground 23. rough 24. ship to ship 25. ship
|
||||||
|
@ -1,22 +1,7 @@
|
|||||||
#define VCMI_DLL
|
#define VCMI_DLL
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "CConsoleHandler.h"
|
#include "CConsoleHandler.h"
|
||||||
#include "CAdvmapInterface.h"
|
|
||||||
#include "CCastleInterface.h"
|
|
||||||
#include "CPlayerInterface.h"
|
|
||||||
#include "CGameInfo.h"
|
|
||||||
#include "global.h"
|
|
||||||
#include "CGameState.h"
|
|
||||||
#include "CCallback.h"
|
|
||||||
#include "CPathfinder.h"
|
|
||||||
#include "mapHandler.h"
|
|
||||||
#include <sstream>
|
|
||||||
#include "SDL_Extensions.h"
|
|
||||||
#include "hch/CHeroHandler.h"
|
|
||||||
#include "hch/CLodHandler.h"
|
|
||||||
#include <boost/algorithm/string.hpp>
|
|
||||||
#include "boost/function.hpp"
|
#include "boost/function.hpp"
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -57,7 +57,6 @@ public:
|
|||||||
CLodHandler * bitmaph;
|
CLodHandler * bitmaph;
|
||||||
CGeneralTextHandler * generaltexth;
|
CGeneralTextHandler * generaltexth;
|
||||||
CConsoleHandler * consoleh;
|
CConsoleHandler * consoleh;
|
||||||
CPathfinder * pathf;
|
|
||||||
CCursorHandler * curh;
|
CCursorHandler * curh;
|
||||||
CScreenHandler * screenh;
|
CScreenHandler * screenh;
|
||||||
|
|
||||||
|
182
CGameState.cpp
182
CGameState.cpp
@ -56,7 +56,10 @@ public:
|
|||||||
void applyOnGS(CGameState *gs, void *pack) const
|
void applyOnGS(CGameState *gs, void *pack) const
|
||||||
{
|
{
|
||||||
T *ptr = static_cast<T*>(pack);
|
T *ptr = static_cast<T*>(pack);
|
||||||
|
while(!gs->mx->try_lock())
|
||||||
|
boost::this_thread::sleep(boost::posix_time::milliseconds(50)); //give other threads time to finish
|
||||||
ptr->applyGs(gs);
|
ptr->applyGs(gs);
|
||||||
|
gs->mx->unlock();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1352,7 +1355,7 @@ void CGameState::loadTownDInfos()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameState::getNeighbours(int3 tile, std::vector<int3> &vec, bool onLand)
|
void CGameState::getNeighbours(int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand)
|
||||||
{
|
{
|
||||||
vec.clear();
|
vec.clear();
|
||||||
int3 hlp;
|
int3 hlp;
|
||||||
@ -1415,10 +1418,11 @@ int CGameState::getMovementCost(const CGHeroInstance *h, int3 src, int3 dest, in
|
|||||||
//get basic cost
|
//get basic cost
|
||||||
int ret = h->getTileCost(d,s);
|
int ret = h->getTileCost(d,s);
|
||||||
|
|
||||||
if(src.x!=dest.x && src.y!=dest.y) //diagonal move costs too much but normal move is possible
|
if(src.x!=dest.x && src.y!=dest.y) //it's diagonal move
|
||||||
{
|
{
|
||||||
int old = ret;
|
int old = ret;
|
||||||
ret *= 1.414;
|
ret *= 1.414;
|
||||||
|
//diagonal move costs too much but normal move is possible - allow diagonal move
|
||||||
if(ret > remainingMovePoints && remainingMovePoints > old)
|
if(ret > remainingMovePoints && remainingMovePoints > old)
|
||||||
{
|
{
|
||||||
return remainingMovePoints;
|
return remainingMovePoints;
|
||||||
@ -1509,6 +1513,160 @@ PlayerState * CGameState::getPlayer( ui8 color )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPath * CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero)
|
||||||
|
{
|
||||||
|
if(!map->isInTheMap(src) || !map->isInTheMap(dest)) //check input
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int3 hpos = hero->getPosition(false);
|
||||||
|
tribool blockLandSea; //true - blocks sea, false - blocks land, indeterminate - allows all
|
||||||
|
|
||||||
|
if (!hero->canWalkOnSea())
|
||||||
|
blockLandSea = (map->getTile(hpos).tertype != water); //block land if hero is on water and vice versa
|
||||||
|
else
|
||||||
|
blockLandSea = boost::logic::indeterminate;
|
||||||
|
|
||||||
|
//graph initialization
|
||||||
|
std::vector< std::vector<CPathNode> > graph;
|
||||||
|
graph.resize(map->width);
|
||||||
|
for(size_t i=0; i<graph.size(); ++i)
|
||||||
|
{
|
||||||
|
graph[i].resize(map->height);
|
||||||
|
for(size_t j=0; j<graph[i].size(); ++j)
|
||||||
|
{
|
||||||
|
const TerrainTile *tinfo = &map->terrain[i][j][src.z];
|
||||||
|
CPathNode &node = graph[i][j];
|
||||||
|
|
||||||
|
node.accesible = !tinfo->blocked;
|
||||||
|
if(i==dest.x && j==dest.y && tinfo->visitable)
|
||||||
|
{
|
||||||
|
node.accesible = true; //for allowing visiting objects
|
||||||
|
}
|
||||||
|
node.dist = -1;
|
||||||
|
node.theNodeBefore = NULL;
|
||||||
|
node.visited = false;
|
||||||
|
node.coord.x = i;
|
||||||
|
node.coord.y = j;
|
||||||
|
node.coord.z = dest.z;
|
||||||
|
|
||||||
|
if ((tinfo->tertype == rock) //it's rock
|
||||||
|
|| ((blockLandSea) && (tinfo->tertype == water)) //it's sea and we cannot walk on sea
|
||||||
|
|| ((!blockLandSea) && (tinfo->tertype != water)) //it's land and we cannot walk on land
|
||||||
|
|| !getPlayer(hero->tempOwner)->fogOfWarMap[i][j][src.z] //tile is covered by the FoW
|
||||||
|
)
|
||||||
|
{
|
||||||
|
node.accesible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//graph initialized
|
||||||
|
|
||||||
|
//initial tile - set cost on 0 and add to the queue
|
||||||
|
graph[src.x][src.y].dist = 0;
|
||||||
|
std::queue<CPathNode> mq;
|
||||||
|
mq.push(graph[src.x][src.y]);
|
||||||
|
|
||||||
|
ui32 curDist = 0xffffffff; //total cost of path - init with max possible val
|
||||||
|
|
||||||
|
std::vector<int3> neighbours;
|
||||||
|
neighbours.reserve(8);
|
||||||
|
|
||||||
|
while(!mq.empty())
|
||||||
|
{
|
||||||
|
CPathNode &cp = graph[mq.front().coord.x][mq.front().coord.y];
|
||||||
|
mq.pop();
|
||||||
|
if (cp.coord == dest) //it's destination tile
|
||||||
|
{
|
||||||
|
if (cp.dist < curDist) //that path is better than previous one
|
||||||
|
curDist = cp.dist;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cp.dist > curDist) //it's not dest and current length is greater than cost of already found path
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add accessible neighbouring nodes to the queue
|
||||||
|
getNeighbours(cp.coord,neighbours,blockLandSea);
|
||||||
|
for(int i=0; i < neighbours.size(); i++)
|
||||||
|
{
|
||||||
|
CPathNode & dp = graph[neighbours[i].x][neighbours[i].y];
|
||||||
|
if(dp.accesible)
|
||||||
|
{
|
||||||
|
int cost = getMovementCost(hero,cp.coord,dp.coord,hero->movement - cp.dist);
|
||||||
|
if((dp.dist==-1 || (dp.dist > cp.dist + cost)) && dp.accesible && checkForVisitableDir(cp.coord, dp.coord) && checkForVisitableDir(dp.coord, cp.coord))
|
||||||
|
{
|
||||||
|
dp.dist = cp.dist + cost;
|
||||||
|
dp.theNodeBefore = &cp;
|
||||||
|
mq.push(dp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CPathNode *curNode = &graph[dest.x][dest.y];
|
||||||
|
if(!curNode->theNodeBefore) //destination is not accessible
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
CPath * ret = new CPath;
|
||||||
|
|
||||||
|
while(curNode->coord != graph[src.x][src.y].coord)
|
||||||
|
{
|
||||||
|
ret->nodes.push_back(*curNode);
|
||||||
|
curNode = curNode->theNodeBefore;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->nodes.push_back(graph[src.x][src.y]);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGameState::checkForVisitableDir(const int3 & src, const int3 & dst) const
|
||||||
|
{
|
||||||
|
const TerrainTile * pom = &map->getTile(dst);
|
||||||
|
for(int b=0; b<pom->visitableObjects.size(); ++b) //checking destination tile
|
||||||
|
{
|
||||||
|
if(!vstd::contains(pom->blockingObjects, pom->visitableObjects[b])) //this visitable object is not blocking, ignore
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CGDefInfo * di = pom->visitableObjects[b]->defInfo;
|
||||||
|
if( (dst.x == src.x-1 && dst.y == src.y-1) && !(di->visitDir & (1<<4)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( (dst.x == src.x && dst.y == src.y-1) && !(di->visitDir & (1<<5)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( (dst.x == src.x+1 && dst.y == src.y-1) && !(di->visitDir & (1<<6)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( (dst.x == src.x+1 && dst.y == src.y) && !(di->visitDir & (1<<7)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( (dst.x == src.x+1 && dst.y == src.y+1) && !(di->visitDir & (1<<0)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( (dst.x == src.x && dst.y == src.y+1) && !(di->visitDir & (1<<1)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( (dst.x == src.x-1 && dst.y == src.y+1) && !(di->visitDir & (1<<2)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( (dst.x == src.x-1 && dst.y == src.y) && !(di->visitDir & (1<<3)) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
|
int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting)
|
||||||
{
|
{
|
||||||
int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0);
|
int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0);
|
||||||
@ -1765,3 +1923,23 @@ std::vector<CStack> BattleInfo::getStackQueue()
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int3 CPath::startPos()
|
||||||
|
{
|
||||||
|
return int3(nodes[nodes.size()-1].coord.x,nodes[nodes.size()-1].coord.y,nodes[nodes.size()-1].coord.z);
|
||||||
|
}
|
||||||
|
void CPath::convert(ui8 mode) //mode=0 -> from 'manifest' to 'object'
|
||||||
|
{
|
||||||
|
if (mode==0)
|
||||||
|
{
|
||||||
|
for (int i=0;i<nodes.size();i++)
|
||||||
|
{
|
||||||
|
nodes[i].coord = CGHeroInstance::convertPosition(nodes[i].coord,true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int3 CPath::endPos()
|
||||||
|
{
|
||||||
|
return int3(nodes[0].coord.x,nodes[0].coord.y,nodes[0].coord.z);
|
||||||
|
}
|
||||||
|
23
CGameState.h
23
CGameState.h
@ -197,6 +197,24 @@ struct UpgradeInfo
|
|||||||
UpgradeInfo(){oldID = -1;};
|
UpgradeInfo(){oldID = -1;};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CPathNode
|
||||||
|
{
|
||||||
|
bool accesible; //true if a hero can be on this node
|
||||||
|
int dist; //distance from the first node of searching; -1 is infinity
|
||||||
|
CPathNode * theNodeBefore;
|
||||||
|
int3 coord; //coordiantes
|
||||||
|
bool visited;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DLL_EXPORT CPath
|
||||||
|
{
|
||||||
|
std::vector<CPathNode> nodes; //just get node by node
|
||||||
|
|
||||||
|
int3 startPos(); // start point
|
||||||
|
int3 endPos(); //destination point
|
||||||
|
void convert(ui8 mode); //mode=0 -> from 'manifest' to 'object'
|
||||||
|
};
|
||||||
|
|
||||||
class DLL_EXPORT CGameState
|
class DLL_EXPORT CGameState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -242,10 +260,12 @@ public:
|
|||||||
UpgradeInfo getUpgradeInfo(CArmedInstance *obj, int stackPos);
|
UpgradeInfo getUpgradeInfo(CArmedInstance *obj, int stackPos);
|
||||||
float getMarketEfficiency(int player, int mode=0);
|
float getMarketEfficiency(int player, int mode=0);
|
||||||
int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
int canBuildStructure(const CGTownInstance *t, int ID);// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
|
||||||
|
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if dst tile is visitable from dst tile
|
||||||
|
CPath * getPath(int3 src, int3 dest, const CGHeroInstance * hero); //calculates path between src and dest; returns pointer to newly allocated CPath or NULL if path does not exists
|
||||||
|
|
||||||
CGameState();
|
CGameState();
|
||||||
~CGameState();
|
~CGameState();
|
||||||
void getNeighbours(int3 tile, std::vector<int3> &vec, bool onLand);
|
void getNeighbours(int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand);
|
||||||
int getMovementCost(const CGHeroInstance *h, int3 src, int3 dest, int remainingMovePoints=-1, bool checkLast=true);
|
int getMovementCost(const CGHeroInstance *h, int3 src, int3 dest, int remainingMovePoints=-1, bool checkLast=true);
|
||||||
int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
|
int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
@ -276,7 +296,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
friend class CCallback;
|
friend class CCallback;
|
||||||
friend class CPathfinder;;
|
|
||||||
friend class CLuaCallback;
|
friend class CLuaCallback;
|
||||||
friend class CClient;
|
friend class CClient;
|
||||||
friend void initGameState(Mapa * map, CGameInfo * cgi);
|
friend void initGameState(Mapa * map, CGameInfo * cgi);
|
||||||
|
6
CMT.cpp
6
CMT.cpp
@ -20,7 +20,6 @@
|
|||||||
#include "CCastleInterface.h"
|
#include "CCastleInterface.h"
|
||||||
#include "CConsoleHandler.h"
|
#include "CConsoleHandler.h"
|
||||||
#include "CCursorHandler.h"
|
#include "CCursorHandler.h"
|
||||||
#include "CPathfinder.h"
|
|
||||||
#include "CGameState.h"
|
#include "CGameState.h"
|
||||||
#include "CCallback.h"
|
#include "CCallback.h"
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
@ -122,10 +121,7 @@ int main(int argc, char** argv)
|
|||||||
cgi->curh = new CCursorHandler;
|
cgi->curh = new CCursorHandler;
|
||||||
cgi->curh->initCursor();
|
cgi->curh->initCursor();
|
||||||
cgi->curh->show();
|
cgi->curh->show();
|
||||||
tlog0<<"\tScreen handler: "<<pomtime.getDif()<<std::endl;
|
tlog0<<"Screen handler: "<<pomtime.getDif()<<std::endl;
|
||||||
cgi->pathf = new CPathfinder();
|
|
||||||
tlog0<<"\tPathfinder: "<<pomtime.getDif()<<std::endl;
|
|
||||||
tlog0<<"Preparing first handlers: "<<tmh.getDif()<<std::endl;
|
|
||||||
pomtime.getDif();
|
pomtime.getDif();
|
||||||
graphics = new Graphics();
|
graphics = new Graphics();
|
||||||
graphics->loadHeroAnim();
|
graphics->loadHeroAnim();
|
||||||
|
234
CPathfinder.cpp
234
CPathfinder.cpp
@ -1,234 +0,0 @@
|
|||||||
#include "stdafx.h"
|
|
||||||
#include "global.h"
|
|
||||||
#include "CPathfinder.h"
|
|
||||||
#include "CGameInfo.h"
|
|
||||||
#include "hch/CAmbarCendamo.h"
|
|
||||||
#include "mapHandler.h"
|
|
||||||
#include "CGameState.h"
|
|
||||||
#include "hch/CObjectHandler.h"
|
|
||||||
#include "hch/CDefObjInfoHandler.h"
|
|
||||||
|
|
||||||
using namespace boost::logic;
|
|
||||||
|
|
||||||
int3 CPath::startPos()
|
|
||||||
{
|
|
||||||
return int3(nodes[nodes.size()-1].coord.x,nodes[nodes.size()-1].coord.y,nodes[nodes.size()-1].coord.z);
|
|
||||||
}
|
|
||||||
int3 CPath::endPos()
|
|
||||||
{
|
|
||||||
return int3(nodes[0].coord.x,nodes[0].coord.y,nodes[0].coord.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPath * CPathfinder::getPath(int3 src, int3 dest, const CGHeroInstance * hero, unsigned char type) //TODO: test it (seems to be finished, but relies on unwritten functions :()
|
|
||||||
{
|
|
||||||
//check input
|
|
||||||
if ((src.x < 0)||(src.y < 0)||(src.z < 0)||(dest.x < 0)||(dest.y < 0)||(dest.z < 0))
|
|
||||||
{
|
|
||||||
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].tileInfo->tertype==water)
|
|
||||||
blockLandSea=false;
|
|
||||||
else
|
|
||||||
blockLandSea=true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
blockLandSea = indeterminate;
|
|
||||||
}
|
|
||||||
|
|
||||||
//graph initialization
|
|
||||||
graph.resize(CGI->mh->sizes.x);
|
|
||||||
for(size_t i=0; i<graph.size(); ++i)
|
|
||||||
{
|
|
||||||
graph[i].resize(CGI->mh->sizes.y);
|
|
||||||
for(size_t j=0; j<graph[i].size(); ++j)
|
|
||||||
{
|
|
||||||
graph[i][j].accesible = !CGI->mh->ttiles[i][j][src.z].tileInfo->blocked;
|
|
||||||
if(i==dest.x && j==dest.y && CGI->mh->ttiles[i][j][src.z].tileInfo->visitable)
|
|
||||||
{
|
|
||||||
graph[i][j].accesible = true; //for allowing visiting objects
|
|
||||||
}
|
|
||||||
graph[i][j].dist = -1;
|
|
||||||
graph[i][j].theNodeBefore = NULL;
|
|
||||||
graph[i][j].visited = false;
|
|
||||||
graph[i][j].coord.x = i;
|
|
||||||
graph[i][j].coord.y = j;
|
|
||||||
graph[i][j].coord.z = dest.z;
|
|
||||||
if (CGI->mh->ttiles[i][j][src.z].tileInfo->tertype==rock)
|
|
||||||
{
|
|
||||||
graph[i][j].accesible = false;
|
|
||||||
}
|
|
||||||
if ((blockLandSea) && (CGI->mh->ttiles[i][j][src.z].tileInfo->tertype==water))
|
|
||||||
{
|
|
||||||
graph[i][j].accesible = false;
|
|
||||||
}
|
|
||||||
else if ((!blockLandSea) && (CGI->mh->ttiles[i][j][src.z].tileInfo->tertype!=water))
|
|
||||||
{
|
|
||||||
graph[i][j].accesible = false;
|
|
||||||
}
|
|
||||||
if(graph[i][j].accesible)
|
|
||||||
{
|
|
||||||
graph[i][j].accesible = CGI->state->players[hero->tempOwner].fogOfWarMap[i][j][src.z];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//graph initialized
|
|
||||||
|
|
||||||
graph[src.x][src.y].dist = 0;
|
|
||||||
|
|
||||||
std::queue<CPathNode> mq;
|
|
||||||
mq.push(graph[src.x][src.y]);
|
|
||||||
|
|
||||||
unsigned int curDist = 4000000000; //XXX 2 147 483 648 // only in C90 //but numeric limit shows 0-4294967295...confused
|
|
||||||
|
|
||||||
while(!mq.empty())
|
|
||||||
{
|
|
||||||
CPathNode cp = mq.front();
|
|
||||||
mq.pop();
|
|
||||||
if ((cp.coord.x == dest.x) && (cp.coord.y==dest.y))
|
|
||||||
{
|
|
||||||
if (cp.dist < curDist)
|
|
||||||
curDist=cp.dist;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (cp.dist > curDist)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(cp.coord.x>0)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x-1][cp.coord.y];
|
|
||||||
processNode(dp, hero, mq, cp, src, false);
|
|
||||||
}
|
|
||||||
if(cp.coord.y>0)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x][cp.coord.y-1];
|
|
||||||
processNode(dp, hero, mq, cp, src, false);
|
|
||||||
}
|
|
||||||
if(cp.coord.x>0 && cp.coord.y>0)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x-1][cp.coord.y-1];
|
|
||||||
processNode(dp, hero, mq, cp, src, true);
|
|
||||||
}
|
|
||||||
if(cp.coord.x<graph.size()-1)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x+1][cp.coord.y];
|
|
||||||
processNode(dp, hero, mq, cp, src, false);
|
|
||||||
}
|
|
||||||
if(cp.coord.y<graph[0].size()-1)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x][cp.coord.y+1];
|
|
||||||
processNode(dp, hero, mq, cp, src, false);
|
|
||||||
}
|
|
||||||
if(cp.coord.x<graph.size()-1 && cp.coord.y<graph[0].size()-1)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x+1][cp.coord.y+1];
|
|
||||||
processNode(dp, hero, mq, cp, src, true);
|
|
||||||
}
|
|
||||||
if(cp.coord.x>0 && cp.coord.y<graph[0].size()-1)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x-1][cp.coord.y+1];
|
|
||||||
processNode(dp, hero, mq, cp, src, true);
|
|
||||||
}
|
|
||||||
if(cp.coord.x<graph.size()-1 && cp.coord.y>0)
|
|
||||||
{
|
|
||||||
CPathNode & dp = graph[cp.coord.x+1][cp.coord.y-1];
|
|
||||||
processNode(dp, hero, mq, cp, src, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CPathNode curNode = graph[dest.x][dest.y];
|
|
||||||
if(!curNode.theNodeBefore)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
CPath * ret = new CPath;
|
|
||||||
|
|
||||||
while(curNode.coord!=graph[src.x][src.y].coord)
|
|
||||||
{
|
|
||||||
ret->nodes.push_back(curNode);
|
|
||||||
curNode = *(curNode.theNodeBefore);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret->nodes.push_back(graph[src.x][src.y]);
|
|
||||||
|
|
||||||
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 = CGHeroInstance::convertPosition(path->nodes[i].coord,true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPathfinder::processNode(CPathNode & dp, const CGHeroInstance * hero, std::queue<CPathNode> & mq, const CPathNode & cp, const int3 & src, bool diagonal)
|
|
||||||
{
|
|
||||||
const TerrainTile * tinfo = CGI->mh->ttiles[dp.coord.x][dp.coord.y][src.z].tileInfo;
|
|
||||||
int cost = CGI->state->getMovementCost(hero,cp.coord,dp.coord,hero->movement - cp.dist);
|
|
||||||
if((dp.dist==-1 || (dp.dist > cp.dist + cost)) && dp.accesible && checkForVisitableDir(cp.coord, dp.coord) && checkForVisitableDir(dp.coord, cp.coord))
|
|
||||||
{
|
|
||||||
dp.dist = cp.dist + cost;
|
|
||||||
dp.theNodeBefore = &graph[cp.coord.x][cp.coord.y];
|
|
||||||
mq.push(dp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CPathfinder::checkForVisitableDir(const int3 & src, const int3 & dst) const
|
|
||||||
{
|
|
||||||
for(int b=0; b<CGI->mh->ttiles[dst.x][dst.y][dst.z].tileInfo->visitableObjects.size(); ++b) //checking destination tile
|
|
||||||
{
|
|
||||||
const TerrainTile * pom = CGI->mh->ttiles[dst.x][dst.y][dst.z].tileInfo;
|
|
||||||
if(!vstd::contains(pom->blockingObjects, pom->visitableObjects[b]))
|
|
||||||
continue;
|
|
||||||
CGDefInfo * di = pom->visitableObjects[b]->defInfo;
|
|
||||||
if( (dst.x == src.x-1 && dst.y == src.y-1) && !(di->visitDir & (1<<4)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (dst.x == src.x && dst.y == src.y-1) && !(di->visitDir & (1<<5)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (dst.x == src.x+1 && dst.y == src.y-1) && !(di->visitDir & (1<<6)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (dst.x == src.x+1 && dst.y == src.y) && !(di->visitDir & (1<<7)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (dst.x == src.x+1 && dst.y == src.y+1) && !(di->visitDir & (1<<0)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (dst.x == src.x && dst.y == src.y+1) && !(di->visitDir & (1<<1)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (dst.x == src.x-1 && dst.y == src.y+1) && !(di->visitDir & (1<<2)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if( (dst.x == src.x-1 && dst.y == src.y) && !(di->visitDir & (1<<3)) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
#ifndef __CPATHFINDER_H__
|
|
||||||
#define __CPATHFINDER_H__
|
|
||||||
#include "global.h"
|
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class CGHeroInstance;
|
|
||||||
|
|
||||||
struct CPathNode
|
|
||||||
{
|
|
||||||
bool accesible; //true if a hero can be on this node
|
|
||||||
int dist; //distance from the first node of searching; -1 is infinity
|
|
||||||
CPathNode * theNodeBefore;
|
|
||||||
int3 coord; //coordiantes
|
|
||||||
bool visited;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CPath
|
|
||||||
{
|
|
||||||
std::vector<CPathNode> nodes; //just get node by node
|
|
||||||
|
|
||||||
int3 startPos(); // start point
|
|
||||||
int3 endPos(); //destination point
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* main pathfinder class
|
|
||||||
*/
|
|
||||||
class CPathfinder
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::vector< std::vector<CPathNode> > graph;
|
|
||||||
void processNode(CPathNode & dp, const CGHeroInstance * hero, std::queue<CPathNode> & mq, const CPathNode & cp, const int3 & src, bool diagonal); //helper function for getPath
|
|
||||||
bool checkForVisitableDir(const int3 & src, const int3 & dst) const;
|
|
||||||
public:
|
|
||||||
CPath * getPath(int3 src, int3 dest, const CGHeroInstance * 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 CGHeroInstance * 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__
|
|
@ -7,7 +7,6 @@
|
|||||||
#include "CGameInfo.h"
|
#include "CGameInfo.h"
|
||||||
#include "CHeroWindow.h"
|
#include "CHeroWindow.h"
|
||||||
#include "CMessage.h"
|
#include "CMessage.h"
|
||||||
#include "CPathfinder.h"
|
|
||||||
#include "CPlayerInterface.h"
|
#include "CPlayerInterface.h"
|
||||||
//#include "SDL_Extensions.h"
|
//#include "SDL_Extensions.h"
|
||||||
#include "SDL_Extensions.h"
|
#include "SDL_Extensions.h"
|
||||||
@ -1799,10 +1798,10 @@ SDL_Surface * CPlayerInterface::infoWin(const CGObjectInstance * specific) //spe
|
|||||||
return graphics->drawTownInfoWin((const CGTownInstance *)adventureInt->selection);
|
return graphics->drawTownInfoWin((const CGTownInstance *)adventureInt->selection);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
tlog1 << "Strange... selection is neither hero nor town\n";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::handleMouseMotion(SDL_Event *sEvent)
|
void CPlayerInterface::handleMouseMotion(SDL_Event *sEvent)
|
||||||
@ -1969,6 +1968,8 @@ int3 CPlayerInterface::repairScreenPos(int3 pos)
|
|||||||
}
|
}
|
||||||
void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val)
|
void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val)
|
||||||
{
|
{
|
||||||
|
if(which >= PRIMARY_SKILLS) //no need to redraw infowin if this is experience (exp is treated as prim skill with id==4)
|
||||||
|
return;
|
||||||
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
boost::unique_lock<boost::recursive_mutex> un(*pim);
|
||||||
redrawHeroWin(hero);
|
redrawHeroWin(hero);
|
||||||
}
|
}
|
||||||
@ -2482,6 +2483,11 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const HeroB
|
|||||||
|
|
||||||
void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
|
void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
|
||||||
{
|
{
|
||||||
|
if(!vstd::contains(graphics->heroWins,hero->subID))
|
||||||
|
{
|
||||||
|
tlog1 << "Cannot redraw infowindow for hero with subID=" << hero->subID << " - not present in our map\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
SDL_FreeSurface(graphics->heroWins[hero->subID]);
|
SDL_FreeSurface(graphics->heroWins[hero->subID]);
|
||||||
graphics->heroWins[hero->subID] = infoWin(hero);
|
graphics->heroWins[hero->subID] = infoWin(hero);
|
||||||
if (adventureInt->selection == hero)
|
if (adventureInt->selection == hero)
|
||||||
@ -2490,12 +2496,11 @@ void CPlayerInterface::redrawHeroWin(const CGHeroInstance * hero)
|
|||||||
|
|
||||||
bool CPlayerInterface::moveHero( const CGHeroInstance *h, CPath * path )
|
bool CPlayerInterface::moveHero( const CGHeroInstance *h, CPath * path )
|
||||||
{
|
{
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
if (!h || !path)
|
if (!h || !path)
|
||||||
return false; //can't find hero
|
return false; //can't find hero
|
||||||
|
|
||||||
CPathfinder::convertPath(path,0);
|
bool result = false;
|
||||||
|
path->convert(0);
|
||||||
stillMoveHero = true;
|
stillMoveHero = true;
|
||||||
|
|
||||||
for(int i=path->nodes.size()-1; i>0; i--)
|
for(int i=path->nodes.size()-1; i>0; i--)
|
||||||
@ -2637,7 +2642,8 @@ void CHeroList::select(int which)
|
|||||||
//recalculationg path in case of something has changed on map
|
//recalculationg path in case of something has changed on map
|
||||||
if(items[which].second)
|
if(items[which].second)
|
||||||
{
|
{
|
||||||
CPath * newPath = CGI->pathf->getPath(items[which].second->startPos(), items[which].second->endPos(), items[which].first);
|
CPath * newPath = LOCPLINT->cb->getPath(items[which].second->startPos(), items[which].second->endPos(), items[which].first);
|
||||||
|
delete items[which].second;
|
||||||
LOCPLINT->adventureInt->terrain.currentPath = items[which].second = newPath;
|
LOCPLINT->adventureInt->terrain.currentPath = items[which].second = newPath;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
0.7 -> 0.71 (as for r754)
|
0.7 -> 0.71 (as for r765)
|
||||||
GENERAL:
|
GENERAL:
|
||||||
* fixed scrolling behind window problem (now it's possible to scroll with CTRL + arrows)
|
* fixed scrolling behind window problem (now it's possible to scroll with CTRL + arrows)
|
||||||
* morale/luck system and corresponding sec. skills supported
|
* morale/luck system and corresponding sec. skills supported
|
||||||
@ -25,6 +25,7 @@ ADVENTURE INTERFACE:
|
|||||||
* new movement cost calculation algorithm
|
* new movement cost calculation algorithm
|
||||||
* fixed sight radious calculation
|
* fixed sight radious calculation
|
||||||
* it's possible to stop hero movement
|
* it's possible to stop hero movement
|
||||||
|
* faster minimap refreshing
|
||||||
|
|
||||||
BATTLES:
|
BATTLES:
|
||||||
* partial support for battle obstacles
|
* partial support for battle obstacles
|
||||||
@ -37,6 +38,7 @@ BATTLES:
|
|||||||
* blue glowing border around hovered creature
|
* blue glowing border around hovered creature
|
||||||
* made animation on battlefield more smooth
|
* made animation on battlefield more smooth
|
||||||
* standing stacks have more static animation
|
* standing stacks have more static animation
|
||||||
|
* probably fixed problem with displaying corpses on battlefield
|
||||||
* fixes for two-hex creatures actions
|
* fixes for two-hex creatures actions
|
||||||
* fixed hero casting spell animation
|
* fixed hero casting spell animation
|
||||||
* corrected stack death animation
|
* corrected stack death animation
|
||||||
@ -62,6 +64,7 @@ TOWN INTERFACE:
|
|||||||
* fixed crash occuring when clicking on hero portrait in Tavern Window, minor improvements for Tavern Window
|
* fixed crash occuring when clicking on hero portrait in Tavern Window, minor improvements for Tavern Window
|
||||||
* proper updating resdatabar after building structure in town or buying creatures (non 800x600 res)
|
* proper updating resdatabar after building structure in town or buying creatures (non 800x600 res)
|
||||||
* fixed blinking resdatabar in town screen when buying (800x600)
|
* fixed blinking resdatabar in town screen when buying (800x600)
|
||||||
|
* fixed horde buildings displaying in town hall
|
||||||
|
|
||||||
|
|
||||||
PREGAME:
|
PREGAME:
|
||||||
@ -86,6 +89,9 @@ New objects supported:
|
|||||||
* Temple
|
* Temple
|
||||||
* Watering Hole
|
* Watering Hole
|
||||||
* Fountain of Youth
|
* Fountain of Youth
|
||||||
|
* support for Redwood Observatory
|
||||||
|
* support for Shrine of Magic Incantation / Gesture / Thought
|
||||||
|
* support for Sign / Ocean Bottle
|
||||||
|
|
||||||
AI PLAYER:
|
AI PLAYER:
|
||||||
Minor improvements and fixes.
|
Minor improvements and fixes.
|
||||||
|
@ -112,15 +112,18 @@ void CClient::run()
|
|||||||
CPack *pack;
|
CPack *pack;
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
|
tlog5 << "Listening... ";
|
||||||
*serv >> pack;
|
*serv >> pack;
|
||||||
tlog5 << "Received server message of type " << typeid(*pack).name() << std::endl;
|
tlog5 << "\treceived server message of type " << typeid(*pack).name() << std::endl;
|
||||||
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)];
|
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)];
|
||||||
if(apply)
|
if(apply)
|
||||||
{
|
{
|
||||||
apply->applyOnClBefore(this,pack);
|
apply->applyOnClBefore(this,pack);
|
||||||
|
tlog5 << "\tMade first apply on cl\n";
|
||||||
gs->apply(pack);
|
gs->apply(pack);
|
||||||
|
tlog5 << "\tApplied on gs\n";
|
||||||
apply->applyOnClAfter(this,pack);
|
apply->applyOnClAfter(this,pack);
|
||||||
tlog5 << "Message successfully applied!\n";
|
tlog5 << "\tMade second apply on cl\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -171,7 +174,7 @@ void CClient::load( const std::string & fname )
|
|||||||
for(std::map<ui8,CGameInterface *>::iterator i = playerint.begin(); i!=playerint.end(); i++)
|
for(std::map<ui8,CGameInterface *>::iterator i = playerint.begin(); i!=playerint.end(); i++)
|
||||||
{
|
{
|
||||||
delete i->second; //delete player interfaces
|
delete i->second; //delete player interfaces
|
||||||
}
|
}
|
||||||
tlog0 <<"Deleting old data: "<<tmh.getDif()<<std::endl;
|
tlog0 <<"Deleting old data: "<<tmh.getDif()<<std::endl;
|
||||||
|
|
||||||
char portc[10];
|
char portc[10];
|
||||||
|
@ -24,7 +24,6 @@ vcmiclient_SOURCES = \
|
|||||||
../CMessage.cpp \
|
../CMessage.cpp \
|
||||||
../CMT.cpp \
|
../CMT.cpp \
|
||||||
../hch/CMusicHandler.cpp \
|
../hch/CMusicHandler.cpp \
|
||||||
../CPathfinder.cpp \
|
|
||||||
../CPlayerInterface.cpp \
|
../CPlayerInterface.cpp \
|
||||||
../CPreGame.cpp \
|
../CPreGame.cpp \
|
||||||
../hch/CSndHandler.cpp \
|
../hch/CSndHandler.cpp \
|
||||||
@ -56,7 +55,6 @@ vcmiclient_SOURCES = \
|
|||||||
../CMessage.h \
|
../CMessage.h \
|
||||||
../hch/CMusicHandler.h \
|
../hch/CMusicHandler.h \
|
||||||
../hch/CObjectHandler.h \
|
../hch/CObjectHandler.h \
|
||||||
../CPathfinder.h \
|
|
||||||
../CPlayerInterface.h \
|
../CPlayerInterface.h \
|
||||||
../CPreGame.h \
|
../CPreGame.h \
|
||||||
../hch/CSndHandler.h \
|
../hch/CSndHandler.h \
|
||||||
|
@ -36,7 +36,13 @@ void SetResource::applyCl( CClient *cl )
|
|||||||
|
|
||||||
void SetPrimSkill::applyCl( CClient *cl )
|
void SetPrimSkill::applyCl( CClient *cl )
|
||||||
{
|
{
|
||||||
cl->playerint[GS(cl)->getHero(id)->tempOwner]->heroPrimarySkillChanged(GS(cl)->getHero(id),which,val);
|
const CGHeroInstance *h = GS(cl)->getHero(id);
|
||||||
|
if(!h)
|
||||||
|
{
|
||||||
|
tlog1 << "Cannot find hero with ID " << id << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
INTERFACE_CALL_IF_PRESENT(h->tempOwner,heroPrimarySkillChanged,h,which,val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSecSkill::applyCl( CClient *cl )
|
void SetSecSkill::applyCl( CClient *cl )
|
||||||
|
@ -338,10 +338,6 @@
|
|||||||
RelativePath="..\hch\CMusicHandler.cpp"
|
RelativePath="..\hch\CMusicHandler.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\CPathfinder.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\CPlayerInterface.cpp"
|
RelativePath="..\CPlayerInterface.cpp"
|
||||||
>
|
>
|
||||||
@ -476,10 +472,6 @@
|
|||||||
RelativePath="..\hch\CObjectHandler.h"
|
RelativePath="..\hch\CObjectHandler.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\CPathfinder.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\CPlayerInterface.h"
|
RelativePath="..\CPlayerInterface.h"
|
||||||
>
|
>
|
||||||
|
@ -257,6 +257,15 @@ void CGeneralTextHandler::load()
|
|||||||
restypes.push_back(temp);
|
restypes.push_back(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlog5 << "\t\tReading RANDSIGN \n";
|
||||||
|
buf = bitmaph->getTextFile("RANDSIGN.TXT");
|
||||||
|
it=0;
|
||||||
|
while (it<buf.length()-1)
|
||||||
|
{
|
||||||
|
loadToIt(temp,buf,it,3);
|
||||||
|
randsign.push_back(temp);
|
||||||
|
}
|
||||||
|
|
||||||
tlog5 << "\t\tReading ZCRGN1 \n";
|
tlog5 << "\t\tReading ZCRGN1 \n";
|
||||||
buf = bitmaph->getTextFile("ZCRGN1.TXT");
|
buf = bitmaph->getTextFile("ZCRGN1.TXT");
|
||||||
it=0;
|
it=0;
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
std::vector<std::string> advobtxt;
|
std::vector<std::string> advobtxt;
|
||||||
std::vector<std::string> xtrainfo;
|
std::vector<std::string> xtrainfo;
|
||||||
std::vector<std::string> restypes;
|
std::vector<std::string> restypes;
|
||||||
|
std::vector<std::string> randsign;
|
||||||
std::vector<std::pair<std::string,std::string> > mines; //first - name; second - event description
|
std::vector<std::pair<std::string,std::string> > mines; //first - name; second - event description
|
||||||
|
|
||||||
//sec skills
|
//sec skills
|
||||||
|
@ -1493,14 +1493,17 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
{
|
{
|
||||||
if(!army.slots.size())
|
if(!army.slots.size())
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
if(ID == 5)
|
||||||
iw.player = h->tempOwner;
|
{
|
||||||
iw.components.push_back(Component(4,subID,0,0));
|
InfoWindow iw;
|
||||||
if(message.length())
|
iw.player = h->tempOwner;
|
||||||
iw.text << message;
|
iw.components.push_back(Component(4,subID,0,0));
|
||||||
else
|
if(message.length())
|
||||||
iw.text << std::pair<ui8,ui32>(12,subID);
|
iw.text << message;
|
||||||
cb->showInfoDialog(&iw);
|
else
|
||||||
|
iw.text << std::pair<ui8,ui32>(12,subID);
|
||||||
|
cb->showInfoDialog(&iw);
|
||||||
|
}
|
||||||
pick(h);
|
pick(h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1521,7 +1524,14 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
|
|
||||||
void CGArtifact::pick(const CGHeroInstance * h) const
|
void CGArtifact::pick(const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
cb->giveHeroArtifact(subID,h->id,-2);
|
if(ID == 5) //Artifact
|
||||||
|
{
|
||||||
|
cb->giveHeroArtifact(subID,h->id,-2);
|
||||||
|
}
|
||||||
|
else if(ID == 93) // Spell scroll
|
||||||
|
{
|
||||||
|
//TODO: support for the spell scroll
|
||||||
|
}
|
||||||
cb->removeObject(id);
|
cb->removeObject(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1996,3 +2006,18 @@ const std::string & CGShrine::getHoverText() const
|
|||||||
}
|
}
|
||||||
return hoverName;
|
return hoverName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGSignBottle::initObj()
|
||||||
|
{
|
||||||
|
//if no text is set than we pick random from the predefined ones
|
||||||
|
if(!message.size())
|
||||||
|
message = VLC->generaltexth->randsign[ran()%VLC->generaltexth->randsign.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGSignBottle::onHeroVisit( const CGHeroInstance * h ) const
|
||||||
|
{
|
||||||
|
InfoWindow iw;
|
||||||
|
iw.player = h->getOwner();
|
||||||
|
iw.text << message;
|
||||||
|
cb->showInfoDialog(&iw);
|
||||||
|
}
|
@ -420,10 +420,12 @@ public:
|
|||||||
|
|
||||||
class DLL_EXPORT CGSignBottle : public CGObjectInstance //signs and ocean bottles
|
class DLL_EXPORT CGSignBottle : public CGObjectInstance //signs and ocean bottles
|
||||||
{
|
{
|
||||||
//TODO: generate default message if sign is 'empty'
|
|
||||||
public:
|
public:
|
||||||
std::string message;
|
std::string message;
|
||||||
|
|
||||||
|
void onHeroVisit(const CGHeroInstance * h) const;
|
||||||
|
void initObj();
|
||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & static_cast<CGObjectInstance&>(*this);
|
h & static_cast<CGObjectInstance&>(*this);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <boost/mpl/identity.hpp>
|
#include <boost/mpl/identity.hpp>
|
||||||
|
|
||||||
#include <boost/type_traits/is_array.hpp>
|
#include <boost/type_traits/is_array.hpp>
|
||||||
const ui32 version = 703;
|
const ui32 version = 704;
|
||||||
class CConnection;
|
class CConnection;
|
||||||
namespace mpl = boost::mpl;
|
namespace mpl = boost::mpl;
|
||||||
|
|
||||||
|
@ -1162,7 +1162,7 @@ void CGameHandler::moveHero(si32 hid, int3 dst, ui8 instant, ui8 asker)
|
|||||||
tlog5 << "Player " <<int(asker) << " wants to move hero "<< hid << " from "<< h->pos << " to " << dst << std::endl;
|
tlog5 << "Player " <<int(asker) << " wants to move hero "<< hid << " from "<< h->pos << " to " << dst << std::endl;
|
||||||
int3 hmpos = dst + int3(-1,0,0);
|
int3 hmpos = dst + int3(-1,0,0);
|
||||||
TerrainTile t = gs->map->terrain[hmpos.x][hmpos.y][hmpos.z];
|
TerrainTile t = gs->map->terrain[hmpos.x][hmpos.y][hmpos.z];
|
||||||
int cost = gs->getMovementCost(h,h->pos,dst,h->movement);
|
int cost = gs->getMovementCost(h,h->getPosition(false),CGHeroInstance::convertPosition(dst,false),h->movement);
|
||||||
|
|
||||||
//result structure for start - movement failed, no move points used
|
//result structure for start - movement failed, no move points used
|
||||||
TryMoveHero tmh;
|
TryMoveHero tmh;
|
||||||
@ -1993,11 +1993,11 @@ void CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
if( !(
|
if( !(
|
||||||
(BattleInfo::mutualPosition(curpos, enemypos) >= 0) //front <=> front
|
(BattleInfo::mutualPosition(curpos, enemypos) >= 0) //front <=> front
|
||||||
|| (curStack->creature->isDoubleWide() //back <=> front
|
|| (curStack->creature->isDoubleWide() //back <=> front
|
||||||
&& BattleInfo::mutualPosition(curpos + (curStack->attackerOwned ? -1 : 1), enemypos) >= 0)
|
&& BattleInfo::mutualPosition(curpos + (curStack->attackerOwned ? -1 : 1), enemypos) >= 0)
|
||||||
|| (stackAtEnd->creature->isDoubleWide() //front <=> back
|
|| (stackAtEnd->creature->isDoubleWide() //front <=> back
|
||||||
&& BattleInfo::mutualPosition(curpos, enemypos + (stackAtEnd->attackerOwned ? -1 : 1)) >= 0)
|
&& BattleInfo::mutualPosition(curpos, enemypos + (stackAtEnd->attackerOwned ? -1 : 1)) >= 0)
|
||||||
|| (stackAtEnd->creature->isDoubleWide() && curStack->creature->isDoubleWide()//back <=> back
|
|| (stackAtEnd->creature->isDoubleWide() && curStack->creature->isDoubleWide()//back <=> back
|
||||||
&& BattleInfo::mutualPosition(curpos + (curStack->attackerOwned ? -1 : 1), enemypos + (stackAtEnd->attackerOwned ? -1 : 1)) >= 0)
|
&& BattleInfo::mutualPosition(curpos + (curStack->attackerOwned ? -1 : 1), enemypos + (stackAtEnd->attackerOwned ? -1 : 1)) >= 0)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user