فهرست منبع

- fixed #582, #1019 and #1022
- linux readme tweaks

Ivan Savenko 13 سال پیش
والد
کامیت
613172fa45

+ 2 - 2
AI/VCAI/VCAI.cpp

@@ -896,7 +896,7 @@ void VCAI::makeTurn()
 {
 	MAKING_TURN;
 	boost::shared_lock<boost::shared_mutex> 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<void()> 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<boost::shared_mutex> gsLock(cb->getGsMutex());
 		b.wait();

+ 7 - 3
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

+ 15 - 7
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<EAnimType> 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<ARRAY_COUNT(previewList); i++)
 		if (anim.size(previewList[i]))
 			available.push_back(previewList[i]);
 
@@ -1358,10 +1361,15 @@ void CCreatureAnim::loopPreview()
 
 	if (rnd >= 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)

+ 3 - 3
client/CAnimation.h

@@ -352,8 +352,8 @@ private:
 	//queue of animations waiting to be displayed
 	std::queue<EAnimType> 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);

+ 1 - 1
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);

+ 3 - 3
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());

+ 28 - 12
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);

+ 1 - 1
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
 	{

+ 3 - 1
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
 			},
 
 			{

+ 1 - 1
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;

+ 11 - 3
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<ui16> &skills, boost::function<void(ui32)> &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<ui16> &skills, boost::function<void(ui32)> &callback)=0;
 	virtual	void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, boost::function<void(ui32)> &callback)=0;
-	virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &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<void()> &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<Component> &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<void()> &onEnd) = 0;
 	virtual void serialize(COSer<CSaveFile> &h, const int version){}; //saving
 	virtual void serialize(CISer<CLoadFile> &h, const int version){}; //loading
 	virtual void finish(){}; //if for some reason we want to end

+ 4 - 2
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

+ 1 - 1
lib/CThreadHelper.h

@@ -34,7 +34,7 @@ template <typename T> inline void setData(T * data, boost::function<T()> 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<TYPE>,&DESTINATION,FUNCTION_TO_GET))

+ 1 - 1
server/CGameHandler.cpp

@@ -847,7 +847,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
 }
 void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 {
-	setThreadName(-1, "CGameHandler::handleConnection");
+	setThreadName("CGameHandler::handleConnection");
 	srand(time(NULL));
 
 	try