1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-25 00:37:24 +02:00

* possibly fixed bug with the mage guild when no spells available

* events won't be shown and won't block movement
* casualties among hero army and neutral creatures are saved
* it's possible to build lighthouse
* increased thread-safety (may prevent some crashes)
* minor fixes
This commit is contained in:
Michał W. Urbańczyk
2008-09-20 18:30:37 +00:00
parent 8c937d92ad
commit 48cb63f144
17 changed files with 157 additions and 69 deletions

View File

@ -1440,7 +1440,7 @@ CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner)
int sp = owner->town->spellsAtLevel(i+1,false); int sp = owner->town->spellsAtLevel(i+1,false);
for(int j=0; j<sp; j++) for(int j=0; j<sp; j++)
{ {
if(i < owner->town->mageGuildLevel()) if(i<owner->town->mageGuildLevel() && owner->town->spells[i].size()<j)
{ {
spells.push_back(Scroll(&CGI->spellh->spells[owner->town->spells[i][j]])); spells.push_back(Scroll(&CGI->spellh->spells[owner->town->spells[i][j]]));
spells[spells.size()-1].pos = positions[i][j]; spells[spells.size()-1].pos = positions[i][j];

View File

@ -505,6 +505,12 @@ void CGameState::applyNL(IPack * pack)
case 1001://set object property case 1001://set object property
{ {
SetObjectProperty *p = static_cast<SetObjectProperty*>(pack); SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
if(p->what == 3) //set creatures amount
{
tlog5 << "Setting creatures amount in " << p->id << std::endl;
static_cast<CCreatureObjInfo*>(map->objects[p->id]->info)->number = p->val;
break;
}
ui8 CGObjectInstance::*point; ui8 CGObjectInstance::*point;
switch(p->what) switch(p->what)
{ {
@ -894,7 +900,12 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
{ {
randomizeObject(map->objects[no]); randomizeObject(map->objects[no]);
if(map->objects[no]->ID==26) if(map->objects[no]->ID==26)
{
map->objects[no]->defInfo->handler=NULL; map->objects[no]->defInfo->handler=NULL;
map->removeBlockVisTiles(map->objects[no]);
map->objects[no]->defInfo->blockMap[5] = 255;
map->addBlockVisTiles(map->objects[no]);
}
map->objects[no]->hoverName = VLC->objh->names[map->objects[no]->ID]; map->objects[no]->hoverName = VLC->objh->names[map->objects[no]->ID];
} }
//std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl; //std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;

View File

@ -791,40 +791,40 @@ void CMonsterS::newObject(int objid)
switch(VLC->creh->creatures[os->subID].level) switch(VLC->creh->creatures[os->subID].level)
{ {
case 1: case 1:
amounts[objid] = rand()%31+20; cb->setAmount(objid,rand()%31+20);
break; break;
case 2: case 2:
amounts[objid] = rand()%16+15; cb->setAmount(objid,rand()%16+15);
break; break;
case 3: case 3:
amounts[objid] = rand()%16+10; cb->setAmount(objid,rand()%16+10);
break; break;
case 4: case 4:
amounts[objid] = rand()%11+10; cb->setAmount(objid,rand()%11+10);
break; break;
case 5: case 5:
amounts[objid] = rand()%9+8; cb->setAmount(objid,rand()%9+8);
break; break;
case 6: case 6:
amounts[objid] = rand()%8+5; cb->setAmount(objid,rand()%8+5);
break; break;
case 7: case 7:
amounts[objid] = rand()%7+3; cb->setAmount(objid,rand()%7+3);
break; break;
case 8: case 8:
amounts[objid] = rand()%4+2; cb->setAmount(objid,rand()%4+2);
break; break;
case 9: case 9:
amounts[objid] = rand()%3+2; cb->setAmount(objid,rand()%3+2);
break; break;
case 10: case 10:
amounts[objid] = rand()%3+1; cb->setAmount(objid,rand()%3+1);
break; break;
} }
MetaString ms; MetaString ms;
int pom = CCreature::getQuantityID(amounts[objid]); int pom = CCreature::getQuantityID(((CCreatureObjInfo*)(os->info))->number);
pom = 174 + 3*pom + 1; pom = 174 + 3*pom + 1;
ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,os->subID); ms << std::pair<ui8,ui32>(6,pom) << " " << std::pair<ui8,ui32>(7,os->subID);
cb->setHoverName(objid,&ms); cb->setHoverName(objid,&ms);
@ -834,7 +834,7 @@ void CMonsterS::onHeroVisit(int objid, int heroID)
DEFOS; DEFOS;
CCreatureSet set; CCreatureSet set;
//TODO: zrobic secik w sposob wyrafinowany //TODO: zrobic secik w sposob wyrafinowany
set.slots[0] = std::pair<ui32,si32>(os->subID,amounts[objid]); set.slots[0] = std::pair<ui32,si32>(os->subID,((CCreatureObjInfo*)(os->info))->number);
cb->startBattle(heroID,set,os->pos,boost::bind(&CMonsterS::endBattleWith,this,os,_1)); cb->startBattle(heroID,set,os->pos,boost::bind(&CMonsterS::endBattleWith,this,os,_1));
} }
std::vector<int> CMonsterS::yourObjects() //returns IDs of objects which are handled by script std::vector<int> CMonsterS::yourObjects() //returns IDs of objects which are handled by script
@ -852,7 +852,11 @@ void CMonsterS::endBattleWith(const CGObjectInstance *monster, BattleResult *res
} }
else else
{ {
//TODO: remove casualties int killedAmount=0;
for(std::set<std::pair<ui32,si32> >::iterator i=result->casualties[1].begin(); i!=result->casualties[1].end(); i++)
if(i->first == monster->subID)
killedAmount += i->second;
cb->setAmount(monster->id,((CCreatureObjInfo*)(monster->info))->number - killedAmount);
} }
} }

1
CLua.h
View File

@ -171,7 +171,6 @@ public:
class CMonsterS : public CCPPObjectScript class CMonsterS : public CCPPObjectScript
{ {
public: public:
std::map<int, int> amounts; //monster id -> stack quantity
CMonsterS(CScriptCallback * CB):CCPPObjectScript(CB){}; CMonsterS(CScriptCallback * CB):CCPPObjectScript(CB){};
void newObject(int objid); void newObject(int objid);
void onHeroVisit(int objid, int heroID); void onHeroVisit(int objid, int heroID);

View File

@ -221,7 +221,7 @@ int main(int argc, char** argv)
while(1) //main SDL events loop while(1) //main SDL events loop
{ {
SDL_WaitEvent(&ev); SDL_WaitEvent(&ev);
if(ev.type==SDL_QUIT) if((ev.type==SDL_QUIT) || (ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
{ {
cl.close(); cl.close();
#ifndef __unix__ #ifndef __unix__

View File

@ -172,7 +172,10 @@ void CPathfinder::AddNeighbors(vector<Coordinate>* branch)
bool pass = true; //checking for allowed visiting direction bool pass = true; //checking for allowed visiting direction
for(int b=0; b<CGI->mh->ttiles[i][j][node.z].tileInfo->visitableObjects.size(); ++b) //checking destination tile for(int b=0; b<CGI->mh->ttiles[i][j][node.z].tileInfo->visitableObjects.size(); ++b) //checking destination tile
{ {
CGDefInfo * di = CGI->mh->ttiles[i][j][node.z].tileInfo->visitableObjects[b]->defInfo; const TerrainTile * pom = CGI->mh->ttiles[i][j][node.z].tileInfo;
if(!vstd::contains(pom->blockingObjects,pom->visitableObjects[b]))
break;
CGDefInfo * di = pom->visitableObjects[b]->defInfo;
if( (i == node.x-1 && j == node.y-1) && !(di->visitDir & (1<<4)) ) if( (i == node.x-1 && j == node.y-1) && !(di->visitDir & (1<<4)) )
{ {
pass = false; break; pass = false; break;
@ -208,7 +211,10 @@ void CPathfinder::AddNeighbors(vector<Coordinate>* branch)
} }
for(int b=0; b<CGI->mh->ttiles[node.x][node.y][node.z].tileInfo->visitableObjects.size(); ++b) //checking source tile for(int b=0; b<CGI->mh->ttiles[node.x][node.y][node.z].tileInfo->visitableObjects.size(); ++b) //checking source tile
{ {
CGDefInfo * di = CGI->mh->ttiles[node.x][node.y][node.z].tileInfo->visitableObjects[b]->defInfo; const TerrainTile * pom = CGI->mh->ttiles[node.x][node.y][node.z].tileInfo;
if(!vstd::contains(pom->blockingObjects,pom->visitableObjects[b]))
break;
CGDefInfo * di = pom->visitableObjects[b]->defInfo;
if( (i == node.x-1 && j == node.y-1) && !(di->visitDir & (1<<0)) ) if( (i == node.x-1 && j == node.y-1) && !(di->visitDir & (1<<0)) )
{ {
pass = false; break; pass = false; break;
@ -269,11 +275,12 @@ void CPathfinder::CalcH(Coordinate* node)
* If there is fog of war on the node. * If there is fog of war on the node.
* => Impossible to move there. * => Impossible to move there.
*/ */
if( (CGI->mh->ttiles[node->x][node->y][node->z].tileInfo->blocked && !(node->x==End.x && node->y==End.y && CGI->mh->ttiles[node->x][node->y][node->z].tileInfo->visitable)) || const TerrainTile *pom = CGI->mh->ttiles[node->x][node->y][node->z].tileInfo;
(CGI->mh->ttiles[node->x][node->y][node->z].tileInfo->tertype==rock) || if( (pom->blocked && !(node->x==End.x && node->y==End.y && pom->visitable)) ||
((blockLandSea) && (CGI->mh->ttiles[node->x][node->y][node->z].tileInfo->tertype==water)) || (pom->tertype==rock) ||
((blockLandSea) && (pom->tertype==water)) ||
(!CGI->state->players[Hero->tempOwner].fogOfWarMap[node->x][node->y][node->z]) || (!CGI->state->players[Hero->tempOwner].fogOfWarMap[node->x][node->y][node->z]) ||
((!blockLandSea) && (CGI->mh->ttiles[node->x][node->y][node->z].tileInfo->tertype!=water))) ((!blockLandSea) && (pom->tertype!=water)))
{ {
//Impossible. //Impossible.

View File

@ -957,7 +957,7 @@ CPlayerInterface::CPlayerInterface(int Player, int serial)
playerID=Player; playerID=Player;
serialID=serial; serialID=serial;
human=true; human=true;
pim = new boost::mutex; pim = new boost::recursive_mutex;
showingDialog = new CondSh<bool>(false); showingDialog = new CondSh<bool>(false);
} }
CPlayerInterface::~CPlayerInterface() CPlayerInterface::~CPlayerInterface()
@ -1100,7 +1100,7 @@ int getDir(int3 src, int3 dst)
} }
void CPlayerInterface::heroMoved(const HeroMoveDetails & details) void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
//initializing objects and performing first step of move //initializing objects and performing first step of move
const CGHeroInstance * ho = details.ho; //object representing this hero const CGHeroInstance * ho = details.ho; //object representing this hero
int3 hp = details.src; int3 hp = details.src;
@ -1536,7 +1536,7 @@ void CPlayerInterface::heroMoved(const HeroMoveDetails & details)
} }
void CPlayerInterface::heroKilled(const CGHeroInstance* hero) void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
graphics->heroWins.erase(hero->ID); graphics->heroWins.erase(hero->ID);
adventureInt->heroList.updateHList(); adventureInt->heroList.updateHList();
} }
@ -1721,19 +1721,6 @@ void CPlayerInterface::handleKeyDown(SDL_Event *sEvent)
LOCPLINT->adventureInt->scrollingDown = true; LOCPLINT->adventureInt->scrollingDown = true;
break; break;
} }
case (SDLK_F4):
{
if(sEvent->key.keysym.mod & KMOD_LALT) //Alt+F4
{
exit(0);
break;
}
}
//case (SDLK_q):
// {
// exit(0);
// break;
// }
case (SDLK_u): case (SDLK_u):
{ {
adventureInt->underground.clickLeft(true); adventureInt->underground.clickLeft(true);
@ -1853,7 +1840,7 @@ 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)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
SDL_FreeSurface(graphics->heroWins[hero->subID]);//TODO: moznaby zmieniac jedynie fragment bitmapy zwiazany z dana umiejetnoscia SDL_FreeSurface(graphics->heroWins[hero->subID]);//TODO: moznaby zmieniac jedynie fragment bitmapy zwiazany z dana umiejetnoscia
graphics->heroWins[hero->subID] = infoWin(hero); //a nie przerysowywac calosc. Troche roboty, obecnie chyba nie wartej swieczki. graphics->heroWins[hero->subID] = infoWin(hero); //a nie przerysowywac calosc. Troche roboty, obecnie chyba nie wartej swieczki.
if (adventureInt->selection == hero) if (adventureInt->selection == hero)
@ -1863,7 +1850,7 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, int
void CPlayerInterface::receivedResource(int type, int val) void CPlayerInterface::receivedResource(int type, int val)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
if(!curint->subInt) if(!curint->subInt)
adventureInt->resdatabar.draw(); adventureInt->resdatabar.draw();
} }
@ -1871,7 +1858,7 @@ void CPlayerInterface::receivedResource(int type, int val)
void CPlayerInterface::showSelDialog(std::string &text, const std::vector<Component*> &components, ui32 askID) void CPlayerInterface::showSelDialog(std::string &text, const std::vector<Component*> &components, ui32 askID)
//void CPlayerInterface::showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID) //void CPlayerInterface::showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
adventureInt->hide(); //dezaktywacja starego interfejsu adventureInt->hide(); //dezaktywacja starego interfejsu
std::vector<CSelectableComponent*> intComps; std::vector<CSelectableComponent*> intComps;
for(int i=0;i<components.size();i++) for(int i=0;i<components.size();i++)
@ -1892,14 +1879,14 @@ void CPlayerInterface::heroGotLevel(const CGHeroInstance *hero, int pskill, std:
while(showingDialog->data) while(showingDialog->data)
showingDialog->cond.wait(un); showingDialog->cond.wait(un);
} }
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
CLevelWindow *lw = new CLevelWindow(hero,pskill,skills,callback); CLevelWindow *lw = new CLevelWindow(hero,pskill,skills,callback);
curint->deactivate(); curint->deactivate();
lw->activate(); lw->activate();
} }
void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town) void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
//redraw infowindow //redraw infowindow
SDL_FreeSurface(graphics->townWins[town->id]); SDL_FreeSurface(graphics->townWins[town->id]);
graphics->townWins[town->id] = infoWin(town); graphics->townWins[town->id] = infoWin(town);
@ -1928,12 +1915,12 @@ void CPlayerInterface::heroVisitsTown(const CGHeroInstance* hero, const CGTownIn
{ {
if(hero->tempOwner != town->tempOwner) if(hero->tempOwner != town->tempOwner)
return; return;
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
openTownWindow(town); openTownWindow(town);
} }
void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj) void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
if(obj->ID == 34) //hero if(obj->ID == 34) //hero
{ {
const CGHeroInstance * hh; const CGHeroInstance * hh;
@ -1977,7 +1964,7 @@ void CPlayerInterface::garrisonChanged(const CGObjectInstance * obj)
} }
void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
switch (buildingID) switch (buildingID)
{ {
case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 15: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 15:
@ -2004,7 +1991,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
void CPlayerInterface::battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side) //called by engine when battle starts; side=0 - left, side=1 - right void CPlayerInterface::battleStart(CCreatureSet *army1, CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side) //called by engine when battle starts; side=0 - left, side=1 - right
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
curint->deactivate(); curint->deactivate();
curint = new CBattleInterface(army1,army2,hero1,hero2); curint = new CBattleInterface(army1,army2,hero1,hero2);
curint->activate(); curint->activate();
@ -2033,7 +2020,7 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
{ {
CBattleInterface *b = dynamic_cast<CBattleInterface*>(curint); CBattleInterface *b = dynamic_cast<CBattleInterface*>(curint);
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
b->stackActivated(stackID); b->stackActivated(stackID);
} }
//wait till BattleInterface sets its command //wait till BattleInterface sets its command
@ -2057,7 +2044,7 @@ void CPlayerInterface::battleEnd(BattleResult *br)
void CPlayerInterface::battleResultQuited() void CPlayerInterface::battleResultQuited()
{ {
//boost::unique_lock<boost::mutex> un(*pim); //boost::unique_lock<boost::recursive_mutex> un(*pim);
((CBattleInterface*)curint)->resWindow->deactivate(); ((CBattleInterface*)curint)->resWindow->deactivate();
objsToBlit -= curint; objsToBlit -= curint;
delete curint; delete curint;
@ -2067,12 +2054,12 @@ void CPlayerInterface::battleResultQuited()
void CPlayerInterface::battleStackMoved(int ID, int dest, bool startMoving, bool endMoving) void CPlayerInterface::battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest, startMoving, endMoving); dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest, startMoving, endMoving);
} }
void CPlayerInterface::battleAttack(BattleAttack *ba) void CPlayerInterface::battleAttack(BattleAttack *ba)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
if(ba->shot()) if(ba->shot())
dynamic_cast<CBattleInterface*>(curint)->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked)); dynamic_cast<CBattleInterface*>(curint)->stackIsShooting(ba->stackAttacking,cb->battleGetPos(ba->bsa.stackAttacked));
else else
@ -2094,7 +2081,7 @@ void CPlayerInterface::battleStackIsShooting(int ID, int dest)
void CPlayerInterface::showComp(SComponent comp) void CPlayerInterface::showComp(SComponent comp)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
adventureInt->infoBar.showComp(&comp,4000); adventureInt->infoBar.showComp(&comp,4000);
} }
@ -2108,6 +2095,7 @@ void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<Compo
void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<SComponent*> & components) void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<SComponent*> & components)
{ {
showingDialog->set(true); showingDialog->set(true);
boost::unique_lock<boost::recursive_mutex> un(*pim);
curint->deactivate(); //dezaktywacja starego interfejsu curint->deactivate(); //dezaktywacja starego interfejsu
std::vector<std::pair<std::string,CFunctionList<void()> > > pom; std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
@ -2120,6 +2108,7 @@ void CPlayerInterface::showInfoDialog(std::string &text, const std::vector<SComp
} }
void CPlayerInterface::showYesNoDialog(std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps) void CPlayerInterface::showYesNoDialog(std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool deactivateCur, bool DelComps)
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim);
if(deactivateCur) if(deactivateCur)
curint->deactivate(); //dezaktywacja starego interfejsu curint->deactivate(); //dezaktywacja starego interfejsu
std::vector<std::pair<std::string,CFunctionList<void()> > > pom; std::vector<std::pair<std::string,CFunctionList<void()> > > pom;
@ -2142,7 +2131,7 @@ void CPlayerInterface::showYesNoDialog(std::string &text, const std::vector<SCom
void CPlayerInterface::showYesNoDialog( std::string &text, const std::vector<Component*> &components, ui32 askID ) void CPlayerInterface::showYesNoDialog( std::string &text, const std::vector<Component*> &components, ui32 askID )
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
curint->deactivate(); //dezaktywacja starego interfejsu curint->deactivate(); //dezaktywacja starego interfejsu
std::vector<SComponent*> intComps; std::vector<SComponent*> intComps;
@ -2164,20 +2153,24 @@ void CPlayerInterface::showYesNoDialog( std::string &text, const std::vector<Com
} }
void CPlayerInterface::removeObjToBlit(IShowable* obj) void CPlayerInterface::removeObjToBlit(IShowable* obj)
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim);
objsToBlit.erase objsToBlit.erase
(std::find(objsToBlit.begin(),objsToBlit.end(),obj)); (std::find(objsToBlit.begin(),objsToBlit.end(),obj));
//delete obj; //delete obj;
} }
void CPlayerInterface::tileRevealed(int3 pos) void CPlayerInterface::tileRevealed(int3 pos)
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim);
adventureInt->minimap.showTile(pos); adventureInt->minimap.showTile(pos);
} }
void CPlayerInterface::tileHidden(int3 pos) void CPlayerInterface::tileHidden(int3 pos)
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim);
adventureInt->minimap.hideTile(pos); adventureInt->minimap.hideTile(pos);
} }
void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero) void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim);
adventureInt->heroWindow->setHero(hero); adventureInt->heroWindow->setHero(hero);
this->objsToBlit.push_back(adventureInt->heroWindow); this->objsToBlit.push_back(adventureInt->heroWindow);
curint->deactivate(); curint->deactivate();
@ -2191,7 +2184,7 @@ void CPlayerInterface::openHeroWindow(const CGHeroInstance *hero)
void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero) void CPlayerInterface::heroArtifactSetChanged(const CGHeroInstance*hero)
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
if(curint->subInt == adventureInt->heroWindow) if(curint->subInt == adventureInt->heroWindow)
{ {
adventureInt->heroWindow->deactivate(); adventureInt->heroWindow->deactivate();
@ -2236,7 +2229,7 @@ void CPlayerInterface::updateWater()
void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town ) void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town )
{ {
boost::unique_lock<boost::mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);
if(curint == castleInt) if(curint == castleInt)
{ {
CFortScreen *fs = dynamic_cast<CFortScreen*>(curint->subInt); CFortScreen *fs = dynamic_cast<CFortScreen*>(curint->subInt);

View File

@ -30,6 +30,7 @@ template <typename T> struct CondSh;
namespace boost namespace boost
{ {
class mutex; class mutex;
class recursive_mutex;
}; };
class IShowable class IShowable
@ -316,7 +317,7 @@ class CPlayerInterface : public CGameInterface
public: public:
//minor interfaces //minor interfaces
CondSh<bool> *showingDialog; CondSh<bool> *showingDialog;
boost::mutex *pim; boost::recursive_mutex *pim;
bool makingTurn; bool makingTurn;
SDL_Event * current; SDL_Event * current;
CMainInterface *curint; CMainInterface *curint;

View File

@ -1,3 +1,32 @@
0.62 -> 0.63 (Sep 28 2008???)
* very significant optimization of battles
* battle summary window
* fixed crashbug on exiting battle
* mostly done morketplace
* confirm window is shown before retreat
* it's possible to use other port than 3030 by passing it as an additional argument
* removed some redundant warnings
* stack queue in battle (shows when 'c' key is pressed)
* partially done spellbook
* fixed crashbug with battles on swamps and rough terrain
* counterattacks
* heroes learn spells in towns
* it's possible to attack enemy hero
* setting army formation
* fixed bug with disappearing head of a hero in adventure map
* some objects are no longer accessible from the top
* no tooltips for objects under FoW
* working resource silo
* neutral monster army disappears when defeated
* Alt+F4 quits the game
* dead stacks won't be displayed in battle queue
* possibly fixed bug with the mage guild when no spells available
* events won't be shown and won't block movement
* casualties among hero army and neutral creatures are saved
* it's possible to build lighthouse
* increased thread-safety (may prevent some crashes)
* minor fixes
0.61 -> 0.62 (Sep 01 2008) 0.61 -> 0.62 (Sep 01 2008)
General: General:
* restructured to the server-client model * restructured to the server-client model

View File

@ -2,7 +2,7 @@
0 0
TPTHBKCS.BMP TPTHBKCS.BMP
10 11 12 13 | 7 8 9 | 5 22 | 16 10 11 12 13 | 7 8 9 | 5 22 | 16
14 15 | 0 1 2 3 | 6 14 15 | 0 1 2 3 | 6 17
21 | 18 19 21 | 18 19
30 37 | 31 38 | 32 39 | 33 40 30 37 | 31 38 | 32 39 | 33 40
34 41 | 35 42 | 36 43 34 41 | 35 42 | 36 43

View File

@ -16,7 +16,7 @@ typedef boost::int8_t si8; //signed int 8 bits (1 byte)
#define THC #define THC
#endif #endif
#define NAME_VER ("VCMI 0.63") #define NAME_VER ("VCMI 0.62b")
#define CONSOLE_LOGGING_LEVEL 5 #define CONSOLE_LOGGING_LEVEL 5
#define FILE_LOGGING_LEVEL 6 #define FILE_LOGGING_LEVEL 6

View File

@ -286,7 +286,7 @@ struct InfoWindow : public CPack<InfoWindow> //103 - displays simple info windo
struct SetObjectProperty : public CPack<SetObjectProperty>//1001 struct SetObjectProperty : public CPack<SetObjectProperty>//1001
{ {
ui32 id; ui32 id;
ui8 what; //1 - owner; 2 - blockvis ui8 what; //1 - owner; 2 - blockvis; 3 - amount (works with creatures stacks)
ui32 val; ui32 val;
SetObjectProperty(){type = 1001;}; SetObjectProperty(){type = 1001;};
SetObjectProperty(ui32 ID, ui8 What, ui32 Val):id(ID),what(What),val(Val){type = 1001;}; SetObjectProperty(ui32 ID, ui8 What, ui32 Val):id(ID),what(What),val(Val){type = 1001;};

View File

@ -500,7 +500,7 @@ void Mapa::removeBlockVisTiles(CGObjectInstance * obj)
if(!((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1)) if(!((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1))
{ {
curt.blockingObjects -= obj; curt.blockingObjects -= obj;
curt.blocked = curt.visitableObjects.size(); curt.blocked = curt.blockingObjects.size();
} }
} }
} }

View File

@ -458,6 +458,8 @@ void CMapHandler::initObjectRects()
} }
void processDef (CGDefInfo* def) void processDef (CGDefInfo* def)
{ {
if(def->id == 26)
return;
def->handler=CDefHandler::giveDef(def->name); def->handler=CDefHandler::giveDef(def->name);
def->width = def->handler->ourImages[0].bitmap->w/32; def->width = def->handler->ourImages[0].bitmap->w/32;
def->height = def->handler->ourImages[0].bitmap->h/32; def->height = def->handler->ourImages[0].bitmap->h/32;

View File

@ -241,6 +241,23 @@ void CGameHandler::changePrimSkill(int ID, int which, int val, bool abs)
} }
} }
CCreatureSet takeCasualties(int color, const CCreatureSet &set, BattleInfo *bat)
{
CCreatureSet ret(set);
for(int i=0; i<bat->stacks.size();i++)
{
CStack *st = bat->stacks[i];
if(st->owner==color && vstd::contains(set.slots,st->slot) && st->amount < set.slots.find(st->slot)->second.second)
{
if(st->alive())
ret.slots[st->slot].second = st->amount;
else
ret.slots.erase(st->slot);
}
}
return ret;
}
void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb) void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb)
{ {
BattleInfo *curB = new BattleInfo; BattleInfo *curB = new BattleInfo;
@ -287,15 +304,33 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
if(hero2 && hero2->tempOwner<PLAYER_LIMIT) if(hero2 && hero2->tempOwner<PLAYER_LIMIT)
states.setFlag(hero2->tempOwner,&PlayerStatus::engagedIntoBattle,false); states.setFlag(hero2->tempOwner,&PlayerStatus::engagedIntoBattle,false);
//casualties among heroes armies
SetGarrisons sg;
if(hero1)
sg.garrs[hero1->id] = takeCasualties(hero1->tempOwner,hero1->army,gs->curB);
if(hero2)
sg.garrs[hero2->id] = takeCasualties(hero2->tempOwner,hero2->army,gs->curB);
sendAndApply(&sg);
//end battle, remove all info, free memory //end battle, remove all info, free memory
sendAndApply(battleResult.data); sendAndApply(battleResult.data);
if(cb) if(cb)
cb(battleResult.data); cb(battleResult.data);
//if one hero has lost we will erase him
if(battleResult.data->winner!=0 && hero1)
{
RemoveObject ro(hero1->id);
sendAndApply(&ro);
}
if(battleResult.data->winner!=1 && hero2)
{
RemoveObject ro(hero2->id);
sendAndApply(&ro);
}
delete battleResult.data; delete battleResult.data;
//for(int i=0;i<stacks.size();i++)
// delete stacks[i];
//delete curB;
//curB = NULL;
} }
void prepareAttack(BattleAttack &bat, CStack *att, CStack *def) void prepareAttack(BattleAttack &bat, CStack *att, CStack *def)
{ {
@ -349,7 +384,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
states.setFlag(gs->currentPlayer,&PlayerStatus::makingTurn,false); states.setFlag(gs->currentPlayer,&PlayerStatus::makingTurn,false);
break; break;
} }
case 500: case 500: //dismiss hero
{ {
si32 id; si32 id;
c >> id; c >> id;
@ -521,7 +556,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
sendAndApply(&sg); sendAndApply(&sg);
break; break;
} }
case 503: case 503: //disband creature
{ {
si32 id; si32 id;
ui8 pos; ui8 pos;
@ -533,7 +568,7 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
sendAndApply(&sg); sendAndApply(&sg);
break; break;
} }
case 504: case 504: //build structure
{ {
si32 tid, bid; si32 tid, bid;
c >> tid >> bid; c >> tid >> bid;
@ -1368,7 +1403,7 @@ void CGameHandler::giveSpells( const CGTownInstance *t, const CGHeroInstance *h
cs.learn = true; cs.learn = true;
for(int i=0; i<std::min(t->mageGuildLevel(),h->getSecSkillLevel(7)+4);i++) for(int i=0; i<std::min(t->mageGuildLevel(),h->getSecSkillLevel(7)+4);i++)
{ {
for(int j=0; j<t->spellsAtLevel(i+1,true); j++) for(int j=0; j<t->spellsAtLevel(i+1,true) && j<t->spells[i].size(); j++)
{ {
if(!vstd::contains(h->spells,t->spells[i][j])) if(!vstd::contains(h->spells,t->spells[i][j]))
cs.spells.insert(t->spells[i][j]); cs.spells.insert(t->spells[i][j]);

View File

@ -33,6 +33,12 @@ void CScriptCallback::removeObject(int objid)
gh->sendAndApply(&ro); gh->sendAndApply(&ro);
} }
void CScriptCallback::setAmount(int objid, ui32 val)
{
SetObjectProperty sop(objid,3,val);
gh->sendAndApply(&sop);
}
void CScriptCallback::setOwner(int objid, ui8 owner) void CScriptCallback::setOwner(int objid, ui8 owner)
{ {
SetObjectProperty sop(objid,1,owner); SetObjectProperty sop(objid,1,owner);

View File

@ -55,6 +55,7 @@ public:
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack
void startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero void startBattle(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattle(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army void startBattle(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void setAmount(int objid, ui32 val);
//friends //friends
friend class CGameHandler; friend class CGameHandler;