diff --git a/CAdvmapInterface.cpp b/CAdvmapInterface.cpp index 9d7828c92..cc8acd8bb 100644 --- a/CAdvmapInterface.cpp +++ b/CAdvmapInterface.cpp @@ -295,7 +295,7 @@ void CTerrainRect::clickLeft(tribool down) int3 mp = whichTileIsIt(); if ((mp.x<0) || (mp.y<0)) return; - std::vector < const CGObjectInstance * > objs = LOCPLINT->cb->getBlockingObjs(mp); + std::vector < const CGObjectInstance * > objs; if (LOCPLINT->adventureInt->selection->ID != HEROI_TYPE) { if (currentPath) @@ -304,9 +304,10 @@ void CTerrainRect::clickLeft(tribool down) delete currentPath; currentPath = NULL; } + objs = LOCPLINT->cb->getBlockingObjs(mp); for(int i=0; iID == 98) //town + if(objs[i]->ID == 98 && objs[i]->tempOwner == LOCPLINT->playerID) //town { if(LOCPLINT->adventureInt->selection == (objs[i])) { @@ -318,7 +319,7 @@ void CTerrainRect::clickLeft(tribool down) return; } } - else if(objs[i]->ID == 34) + else if(objs[i]->ID == 34 && objs[i]->tempOwner == LOCPLINT->playerID) { LOCPLINT->adventureInt->select(static_cast(objs[i])); return; @@ -328,20 +329,28 @@ void CTerrainRect::clickLeft(tribool down) } else { + objs = LOCPLINT->cb->getVisitableObjs(mp); for(int i=0; iID == 98) //town + if(objs[i]->ID == 98) + goto endchkpt; + } + objs = LOCPLINT->cb->getBlockingObjs(mp); + for(int i=0; iID == 98 && objs[i]->tempOwner == LOCPLINT->playerID) //town { LOCPLINT->adventureInt->select(static_cast(objs[i])); return; } - else if(objs[i]->ID == 34 && LOCPLINT->adventureInt->selection == (objs[i])) + else if(objs[i]->ID == 34 && objs[i]->tempOwner == LOCPLINT->playerID && LOCPLINT->adventureInt->selection == (objs[i])) { LOCPLINT->openHeroWindow(static_cast(objs[i])); return; } } } +endchkpt: bool mres =true; if (currentPath) { @@ -413,13 +422,14 @@ void CTerrainRect::mouseMoved (SDL_MouseMotionEvent & sEvent) objs = LOCPLINT->cb->getBlockingObjs(pom); for(int i=0; iID == 98) //town + if(objs[i]->ID == 98 && objs[i]->tempOwner == LOCPLINT->playerID) //town { CGI->curh->changeGraphic(0,3); return; } else if(objs[i]->ID == 34 //mouse over hero - && (objs[i]==LOCPLINT->adventureInt->selection || LOCPLINT->adventureInt->selection->ID==98)) //this hero is selected or we've selected a town + && (objs[i]==LOCPLINT->adventureInt->selection || LOCPLINT->adventureInt->selection->ID==98) + && objs[i]->tempOwner == LOCPLINT->playerID) //this hero is selected or we've selected a town { CGI->curh->changeGraphic(0,2); return; @@ -1068,6 +1078,7 @@ void CAdvMapInt::show(SDL_Surface *to) } void CAdvMapInt::hide() { + CGI->curh->changeGraphic(0,0); kingOverview.deactivate(); underground.deactivate(); questlog.deactivate(); diff --git a/CBattleInterface.cpp b/CBattleInterface.cpp index 2da667920..d77f4e2d0 100644 --- a/CBattleInterface.cpp +++ b/CBattleInterface.cpp @@ -188,6 +188,7 @@ CBattleInterface::~CBattleInterface() void CBattleInterface::activate() { + subInt = NULL; bOptions->activate(); bSurrender->activate(); bFlee->activate(); @@ -458,11 +459,11 @@ void CBattleInterface::stackKilled(int ID, int dmg, int killed, int IDby, bool b creAnims[ID]->setType(5); //death for(int i=0; iframesInGroup(5); ++i) { + if(i) + creAnims[ID]->incrementFrame(); show(); CSDL_Ext::update(); SDL_framerateDelay(LOCPLINT->mainFPSmng); - if((animCount+1)%4) - creAnims[ID]->incrementFrame(); } printConsoleAttacked(ID, dmg, killed, IDby); diff --git a/CCallback.cpp b/CCallback.cpp index f7ac2fa4a..66dfeeac7 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -1,23 +1,24 @@ #include "stdafx.h" -#include "CCallback.h" -#include "CPathfinder.h" -#include "hch/CHeroHandler.h" -#include "hch/CTownHandler.h" -#include "CGameInfo.h" -#include "hch/CAmbarCendamo.h" -#include "mapHandler.h" -#include "CGameState.h" -#include "CPlayerInterface.h" -#include "hch/CGeneralTextHandler.h" #include "CAdvmapInterface.h" +#include "CCallback.h" +#include "CGameInfo.h" +#include "CGameState.h" +#include "CPathfinder.h" +#include "CPlayerInterface.h" #include "CPlayerInterface.h" -#include "hch/CBuildingHandler.h" -#include "hch/CObjectHandler.h" -#include "lib/Connection.h" #include "client/Client.h" -#include -#include +#include "hch/CAmbarCendamo.h" +#include "hch/CBuildingHandler.h" +#include "hch/CDefObjInfoHandler.h" +#include "hch/CGeneralTextHandler.h" +#include "hch/CHeroHandler.h" +#include "hch/CObjectHandler.h" +#include "hch/CTownHandler.h" +#include "lib/Connection.h" #include "lib/NetPacks.h" +#include "mapHandler.h" +#include +#include #include #ifdef min #undef min @@ -276,7 +277,7 @@ std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur) { for (int j=0;j<(*i).second.towns.size();j++) { - if ( ( isVisible((*i).second.towns[j]->pos,player) ) || (*i).first==player) + if ( ( isVisible((*i).second.towns[j],player) ) || (*i).first==player) { ret.push_back((*i).second.towns[j]); } @@ -305,6 +306,22 @@ bool CCallback::isVisible(int3 pos) return isVisible(pos,player); } +bool CCallback::isVisible( CGObjectInstance *obj, int Player ) +{ + //object is visible when at least one blocked tile is visible + for(int fx=0; fx<8; ++fx) + { + for(int fy=0; fy<6; ++fy) + { + int3 pos = obj->pos + int3(fx-7,fy-5,0); + if(gs->map->isInTheMap(pos) + && !((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1) + && isVisible(pos,Player) ) + return true; + } + } + return false; +} int CCallback::getMyColor() { return player; @@ -377,29 +394,6 @@ bool CCallback::swapArifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHe return false; *cl->serv << ui16(509) << hero1->id << pos1 << hero2->id << pos2; return true; - //if(!hero1 || !hero2) //incorrect data - // return false; - //CGHeroInstance * Uhero1 = const_cast(hero1); - //CGHeroInstance * Uhero2 = const_cast(hero2); - - //if(worn1 && worn2) - //{ - // std::swap(Uhero1->artifWorn[pos1], Uhero2->artifWorn[pos2]); - //} - //else if(worn1 && !worn2) - //{ - // std::swap(Uhero1->artifWorn[pos1], Uhero2->artifacts[pos2]); - //} - //else if(!worn1 && worn2) - //{ - // std::swap(Uhero1->artifacts[pos1], Uhero2->artifWorn[pos2]); - //} - //else - //{ - // std::swap(Uhero1->artifacts[pos1], Uhero2->artifacts[pos2]); - //} - // - //return true; } bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID) @@ -526,8 +520,10 @@ void CCallback::buyArtifact(const CGHeroInstance *hero, int aid) std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos ) { - boost::shared_lock lock(*gs->mx); std::vector ret; + if(!gs->map->isInTheMap(pos)) + return ret; + boost::shared_lock lock(*gs->mx); BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects) ret.push_back(obj); return ret; @@ -535,8 +531,10 @@ std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos ) std::vector < const CGObjectInstance * > CCallback::getVisitableObjs( int3 pos ) { - boost::shared_lock lock(*gs->mx); std::vector ret; + if(!gs->map->isInTheMap(pos)) + return ret; + boost::shared_lock lock(*gs->mx); BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].visitableObjects) ret.push_back(obj); return ret; diff --git a/CCallback.h b/CCallback.h index d929254bb..b7bd02867 100644 --- a/CCallback.h +++ b/CCallback.h @@ -96,6 +96,7 @@ private: CGameState * gs; CClient *cl; bool isVisible(int3 pos, int Player); + bool isVisible(CGObjectInstance *obj, int Player); protected: int player; diff --git a/CCastleInterface.cpp b/CCastleInterface.cpp index da5f85d47..3271b3cc0 100644 --- a/CCastleInterface.cpp +++ b/CCastleInterface.cpp @@ -508,8 +508,8 @@ void CCastleInterface::buildingClicked(int building) } case 7: case 8: case 9: { - CFortScreen *fs = new CFortScreen(this); deactivate(); + CFortScreen *fs = new CFortScreen(this); fs->activate(); fs->show(); break; @@ -533,7 +533,7 @@ void CCastleInterface::buildingClicked(int building) if(vstd::contains(hero->artifWorn,ui16(aid+9))) //hero already has machine possible = false; deactivate(); - (new CBlacksmithDialog(possible,142+aid,aid,hero->id))->activate(); + (new CBlacksmithDialog(possible,CArtHandler::convertMachineID(aid,false),aid,hero->id))->activate(); break; } default: @@ -677,8 +677,6 @@ void CCastleInterface::activate() subInt->activate(); return; } - else - subInt = NULL; showing = true; townlist->activate(); garr->activate(); @@ -1256,6 +1254,7 @@ CHallInterface::CBuildWindow::~CBuildWindow() CFortScreen::~CFortScreen() { + LOCPLINT->curint->subInt = NULL; for(int i=0;icurint = this; + LOCPLINT->curint->subInt = this; exit->activate(); for (int i=0;icurint->subInt = this; bg = NULL; exit = new AdventureMapButton(CGI->townh->tcommands[8],"",boost::bind(&CFortScreen::close,this),748,556,"TPMAGE1.DEF",false,NULL,false); positions += genRect(126,386,10,22),genRect(126,386,404,22), @@ -1398,7 +1398,6 @@ void CFortScreen::RecArea::clickLeft (tribool down) { LOCPLINT->curint->deactivate(); CRecrutationWindow *rw = LOCPLINT->castleInt->showRecruitmentWindow(bid); - rw->buy->callback += boost::bind(&CFortScreen::draw, static_cast(LOCPLINT->curint), LOCPLINT->castleInt, false); } ClickableL::clickLeft(down); } @@ -1542,7 +1541,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, int aid, i blitAt(bg2,64,50,bmp); SDL_FreeSurface(bg2); CCreatureAnimation cra(CGI->creh->creatures[creMachineID].animDefName); - cra.nextFrameMiddle(bmp,165,130,true,false); + cra.nextFrameMiddle(bmp,170,120,true,false); char pom[75]; sprintf(pom,CGI->generaltexth->allTexts[274].c_str(),CGI->creh->creatures[creMachineID].nameSing.c_str()); //build a new ... printAtMiddle(pom,165,28,GEORXX,tytulowy,bmp); diff --git a/CGameInterface.h b/CGameInterface.h index b44462e16..c1a75432e 100644 --- a/CGameInterface.h +++ b/CGameInterface.h @@ -62,6 +62,7 @@ public: virtual void tileHidden(int3 pos){}; virtual void tileRevealed(int3 pos){}; virtual void yourTurn(){}; + virtual void availableCreaturesChanged(const CGTownInstance *town){}; //battle call-ins //virtual void actionFinished(BattleAction action){};//occurs AFTER every action taken by any stack or by the hero diff --git a/CGameState.cpp b/CGameState.cpp index 0a5efd3bf..5b76fc0f5 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -566,7 +566,7 @@ void CGameState::apply(IPack * pack) int CGameState::pickHero(int owner) { int h=-1; - if(map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero + if(!map->getHero(h = scenarioOps->getIthPlayersSettings(owner).hero,0) && h>=0) //we haven't used selected hero return h; int f = scenarioOps->getIthPlayersSettings(owner).castle; int i=0; @@ -615,7 +615,14 @@ std::pair CGameState::pickObject(CGObjectInstance *obj) return std::pair(34,pickHero(obj->tempOwner)); } case 71: //random monster - return std::pair(54,ran()%(VLC->creh->creatures.size())); + { + int r; + do + { + r = ran()%197; + } while (vstd::contains(VLC->creh->notUsedMonsters,r)); + return std::pair(54,r); + } case 72: //random monster lvl1 return std::pair(54,VLC->creh->levelCreatures[1][ran()%VLC->creh->levelCreatures[1].size()]->idNumber); case 73: //random monster lvl2 @@ -788,7 +795,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur) map->defs.insert(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]); if(!cur->defInfo) { - std::cout<<"Missing def declaration for "<ID<<" "<subID<ID<<" "<subID<artifWorn[16] = 3; break; default: - pom-=145; - vhi->artifWorn[12+pom] = 3+pom; + vhi->artifWorn[9+CArtHandler::convertMachineID(pom,true)] = CArtHandler::convertMachineID(pom,true); break; } continue; @@ -1188,7 +1194,7 @@ int CGameState::battleGetStack(int pos) if(curB->stacks[g]->position == pos || ( curB->stacks[g]->creature->isDoubleWide() && ( (curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos) || - (!curB->stacks[g]->attackerOwned && curB->stacks[g]->position-1 == pos) + (!curB->stacks[g]->attackerOwned && curB->stacks[g]->position+1 == pos) ) ) ) diff --git a/CMT.cpp b/CMT.cpp index bbd814918..62982a5fa 100644 --- a/CMT.cpp +++ b/CMT.cpp @@ -142,7 +142,14 @@ int main(int argc, _TCHAR* argv[]) THC tmh.getDif();pomtime.getDif();//reset timers cgi->pathf = new CPathfinder(); THC std::cout<<"\tPathfinder: "<consoleh->runConsole(); + if(argc>1) + { + std::cout << "Special mode without support for console!" << std::endl; + } + else + { + cgi->consoleh->runConsole(); + } THC std::cout<<"\tCallback and console: "<screenh->updateScreen(); } + +void CPlayerInterface::availableCreaturesChanged( const CGTownInstance *town ) +{ + boost::unique_lock un(*pim); + if(curint == castleInt) + { + CFortScreen *fs = dynamic_cast(curint->subInt); + if(fs) + fs->draw(castleInt,false); + } +} CStatusBar::CStatusBar(int x, int y, std::string name, int maxw) { bg=BitmapHandler::loadBitmap(name); diff --git a/CPlayerInterface.h b/CPlayerInterface.h index 1217d6611..330aba524 100644 --- a/CPlayerInterface.h +++ b/CPlayerInterface.h @@ -353,6 +353,7 @@ public: void tileHidden(int3 pos); void tileRevealed(int3 pos); void yourTurn(); + void availableCreaturesChanged(const CGTownInstance *town); //for battles //void actionFinished(BattleAction action);//occurs AFTER every action taken by any stack or by the hero //void actionStarted(BattleAction action);//occurs BEFORE every action taken by any stack or by the hero diff --git a/client/Client.cpp b/client/Client.cpp index f2e61dd3b..44d91e6fe 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -350,7 +350,9 @@ void CClient::process(int what) *serv >> ns; std::cout << "Setting available creatures in " << ns.tid << std::endl; gs->apply(&ns); - //TODO: do we need to inform interface? + CGTownInstance *t = gs->getTown(ns.tid); + if(vstd::contains(playerint,t->tempOwner)) + playerint[t->tempOwner]->availableCreaturesChanged(t); break; } case 508: @@ -527,8 +529,13 @@ void CClient::process(int what) } void CClient::waitForMoveAndSend(int color) { - BattleAction ba = playerint[color]->activeStack(gs->curB->activeStack); - *serv << ui16(3002) << ba; + try + { + BattleAction ba = playerint[color]->activeStack(gs->curB->activeStack); + *serv << ui16(3002) << ba; + return; + }HANDLE_EXCEPTION + std::cout << "We should not be here!" << std::endl; } void CClient::run() { diff --git a/hch/CArtHandler.cpp b/hch/CArtHandler.cpp index 2761aadbe..19f7323fc 100644 --- a/hch/CArtHandler.cpp +++ b/hch/CArtHandler.cpp @@ -60,3 +60,34 @@ void CArtHandler::loadArtifacts() } } } + +int CArtHandler::convertMachineID(int id, bool creToArt ) +{ + int dif = 142; + if(creToArt) + { + switch (id) + { + case 147: + dif--; + break; + case 148: + dif++; + break; + } + dif = -dif; + } + else + { + switch (id) + { + case 6: + dif--; + break; + case 5: + dif++; + break; + } + } + return id + dif; +} \ No newline at end of file diff --git a/hch/CArtHandler.h b/hch/CArtHandler.h index 0a66329de..85f2ff3bf 100644 --- a/hch/CArtHandler.h +++ b/hch/CArtHandler.h @@ -29,6 +29,7 @@ public: std::vector treasures, minors, majors, relics; std::vector artifacts; void loadArtifacts(); + static int convertMachineID(int id, bool creToArt); CArtHandler(); }; diff --git a/hch/CCreatureHandler.cpp b/hch/CCreatureHandler.cpp index 6912c3db6..fed96081b 100644 --- a/hch/CCreatureHandler.cpp +++ b/hch/CCreatureHandler.cpp @@ -3,11 +3,13 @@ #include "CCreatureHandler.h" #include "CLodHandler.h" #include +#include #include #include #include #include #include "../lib/VCMI_Lib.h" +using namespace boost::assign; extern CLodHandler * bitmaph; CCreatureHandler::CCreatureHandler() { @@ -61,6 +63,7 @@ si32 CCreature::maxAmount(const std::vector &res) const //how many creatur void CCreatureHandler::loadCreatures() { + notUsedMonsters += 122,124,126,128,145,146,147,148,149,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191; std::string buf = bitmaph->getTextFile("ZCRTRAIT.TXT"); int andame = buf.size(); int i=0; //buf iterator @@ -439,6 +442,8 @@ void CCreatureHandler::loadCreatures() idToProjectileSpin[id] = spin; } inp2.close(); + + creatures[123].abilityRefs += "DOUBLE_WIDE"; } void CCreatureHandler::loadAnimationInfo() diff --git a/hch/CCreatureHandler.h b/hch/CCreatureHandler.h index de2d9524d..46b6b9463 100644 --- a/hch/CCreatureHandler.h +++ b/hch/CCreatureHandler.h @@ -49,6 +49,7 @@ public: class DLL_EXPORT CCreatureHandler { public: + std::set notUsedMonsters; std::vector creatures; //creature ID -> creature info std::map > levelCreatures; //level -> list of creatures std::map nameToID; diff --git a/map.cpp b/map.cpp index 55b8cf3e8..1133ef31d 100644 --- a/map.cpp +++ b/map.cpp @@ -1169,6 +1169,7 @@ void Mapa::loadPlayerInfo( int &pom, unsigned char * bufor, int &i ) players[pom].canComputerPlay = bufor[i++]; if ((!(players[pom].canHumanPlay || players[pom].canComputerPlay))) { + memset(&players[pom],0,sizeof(PlayerInfo)); switch(version) { case SoD: case WoG: @@ -1187,7 +1188,9 @@ void Mapa::loadPlayerInfo( int &pom, unsigned char * bufor, int &i ) players[pom].AITactic = bufor[i++]; if(version == SoD || version == WoG) - players[pom].p7= bufor[i++]; + players[pom].p7= bufor[i++]; + else + players[pom].p7= -1; players[pom].allowedFactions = 0; players[pom].allowedFactions += bufor[i++]; @@ -2451,4 +2454,11 @@ void Mapa::readEvents( unsigned char * bufor, int &i ) i+=18; events.push_back(ne); } +} + +bool Mapa::isInTheMap( int3 pos ) +{ + if(pos.x<0 || pos.y<0 || pos.z<0 || pos.x >= width || pos.y >= height || pos.z > twoLevel) + return false; + else return true; } \ No newline at end of file diff --git a/map.h b/map.h index 1e97ac100..091dacf7a 100644 --- a/map.h +++ b/map.h @@ -498,9 +498,12 @@ struct DLL_EXPORT Mapa void loadHero( CGObjectInstance * &nobj, unsigned char * bufor, int &i); void loadTown( CGObjectInstance * &nobj, unsigned char * bufor, int &i); int loadSeerHut( unsigned char * bufor, int i, CGObjectInstance * nobj); + + void addBlockVisTiles(CGObjectInstance * obj); void removeBlockVisTiles(CGObjectInstance * obj); Mapa(std::string filename); //creates map structure from .h3m file CGHeroInstance * getHero(int ID, int mode=0); + bool isInTheMap(int3 pos); }; #endif //MAPD_H diff --git a/mapHandler.cpp b/mapHandler.cpp index fcd50a405..99e570419 100644 --- a/mapHandler.cpp +++ b/mapHandler.cpp @@ -526,6 +526,8 @@ void CMapHandler::init() else n = CGI->state->capitols[i%ccc]; ifs >> n->name; + if(!n) + std::cout << "*HUGE* Warning - missing town def for " << i << std::endl; map->defs.insert(n); } std::cout<<"\tLoading town def info: "<