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

* further fight with hanged scroll tab

* fixed r-click on FoW crash
* fixed crash on opening tavern window after load
* fixed recruiting new heroes after load
* fixed crash on loading map with spell scrolls
* fixed more crashes
* displpaying difficulty level of saved game
* added support for Library of Enlightenment
* added notification when saving is done
This commit is contained in:
Michał W. Urbańczyk 2009-02-01 14:11:41 +00:00
parent a560e9069a
commit 3d29c31deb
16 changed files with 169 additions and 38 deletions

View File

@ -371,6 +371,10 @@ void CSlider::clickLeft (tribool down)
moveTo(rw*amount);
return;
}
else
{
moving = false;
}
if(moving)
{
MotionInterested::deactivate();

View File

@ -454,6 +454,11 @@ void CTerrainRect::clickRight(tribool down)
{
case 34:
{
if(!vstd::contains(graphics->heroWins,obj->subID))
{
tlog3 << "Warning - no infowin for hero " << obj->subID << std::endl;
break;
}
CInfoPopup * ip = new CInfoPopup(graphics->heroWins[obj->subID],
LOCPLINT->current->motion.x-graphics->heroWins[obj->subID]->w,
LOCPLINT->current->motion.y-graphics->heroWins[obj->subID]->h,false
@ -463,6 +468,11 @@ void CTerrainRect::clickRight(tribool down)
}
case 98:
{
if(!vstd::contains(graphics->townWins,obj->subID))
{
tlog3 << "Warning - no infowin for town " << obj->subID << std::endl;
break;
}
CInfoPopup * ip = new CInfoPopup(graphics->townWins[obj->id],
LOCPLINT->current->motion.x-graphics->townWins[obj->id]->w,
LOCPLINT->current->motion.y-graphics->townWins[obj->id]->h,false

View File

@ -574,9 +574,9 @@ void CCallback::buyArtifact(const CGHeroInstance *hero, int aid)
std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos ) const
{
std::vector<const CGObjectInstance *> ret;
if(!gs->map->isInTheMap(pos))
return ret;
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->map->isInTheMap(pos) || !isVisible(pos))
return ret;
BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects)
ret.push_back(obj);
return ret;
@ -585,9 +585,9 @@ std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos )
std::vector < const CGObjectInstance * > CCallback::getVisitableObjs( int3 pos ) const
{
std::vector<const CGObjectInstance *> ret;
if(!gs->map->isInTheMap(pos))
return ret;
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->map->isInTheMap(pos) || !isVisible(pos))
return ret;
BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].visitableObjects)
ret.push_back(obj);
return ret;
@ -614,7 +614,7 @@ void CCallback::getMarketOffer( int t1, int t2, int &give, int &rec, int mode/*=
std::vector < const CGObjectInstance * > CCallback::getFlaggableObjects(int3 pos) const
{
if(!isVisible(pos, LOCPLINT->playerID))
if(!isVisible(pos))
return std::vector < const CGObjectInstance * >();
std::vector < const CGObjectInstance * > ret;

View File

@ -721,6 +721,8 @@ void CGameState::applyNL(IPack * pack)
}
else
map->objects[h->id] = h;
h->initHeroDefInfo();
map->heroes.push_back(h);
players[h->tempOwner].heroes.push_back(h);
map->addBlockVisTiles(h);

View File

@ -60,6 +60,27 @@ public:
template <typename Handler> void serialize(Handler &h, const int version)
{
h & color & serial & currentSelection & fogOfWarMap & resources;
ui32 size;
if(h.saving) //write subids of available heroes
{
size = availableHeroes.size();
h & size;
for(size_t i=0; i < size; i++)
h & availableHeroes[i]->subID;
}
else
{
ui32 hid;
h & size;
for(size_t i=0; i < size; i++)
{
//fill availableHeroes with dummy hero instances, holding subids
h & hid;
availableHeroes.push_back(new CGHeroInstance);
availableHeroes[availableHeroes.size()-1]->subID = hid;
}
}
}
};
@ -225,6 +246,16 @@ public:
for(int i=0; i<map->heroes.size(); i++)
if(map->heroes[i]->tempOwner < PLAYER_LIMIT)
players[map->heroes[i]->tempOwner].heroes.push_back(map->heroes[i]);
//recreating available heroes
for(std::map<ui8,PlayerState>::iterator i=players.begin(); i!=players.end(); i++)
{
for(size_t j=0; j < i->second.availableHeroes.size(); j++)
{
ui32 hlp = i->second.availableHeroes[j]->subID;
delete i->second.availableHeroes[j];
i->second.availableHeroes[j] = hpool.heroesPool[hlp];
}
}
}
}

View File

@ -1074,12 +1074,18 @@ void MapSel::processMaps(std::vector<std::string> &pliczkiTemp, int &index)
void MapSel::processGames( std::vector<std::string> &pliczkiTemp, int &index )
{
ourGames.resize(pliczkiTemp.size());
ui32 hlp;
for(int i=0; i<pliczkiTemp.size(); i++)
{
CLoadFile lf(pliczkiTemp[i]);
ui8 sign[8];
lf >> sign >> static_cast<CMapHeader&>(ourGames[i]);
lf >> sign >> hlp >> static_cast<CMapHeader&>(ourGames[i]) >> ourGames[i].seldiff;
if(hlp != version)
{
tlog3 << "\t" << ourGames[i].filename << " seems to be too " << ((hlp>version) ? "new" : "old") << " and will be ommited.\n";
continue;
}
ourGames[i].filename = pliczkiTemp[i];
ourGames[i].countPlayers();
}
@ -1308,6 +1314,8 @@ MapSel::MapSel():selected(0),sizeFilter(0)
}
void MapSel::printSelectedInfo()
{
CMapInfo &selMap = selectedMap();
SDL_BlitSurface(CPG->ourScenSel->scenInf,&genRect(399,337,17,23),screen,&genRect(399,337,413,29));
SDL_BlitSurface(CPG->ourScenSel->scenInf,&genRect(50,91,18,447),screen,&genRect(50,91,414,453));
if(CPG->fromnewgame)
@ -1316,6 +1324,19 @@ void MapSel::printSelectedInfo()
SDL_BlitSurface(CPG->ourScenSel->bOptions.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bOptions.pos);
SDL_BlitSurface(CPG->ourScenSel->bRandom.imgs->ourImages[0].bitmap,NULL,screen,&CPG->ourScenSel->bRandom.pos);
}
else
{
CPG->ourScenSel->bEasy.state = 2 + (selMap.seldiff==0);
CPG->ourScenSel->bNormal.state = 2 + (selMap.seldiff==1);
CPG->ourScenSel->bHard.state = 2 + (selMap.seldiff==2);
CPG->ourScenSel->bExpert.state = 2 + (selMap.seldiff==3);
CPG->ourScenSel->bImpossible.state = 2 + (selMap.seldiff==4);
CPG->ourScenSel->bEasy.show();
CPG->ourScenSel->bNormal.show();
CPG->ourScenSel->bHard.show();
CPG->ourScenSel->bExpert.show();
CPG->ourScenSel->bImpossible.show();
}
//blit texts
CSDL_Ext::printAt(CGI->generaltexth->zelp[21].second,420,25,GEOR13);
CSDL_Ext::printAt(CGI->generaltexth->allTexts[496],420,135,GEOR13);
@ -1324,8 +1345,6 @@ void MapSel::printSelectedInfo()
CSDL_Ext::printAt(CGI->generaltexth->allTexts[390],420,406,GEOR13,zwykly);
CSDL_Ext::printAt(CGI->generaltexth->allTexts[391],585,406,GEOR13,zwykly);
CMapInfo &selMap = selectedMap();
int temp = selMap.victoryCondition.condition+1;
if (temp>20) temp=0;
std::string sss = CGI->generaltexth->victoryConditions[temp];
@ -2165,13 +2184,15 @@ StartInfo CPreGame::runLoop()
{
highlightButton(1,2);
current->highlighted=1;
(this->*(current->fNewGame))();
if(current->fNewGame)
(this->*(current->fNewGame))();
}
else if (isItIn(&current->lLoadGame,sEvent.motion.x,sEvent.motion.y))
{
highlightButton(2,2);
current->highlighted=2;
(this->*(current->fLoadGame))();
if(current->fLoadGame)
(this->*(current->fLoadGame))();
}
else if (isItIn(&current->lHighScores,sEvent.motion.x,sEvent.motion.y))
{
@ -2187,7 +2208,8 @@ StartInfo CPreGame::runLoop()
{
highlightButton(5,2);
current->highlighted=5;
(this->*(current->fQuit))();
if(current->fQuit)
(this->*(current->fQuit))();
}
}
else if ((sEvent.type==SDL_MOUSEBUTTONDOWN) && (sEvent.button.button == SDL_BUTTON_RIGHT))
@ -2376,16 +2398,19 @@ void CPreGame::initLoadMenu()
ourLoadMenu->lLoadGame.w=ourLoadMenu->loadGame->ourImages[0].bitmap->w;
ourLoadMenu->lLoadGame.x=568;
ourLoadMenu->lLoadGame.y=120;
ourLoadMenu->fLoadGame = NULL;
//campaign
ourLoadMenu->lHighScores.h=ourLoadMenu->highScores->ourImages[0].bitmap->h;
ourLoadMenu->lHighScores.w=ourLoadMenu->highScores->ourImages[0].bitmap->w;
ourLoadMenu->lHighScores.x=541;
ourLoadMenu->lHighScores.y=233;
ourLoadMenu->fHighScores = NULL;
//tutorial
ourLoadMenu->lCredits.h=ourLoadMenu->credits->ourImages[0].bitmap->h;
ourLoadMenu->lCredits.w=ourLoadMenu->credits->ourImages[0].bitmap->w;
ourLoadMenu->lCredits.x=545;
ourLoadMenu->lCredits.y=358;
ourLoadMenu->fCredits = NULL;
//back
ourLoadMenu->lQuit.h=ourLoadMenu->quit->ourImages[0].bitmap->h;
ourLoadMenu->lQuit.w=ourLoadMenu->quit->ourImages[0].bitmap->w;

View File

@ -34,7 +34,7 @@ struct StartInfo
}
};
ui8 mode; //0 - new game; 1 - load game
si32 difficulty; //0=easy; 4=impossible
ui8 difficulty; //0=easy; 4=impossible
std::vector<PlayerSettings> playerInfos;
ui8 turnTime; //in minutes, 0=unlimited
std::string mapname;

View File

@ -31,6 +31,7 @@ namespace intpr = boost::interprocess;
void CClient::init()
{
IObjectInterface::cb = this;
serv = NULL;
gs = NULL;
cb = NULL;
@ -58,6 +59,13 @@ void CClient::process(int what)
static BattleAction curbaction;
switch (what)
{
case 95: //system message
{
std::string m;
*serv >> m;
tlog4 << "System message from server: " << m << std::endl;
break;
}
case 100: //one of our interfaces has turn
{
ui8 player;
@ -635,12 +643,13 @@ void CClient::load( const std::string & fname )
tlog0 <<"Restarting server: "<<tmh.getDif()<<std::endl;
{
ui32 ver;
char sig[8];
CMapHeader dum;
CGI->mh = new CMapHandler();
CLoadFile lf(fname + ".vlgm1");
lf >> sig >> dum;
lf >> sig >> ver >> dum >> *sig;
tlog0 <<"Reading save signature: "<<tmh.getDif()<<std::endl;
lf >> *VLC;

View File

@ -475,25 +475,9 @@ void CGHeroInstance::initHero(int SUBID)
void CGHeroInstance::initHero()
{
if(!defInfo)
{
defInfo = new CGDefInfo();
defInfo->id = 34;
defInfo->subid = subID;
defInfo->printPriority = 0;
defInfo->visitDir = 0xff;
}
initHeroDefInfo();
if(!type)
type = VLC->heroh->heroes[subID];
for(int i=0;i<6;i++)
{
defInfo->blockMap[i]=255;
defInfo->visitMap[i]=0;
}
defInfo->handler=NULL;
defInfo->blockMap[5] = 253;
defInfo->visitMap[5] = 2;
artifWorn[16] = 3;
if(type->heroType % 2 == 1) //it's a magical hero
{
@ -559,6 +543,25 @@ void CGHeroInstance::initHero()
boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);
}
void CGHeroInstance::initHeroDefInfo()
{
if(!defInfo)
{
defInfo = new CGDefInfo();
defInfo->id = 34;
defInfo->subid = subID;
defInfo->printPriority = 0;
defInfo->visitDir = 0xff;
}
for(int i=0;i<6;i++)
{
defInfo->blockMap[i]=255;
defInfo->visitMap[i]=0;
}
defInfo->handler=NULL;
defInfo->blockMap[5] = 253;
defInfo->visitMap[5] = 2;
}
CGHeroInstance::~CGHeroInstance()
{
}
@ -597,6 +600,7 @@ void CGHeroInstance::initObj()
{
blockVisit = true;
}
int CGTownInstance::getSightDistance() const //returns sight distance
{
return 10;
@ -743,7 +747,7 @@ void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
if(visitors.find(h->id)==visitors.end())
{
onNAHeroVisit(h->id, false);
if(ID != 102 && ID!=4) //not tree nor arena
if(ID != 102 && ID!=4 && ID!=41) //not tree nor arena nor library of enlightenment
cb->setObjProperty(id,4,h->id); //add to the visitors
}
else
@ -804,6 +808,9 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const
ot = 146;
val = 1;
break;
case 41:
ot = 66;
break;
}
if (!alreadyVisited)
{
@ -891,6 +898,30 @@ void CGVisitableOPH::onNAHeroVisit(int heroID, bool alreadyVisited) const
}
break;
}
case 41:
{
const CGHeroInstance *h = cb->getHero(heroID);
if(h->level < 10 - 2*h->getSecSkillLevel(4)) //not enough level
{
InfoWindow iw;
iw.player = cb->getOwner(heroID);
iw.text << std::pair<ui8,ui32>(11,68);
cb->showInfoDialog(&iw);
}
else
{
cb->setObjProperty(this->id,4,heroID); //add to the visitors
cb->changePrimSkill(heroID,0,2);
cb->changePrimSkill(heroID,1,2);
cb->changePrimSkill(heroID,2,2);
cb->changePrimSkill(heroID,3,2);
InfoWindow iw;
iw.player = cb->getOwner(heroID);
iw.text << std::pair<ui8,ui32>(11,66);
cb->showInfoDialog(&iw);
}
break;
}
}
}
else
@ -929,6 +960,8 @@ const std::string & CGVisitableOPH::getHoverText() const
case 102:
pom = 18;
break;
case 41:
break;
default:
throw std::string("Wrong CGVisitableOPH object ID!\n");
}
@ -1276,6 +1309,7 @@ void CGArtifact::initObj()
void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
{
cb->giveHeroArtifact(subID,h->id,-2);
cb->removeObject(id);
InfoWindow iw;
iw.player = h->tempOwner;
iw.components.push_back(Component(4,subID,0,0));

View File

@ -221,6 +221,7 @@ public:
void initHero();
void initHero(int SUBID);
void initHeroDefInfo();
CGHeroInstance();
virtual ~CGHeroInstance();

View File

@ -17,7 +17,7 @@
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_array.hpp>
const int version = 63;
const ui32 version = 63;
class CConnection;
namespace mpl = boost::mpl;
@ -189,7 +189,7 @@ public:
}
template<class T>
COSer & operator&(T & t)
COSer & operator&(const T & t)
{
return * this->This() << t;
}

View File

@ -1418,6 +1418,7 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
case 32: // Garden of Revelation
case 100: //Learning Stone
case 102: //Tree of Knowledge
case 41: //Library of Enlightenment
{
nobj = new CGVisitableOPH();
break;
@ -1584,6 +1585,9 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
{
art->army = readCreatureSet(bufor,i,7,(version>RoE));
}
}
if(areSettings || defInfo->id==93)
{
art->spell = readNormalNr(bufor,i);
i+=4;
}

5
map.h
View File

@ -229,6 +229,7 @@ public:
class DLL_EXPORT CMapInfo : public CMapHeader
{
public:
ui8 seldiff; //selected difficulty (only in saved games)
std::string filename;
std::string date;
int playerAmnt, humenPlayers;
@ -366,10 +367,12 @@ struct DLL_EXPORT Mapa : public CMapHeader
if(h.saving) //create vector with all defs used on map
{
for(int i=0; i<objects.size(); i++)
objects[i]->defInfo->serial = -1; //set serial to serial -1 - indicates that def is not present in defs vector
if(objects[i])
objects[i]->defInfo->serial = -1; //set serial to serial -1 - indicates that def is not present in defs vector
for(int i=0; i<objects.size(); i++)
{
if(!objects[i]) continue;
CGDefInfo *cur = objects[i]->defInfo;
if(cur->serial < 0)
{

View File

@ -413,18 +413,19 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
std::string fname;
Mapa * mapa;
c >> fname;
{
sendMessageTo(c,"Serializing game info...");
CSaveFile save(std::string("Games") + PATHSEPARATOR + fname + ".vlgm1");
char hlp[8] = "VCMISVG";
save << hlp << static_cast<CMapHeader&>(*gs->map) << *VLC << gs;
save << hlp << version << static_cast<CMapHeader&>(*gs->map) << gs->scenarioOps->difficulty << *VLC << gs;
}
{
sendMessageTo(c,"Serializing server info...");
CSaveFile save(std::string("Games") + PATHSEPARATOR + fname + ".vsgm1");
save << *this;
}
sendMessageTo(c,"Game has been succesfully saved!");
break;
}
case 99: //end!
@ -2342,4 +2343,9 @@ void CGameHandler::setObjProperty( int objid, int prop, int val )
sob.what = prop;
sob.val = val;
sendAndApply(&sob);
}
void CGameHandler::sendMessageTo( CConnection &c, std::string message )
{
c << ui16(95) << message;
}

View File

@ -62,6 +62,7 @@ class CGameHandler : public IGameCallback
PlayerStatuses states; //player color -> player state
std::set<CConnection*> conns;
void sendMessageTo(CConnection &c, std::string message);
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
void moveStack(int stack, int dest);
void startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero

View File

@ -169,11 +169,12 @@ void CVCMIServer::loadGame( CConnection *c )
*c >> clients >> fname; //how many clients should be connected - TODO: support more than one
{
ui32 ver;
char sig[8];
CMapHeader dum;
CLoadFile lf(fname + ".vlgm1");
lf >> sig >> dum;
lf >> sig >> ver >> dum >> *sig;
tlog0 <<"Reading save signature"<<std::endl;
lf >> *VLC;