浏览代码

Miscellaneous fixes:
- proper block of "back" button in campaign menu.
- proper block of AI switch in battles
- vertical garrisons can now be attacked from top
- better UI logging, vcmi will print to log file all pressed buttons
- server will not try to build already existing building

Ivan Savenko 11 年之前
父节点
当前提交
c5b74a2dce

+ 5 - 2
client/CPreGame.cpp

@@ -3139,8 +3139,6 @@ void CBonusSelection::init()
 	startB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::startMap, this), 475, 536, "CBBEGIB.DEF", SDLK_RETURN);
 	restartB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::restartMap, this), 475, 536, "CBRESTB.DEF", SDLK_RETURN);
 	backB = new CAdventureMapButton("", "", boost::bind(&CBonusSelection::goBack, this), 624, 536, "CBCANCB.DEF", SDLK_ESCAPE);
-	// block back button for in-progress campaigns. May not be H3 behaviour but avoids the crash
-	backB->block(!ourCampaign->mapsConquered.empty());
 
 	//campaign name
 	if (ourCampaign->camp->header.name.length())
@@ -3299,12 +3297,17 @@ void CBonusSelection::selectMap(int mapNr, bool initialSelect)
 			// draw start button
 			restartB->disable();
 			startB->enable();
+			if (!ourCampaign->mapsConquered.empty())
+				backB->block(true);
+			else
+				backB->block(false);
 		}
 		else
 		{
 			// draw restart button
 			startB->disable();
 			restartB->enable();
+			backB->block(false);
 		}
 
 		startInfo.difficulty = ourCampaign->camp->scenarios[mapNr].difficulty;

+ 3 - 3
client/battle/CBattleInterface.cpp

@@ -1911,9 +1911,9 @@ void CBattleInterface::blockUI(bool on)
 	bFlee->block(on || !curInt->cb->battleCanFlee());
 	bSurrender->block(on || curInt->cb->battleGetSurrenderCost() < 0);
 
-	// never block autofight button
-	//FIXME: is that correct?
-	bAutofight->block(false); //curInt->isAutoFightOn
+	// block only if during enemy turn and auto-fight is off
+	// othervice - crash on accessing non-exisiting active stack
+	bAutofight->block(curInt->isAutoFightOn || activeStack);
 
 	if(tacticsMode && btactEnd && btactNext)
 	{

+ 18 - 2
client/gui/CIntObjectClasses.cpp

@@ -309,6 +309,22 @@ CAdventureMapButton::CAdventureMapButton( const std::pair<std::string, std::stri
 	pom[0] = help.first;
 	init(Callback, pom, help.second, playerColoredButton, defName, add, x, y, key);
 }
+
+void CAdventureMapButton::onButtonClicked()
+{
+	// debug logging to figure out pressed button (and as result - player actions) in case of crash
+	logAnim->traceStream() << "Button clicked at " << pos.x << "x" << pos.y;
+	CIntObject * parent = this->parent;
+	std::string prefix = "Parent is";
+	while (parent)
+	{
+		logAnim->traceStream() << prefix << typeid(*parent).name() << " at " << parent->pos.x << "x" << parent->pos.y;
+		parent = parent->parent;
+		prefix = '\t' + prefix;
+	}
+	callback();
+}
+
 void CAdventureMapButton::clickLeft(tribool down, bool previousState)
 {
 	if(isBlocked())
@@ -327,11 +343,11 @@ void CAdventureMapButton::clickLeft(tribool down, bool previousState)
 
 	if (actOnDown && down)
 	{
-		callback();
+		onButtonClicked();
 	}
 	else if (!actOnDown && previousState && (down==false))
 	{
-		callback();
+		onButtonClicked();
 	}
 }
 

+ 2 - 0
client/gui/CIntObjectClasses.h

@@ -124,6 +124,8 @@ class CAdventureMapButton : public CButtonBase
 {
 	std::vector<std::string> imageNames;//store list of images that can be used by this button
 	size_t currentImage;
+
+	void onButtonClicked(); // calls callback
 public:
 	std::map<int, std::string> hoverTexts; //text for statusbar
 	std::string helpBox; //for right-click help

+ 1 - 0
lib/CDefObjInfoHandler.cpp

@@ -35,6 +35,7 @@ static bool isVisitableFromTop(int identifier, int type)
 		Obj::BOAT,
 		Obj::WHIRLPOOL,
 		Obj::GARRISON,
+		Obj::GARRISON2,
 		Obj::SCHOLAR,
 		Obj::CAMPFIRE,
 		Obj::BORDERGUARD,

+ 2 - 0
server/CGameHandler.cpp

@@ -2390,6 +2390,8 @@ bool CGameHandler::buildStructure( ObjectInstanceID tid, BuildingID requestedID,
 		COMPLAIN_RETF("No such town (ID=%s)!", tid);
 	if(!t->town->buildings.count(requestedID))
 		COMPLAIN_RETF("Town of faction %s does not have info about building ID=%s!", t->town->faction->name % tid);
+	if (t->hasBuilt(requestedID))
+		COMPLAIN_RETF("Building %s is already built in %s", t->town->buildings.at(requestedID)->Name() % t->name);
 
 	const CBuilding * requestedBuilding = t->town->buildings.at(requestedID);