diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 4ecb14d96..008ca606f 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -896,7 +896,7 @@ void VCAI::makeTurn() { MAKING_TURN; boost::shared_lock gsLock(cb->getGsMutex()); - setThreadName(-1, "VCAI::makeTurn"); + setThreadName("VCAI::makeTurn"); BNLOG("Player %d starting turn", playerID); INDENT; @@ -2178,7 +2178,7 @@ void VCAI::requestActionASAP(boost::function whatToDo) boost::barrier b(2); boost::thread newThread([&b,this,whatToDo]() { - setThreadName(-1, "VCAI::requestActionASAP::helper"); + setThreadName("VCAI::requestActionASAP::helper"); SET_GLOBAL_STATE(this); boost::shared_lock gsLock(cb->getGsMutex()); b.wait(); diff --git a/README.linux b/README.linux index a49b40c0b..762174a15 100644 --- a/README.linux +++ b/README.linux @@ -1,8 +1,12 @@ This readme covers VCMI compilation on Unix-like systems. -For complete installation instructions see VCMI wiki: -http://wiki.vcmi.eu/index.php?title=Installation_on_Linux +To run the game you will need: +1) Heroes 3 data files (SoD or Complete editions); +2) Unofficial WoG addon +2) VCMI data pack (http://download.vcmi.eu/vcmi-data_0.89.tar.gz) +For complete installation instructions see VCMI wiki: +http://wiki.vcmi.eu/index.php?title=Installation_on_Linux#Preparing_data I. Prerequisites @@ -80,7 +84,7 @@ Since VCMI is still in development, there's no install procedure, although this make install You also need to update configuration files: cp /PATH_TO_SOURCE/config /DATA_PATH/vcmi -In this case you'll have to manually update after any changes. +In this case you'll have to manually update these files after any changes. For more permament solution you should use links as described below. For development puposes, it's better to use links. Go diff --git a/client/CAnimation.cpp b/client/CAnimation.cpp index 4d837a2b0..e3dca5489 100644 --- a/client/CAnimation.cpp +++ b/client/CAnimation.cpp @@ -1345,12 +1345,15 @@ CCreatureAnim::CCreatureAnim(int x, int y, std::string name, Rect picPos, ui8 fl pos.h = picPos.h; }; -void CCreatureAnim::loopPreview() +void CCreatureAnim::loopPreview(bool warMachine) { std::vector available; - static const EAnimType previewList[] = {HOLDING, HITTED, DEFENCE, ATTACK_FRONT, CAST_FRONT}; + + static const EAnimType creaPreviewList[] = {HOLDING, HITTED, DEFENCE, ATTACK_FRONT, CAST_FRONT}; + static const EAnimType machPreviewList[] = {HOLDING, MOVING, SHOOT_UP, SHOOT_FRONT, SHOOT_DOWN}; + auto & previewList = warMachine ? machPreviewList : creaPreviewList; - for (size_t i=0; i<5; i++) + for (size_t i=0; i= available.size()) { + EAnimType type; if ( anim.size(MOVING) == 0 )//no moving animation present - addLast( HOLDING ); + type = HOLDING; else - addLast( MOVING ) ; + type = MOVING; + + //display this anim for ~1 second (time is random, but it looks good) + for (size_t i=0; i< 12/anim.size(type) + 1; i++) + addLast(type); } else addLast(available[rnd]); @@ -1410,9 +1418,9 @@ void CCreatureAnim::reset() set(HOLDING); } -void CCreatureAnim::startPreview() +void CCreatureAnim::startPreview(bool warMachine) { - callback = boost::bind(&CCreatureAnim::loopPreview,this); + callback = boost::bind(&CCreatureAnim::loopPreview, this, warMachine); } void CCreatureAnim::clearAndSet(EAnimType type) diff --git a/client/CAnimation.h b/client/CAnimation.h index 23f3bb6e6..58174396c 100644 --- a/client/CAnimation.h +++ b/client/CAnimation.h @@ -352,8 +352,8 @@ private: //queue of animations waiting to be displayed std::queue queue; - //this funcction is used as callback if preview flag was set during construction - void loopPreview(); + //this function is used as callback if preview flag was set during construction + void loopPreview(bool warMachine); public: //change anim to next if queue is not empty, call callback othervice @@ -362,7 +362,7 @@ public: //add sequence to the end of queue void addLast(EAnimType newType); - void startPreview(); + void startPreview(bool warMachine); //clear queue and set animation to this sequence void clearAndSet(EAnimType type); diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index c76bfddb6..b8aaaee50 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -878,7 +878,7 @@ void CSelectionScreen::difficultyChange( int to ) void CSelectionScreen::handleConnection() { - setThreadName(-1, "CSelectionScreen::handleConnection"); + setThreadName("CSelectionScreen::handleConnection"); try { assert(serv); diff --git a/client/Client.cpp b/client/Client.cpp index 3227298b7..d2b1a8a4f 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -133,7 +133,7 @@ void CClient::waitForMoveAndSend(int color) void CClient::run() { - setThreadName(-1, "CClient::run"); + setThreadName("CClient::run"); try { CPack *pack = NULL; @@ -614,7 +614,7 @@ void CClient::calculatePaths(const CGHeroInstance *h) void CClient::commenceTacticPhaseForInt(CBattleGameInterface *battleInt) { - setThreadName(-1, "CClient::commenceTacticPhaseForInt"); + setThreadName("CClient::commenceTacticPhaseForInt"); try { battleInt->yourTacticPhase(gs->curB->tacticDistance); @@ -708,7 +708,7 @@ CServerHandler::~CServerHandler() void CServerHandler::callServer() { - setThreadName(-1, "CServerHandler::callServer"); + setThreadName("CServerHandler::callServer"); std::string logName = GVCMIDirs.UserPath + "/server_log.txt"; std::string comm = GameConstants::BIN_DIR + GameConstants::PATH_SEPARATOR + GameConstants::SERVER_NAME + " " + port + " > " + logName; int result = std::system(comm.c_str()); diff --git a/client/GUIClasses.cpp b/client/GUIClasses.cpp index 86ab8290f..b076d0a9b 100644 --- a/client/GUIClasses.cpp +++ b/client/GUIClasses.cpp @@ -1037,8 +1037,8 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool An bg = new CPicture(graphics->backgroundsm[cre->faction],0,0,false); bg->needRefresh = true; anim = new CCreatureAnim(0, 0, cre->animDefName, Rect()); - anim->clipRect(cre->doubleWide?170:150, 155, bg->pos.w, bg->pos.h); - anim->startPreview(); + anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h); + anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON)); pos.w = bg->pos.w; pos.h = bg->pos.h; @@ -1201,9 +1201,6 @@ void CRecruitmentWindow::buy() onRecruit(crid, slider->value); if(level >= 0) close(); - else - slider->moveTo(0); - } void CRecruitmentWindow::showAll(SDL_Surface * to) @@ -1261,13 +1258,14 @@ void CRecruitmentWindow::availableCreaturesChanged() { OBJ_CONSTRUCTION_CAPTURING_ALL; + size_t selectedIndex = 0; + + if (!cards.empty() && selected) // find position of selected item + selectedIndex = std::find(cards.begin(), cards.end(), selected) - cards.begin(); + //deselect card select(nullptr); - static const int SPACE_BETWEEN = 18; - static const int CREATURE_WIDTH = 102; - static const int TOTAL_CREATURE_WIDTH = SPACE_BETWEEN + CREATURE_WIDTH; - //delete old cards BOOST_FOREACH(auto & card, cards) delete card; @@ -1288,15 +1286,33 @@ void CRecruitmentWindow::availableCreaturesChanged() assert(!cards.empty()); + const int creatureWidth = 102; + + //normal distance between cards - 18px + int requiredSpace = 18; + //maximum distance we can use without reaching window borders + int availableSpace = pos.w - 50 - creatureWidth * cards.size(); + + if (cards.size() > 1) // avoid division by zero + availableSpace /= cards.size() - 1; + else + availableSpace = 0; + + assert(availableSpace >= 0); + + const int spaceBetween = std::min(requiredSpace, availableSpace); + const int totalCreatureWidth = spaceBetween + creatureWidth; + //now we know total amount of cards and can move them to correct position - int curx = 192 + 50 - (CREATURE_WIDTH*cards.size()/2) - (SPACE_BETWEEN*(cards.size()-1)/2); + int curx = pos.w / 2 - (creatureWidth*cards.size()/2) - (spaceBetween*(cards.size()-1)/2); BOOST_FOREACH(auto & card, cards) { card->moveBy(Point(curx, 64)); - curx += TOTAL_CREATURE_WIDTH; + curx += totalCreatureWidth; } - select(cards.front()); + //restore selection + select(cards[selectedIndex]); if(slider->value) slider->moveTo(0); diff --git a/client/UIFramework/CGuiHandler.cpp b/client/UIFramework/CGuiHandler.cpp index 5e386355f..5bfbe4ec9 100644 --- a/client/UIFramework/CGuiHandler.cpp +++ b/client/UIFramework/CGuiHandler.cpp @@ -342,7 +342,7 @@ void CGuiHandler::fakeMouseMove() void CGuiHandler::run() { - setThreadName(-1, "CGuiHandler::run"); + setThreadName("CGuiHandler::run"); inGuiThread.reset(new bool(true)); try { diff --git a/config/creatures.json b/config/creatures.json index 8d9657885..6d8ac4780 100644 --- a/config/creatures.json +++ b/config/creatures.json @@ -1943,7 +1943,9 @@ "level": 0, "name": [ "SylvanCentaur" ], "faction": -1, - "defname": "ZM192Z.DEF" + "defname": "ZM192Z.DEF", + "projectile_defname": "PELFX.DEF", + "projectile_spin": false }, { diff --git a/lib/CConsoleHandler.cpp b/lib/CConsoleHandler.cpp index 7f5f4406d..f9e36e3a0 100644 --- a/lib/CConsoleHandler.cpp +++ b/lib/CConsoleHandler.cpp @@ -180,7 +180,7 @@ void CConsoleHandler::setColor(int level) int CConsoleHandler::run() { - setThreadName(-1, "CConsoleHandler::run"); + setThreadName("CConsoleHandler::run"); //disabling sync to make in_avail() work (othervice always returns 0) std::ios::sync_with_stdio(false); std::string buffer; diff --git a/lib/CGameInterface.h b/lib/CGameInterface.h index 41ab649ba..c24129843 100644 --- a/lib/CGameInterface.h +++ b/lib/CGameInterface.h @@ -74,10 +74,18 @@ class CGameInterface : public CBattleGameInterface, public IGameEventsReceiver public: virtual void init(CCallback * CB){}; virtual void yourTurn(){}; //called AFTER playerStartsTurn(player) - virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector &skills, boost::function &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id + + //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id + virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector &skills, boost::function &callback)=0; virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector skills, boost::function &callback)=0; - virtual void showBlockingDialog(const std::string &text, const std::vector &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. - virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done + + // Show a dialog, player must take decision. If selection then he has to choose between one of given components, + // if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called + // with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. + virtual void showBlockingDialog(const std::string &text, const std::vector &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; + + // all stacks operations between these objects become allowed, interface has to call onEnd when done + virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function &onEnd) = 0; virtual void serialize(COSer &h, const int version){}; //saving virtual void serialize(CISer &h, const int version){}; //loading virtual void finish(){}; //if for some reason we want to end diff --git a/lib/CThreadHelper.cpp b/lib/CThreadHelper.cpp index 90239c766..8cb63830f 100644 --- a/lib/CThreadHelper.cpp +++ b/lib/CThreadHelper.cpp @@ -45,7 +45,9 @@ void CThreadHelper::processTasks() } } -void setThreadName(long threadID, const std::string &name) +// set name for this thread. +// NOTE: on *nix string will be trimmed to 16 symbols +void setThreadName(const std::string &name) { #ifdef _WIN32 //follows http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx @@ -62,7 +64,7 @@ void setThreadName(long threadID, const std::string &name) THREADNAME_INFO info; info.dwType = 0x1000; info.szName = name.c_str(); - info.dwThreadID = threadID; + info.dwThreadID = -1; info.dwFlags = 0; __try diff --git a/lib/CThreadHelper.h b/lib/CThreadHelper.h index 72b9a92ce..139384719 100644 --- a/lib/CThreadHelper.h +++ b/lib/CThreadHelper.h @@ -34,7 +34,7 @@ template inline void setData(T * data, boost::function func) *data = func(); } -void DLL_LINKAGE setThreadName(long threadID, const std::string &name); +void DLL_LINKAGE setThreadName(const std::string &name); #define GET_DATA(TYPE,DESTINATION,FUNCTION_TO_GET) \ (boost::bind(&setData,&DESTINATION,FUNCTION_TO_GET)) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 35a71b446..fe40c83a6 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -847,7 +847,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons } void CGameHandler::handleConnection(std::set players, CConnection &c) { - setThreadName(-1, "CGameHandler::handleConnection"); + setThreadName("CGameHandler::handleConnection"); srand(time(NULL)); try