Pārlūkot izejas kodu

Merge pull request #3546 from IvanSavenko/fix_freeze_on_start

Fix freeze on map start
Ivan Savenko 1 gadu atpakaļ
vecāks
revīzija
46c4f39eb8

+ 19 - 0
ChangeLog.md

@@ -1,3 +1,22 @@
+# 1.4.4 -> 1.4.5
+
+### Stability
+* Fixed crash on creature spellcasting
+* Fixed crash on unit entering magical obstacles such as quicksands
+* Fixed freeze on map loading on some systems
+
+### Random Maps Generator
+* Fixed placement of guards sometimes resulting into open connection into third zone
+* Fixed rare crash on multithreaded access during placement of artifacts or wandering monsters
+
+### Map Editor
+* Fixed inspector using wrong editor for some values
+
+# 1.4.3 -> 1.4.4
+
+### General
+* Fixed crash on generation of random maps
+
 # 1.4.2 -> 1.4.3
 
 ### General

+ 2 - 2
android/vcmi-app/build.gradle

@@ -10,8 +10,8 @@ android {
 		applicationId "is.xyz.vcmi"
 		minSdk 19
 		targetSdk 33
-		versionCode 1441
-		versionName "1.4.4"
+		versionCode 1450
+		versionName "1.4.5"
 		setProperty("archivesBaseName", "vcmi")
 	}
 

+ 14 - 29
client/eventsSDL/InputSourceText.cpp

@@ -21,10 +21,6 @@
 
 #include <SDL_events.h>
 
-#ifdef VCMI_APPLE
-#	include <dispatch/dispatch.h>
-#endif
-
 void InputSourceText::handleEventTextInput(const SDL_TextInputEvent & text)
 {
 	GH.events().dispatchTextInput(text.text);
@@ -37,38 +33,27 @@ void InputSourceText::handleEventTextEditing(const SDL_TextEditingEvent & text)
 
 void InputSourceText::startTextInput(const Rect & whereInput)
 {
-
-#ifdef VCMI_APPLE
-	dispatch_async(dispatch_get_main_queue(), ^{
-#endif
-
-	Rect rectInScreenCoordinates = GH.screenHandler().convertLogicalPointsToWindow(whereInput);
-	SDL_Rect textInputRect = CSDL_Ext::toSDL(rectInScreenCoordinates);
-
-	SDL_SetTextInputRect(&textInputRect);
-
-	if (SDL_IsTextInputActive() == SDL_FALSE)
+	GH.dispatchMainThread([whereInput]()
 	{
-		SDL_StartTextInput();
-	}
+		Rect rectInScreenCoordinates = GH.screenHandler().convertLogicalPointsToWindow(whereInput);
+		SDL_Rect textInputRect = CSDL_Ext::toSDL(rectInScreenCoordinates);
+
+		SDL_SetTextInputRect(&textInputRect);
 
-#ifdef VCMI_APPLE
+		if (SDL_IsTextInputActive() == SDL_FALSE)
+		{
+			SDL_StartTextInput();
+		}
 	});
-#endif
 }
 
 void InputSourceText::stopTextInput()
 {
-#ifdef VCMI_APPLE
-	dispatch_async(dispatch_get_main_queue(), ^{
-#endif
-
-	if (SDL_IsTextInputActive() == SDL_TRUE)
+	GH.dispatchMainThread([]()
 	{
-		SDL_StopTextInput();
-	}
-
-#ifdef VCMI_APPLE
+		if (SDL_IsTextInputActive() == SDL_TRUE)
+		{
+			SDL_StopTextInput();
+		}
 	});
-#endif
 }

+ 10 - 23
client/widgets/TextControls.cpp

@@ -553,8 +553,7 @@ Point CGStatusBar::getBorderSize()
 
 CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB, bool giveFocusToInput)
 	: CLabel(Pos.x, Pos.y, font, ETextAlignment::CENTER),
-	cb(CB),
-	CFocusable(std::make_shared<CKeyboardFocusListener>(this))
+	cb(CB)
 {
 	setRedrawParent(true);
 	pos.h = Pos.h;
@@ -570,7 +569,7 @@ CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(c
 }
 
 CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const ImagePath & bgName, const CFunctionList<void(const std::string &)> & CB)
-	:cb(CB), 	CFocusable(std::make_shared<CKeyboardFocusListener>(this))
+	:cb(CB)
 {
 	pos += Pos.topLeft();
 	pos.h = Pos.h;
@@ -587,7 +586,6 @@ CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const ImagePath
 }
 
 CTextInput::CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf)
-	:CFocusable(std::make_shared<CKeyboardFocusListener>(this))
 {
 	pos += Pos.topLeft();
 	OBJ_CONSTRUCTION;
@@ -603,20 +601,15 @@ CTextInput::CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf)
 #endif
 }
 
-std::atomic<int> CKeyboardFocusListener::usageIndex(0);
+std::atomic<int> CFocusable::usageIndex(0);
 
-CKeyboardFocusListener::CKeyboardFocusListener(CTextInput * textInput)
-	:textInput(textInput)
+void CFocusable::focusGot()
 {
-}
-
-void CKeyboardFocusListener::focusGot()
-{
-	GH.startTextInput(textInput->pos);
+	GH.startTextInput(pos);
 	usageIndex++;
 }
 
-void CKeyboardFocusListener::focusLost()
+void CFocusable::focusLost()
 {
 	if(0 == --usageIndex)
 	{
@@ -769,12 +762,6 @@ void CTextInput::numberFilter(std::string & text, const std::string & oldText, i
 }
 
 CFocusable::CFocusable()
-	:CFocusable(std::make_shared<IFocusListener>())
-{
-}
-
-CFocusable::CFocusable(std::shared_ptr<IFocusListener> focusListener)
-	: focusListener(focusListener)
 {
 	focus = false;
 	focusables.push_back(this);
@@ -785,7 +772,7 @@ CFocusable::~CFocusable()
 	if(hasFocus())
 	{
 		inputWithFocus = nullptr;
-		focusListener->focusLost();
+		focusLost();
 	}
 
 	focusables -= this;
@@ -799,13 +786,13 @@ bool CFocusable::hasFocus() const
 void CFocusable::giveFocus()
 {
 	focus = true;
-	focusListener->focusGot();
+	focusGot();
 	redraw();
 
 	if(inputWithFocus)
 	{
 		inputWithFocus->focus = false;
-		inputWithFocus->focusListener->focusLost();
+		inputWithFocus->focusLost();
 		inputWithFocus->redraw();
 	}
 
@@ -837,7 +824,7 @@ void CFocusable::removeFocus()
 	if(this == inputWithFocus)
 	{
 		focus = false;
-		focusListener->focusLost();
+		focusLost();
 		redraw();
 
 		inputWithFocus = nullptr;

+ 6 - 30
client/widgets/TextControls.h

@@ -163,25 +163,12 @@ public:
 	void clear() override;
 	void setEnteringMode(bool on) override;
 	void setEnteredText(const std::string & text) override;
-
-};
-
-class CFocusable;
-
-class IFocusListener
-{
-public:
-	virtual void focusGot() {};
-	virtual void focusLost() {};
-	virtual ~IFocusListener() = default;
 };
 
 /// UIElement which can get input focus
 class CFocusable : public virtual CIntObject
 {
-private:
-	std::shared_ptr<IFocusListener> focusListener;
-
+	static std::atomic<int> usageIndex;
 public:
 	bool focus; //only one focusable control can have focus at one moment
 
@@ -190,38 +177,27 @@ public:
 	void removeFocus(); //remove focus
 	bool hasFocus() const;
 
+	void focusGot();
+	void focusLost();
+
 	static std::list<CFocusable *> focusables; //all existing objs
 	static CFocusable * inputWithFocus; //who has focus now
 
 	CFocusable();
-	CFocusable(std::shared_ptr<IFocusListener> focusListener);
 	~CFocusable();
 };
 
-class CTextInput;
-class CKeyboardFocusListener : public IFocusListener
-{
-private:
-	static std::atomic<int> usageIndex;
-	CTextInput * textInput;
-
-public:
-	CKeyboardFocusListener(CTextInput * textInput);
-	void focusGot() override;
-	void focusLost() override;
-};
-
 /// Text input box where players can enter text
 class CTextInput : public CLabel, public CFocusable
 {
 	std::string newText;
 	std::string helpBox; //for right-click help
-	
+
 protected:
 	std::string visibleText() override;
 
 public:
-	
+
 	CFunctionList<void(const std::string &)> cb;
 	CFunctionList<void(std::string &, const std::string &)> filters;
 	void setText(const std::string & nText) override;

+ 1 - 1
cmake_modules/VersionDefinition.cmake

@@ -1,6 +1,6 @@
 set(VCMI_VERSION_MAJOR 1)
 set(VCMI_VERSION_MINOR 4)
-set(VCMI_VERSION_PATCH 4)
+set(VCMI_VERSION_PATCH 5)
 add_definitions(
 	-DVCMI_VERSION_MAJOR=${VCMI_VERSION_MAJOR}
 	-DVCMI_VERSION_MINOR=${VCMI_VERSION_MINOR}

+ 6 - 0
debian/changelog

@@ -1,3 +1,9 @@
+vcmi (1.4.5) jammy; urgency=medium
+
+  * New upstream release
+
+ -- Ivan Savenko <[email protected]>  Tue, 23 Jan 2024 12:00:00 +0200
+
 vcmi (1.4.4) jammy; urgency=medium
 
   * New upstream release

+ 1 - 0
launcher/eu.vcmi.VCMI.metainfo.xml

@@ -76,6 +76,7 @@
 		</screenshot>
 	</screenshots>
 	<releases>
+		<release version="1.4.5" date="2024-01-23" type="stable"/>
 		<release version="1.4.4" date="2024-01-20" type="stable"/>
 		<release version="1.4.3" date="2024-01-19" type="stable"/>
 		<release version="1.4.2" date="2023-12-25" type="stable"/>

+ 3 - 0
launcher/modManager/cmodlist.cpp

@@ -38,6 +38,9 @@ bool CModEntry::isEnabled() const
 	if(!isInstalled())
 		return false;
 
+	if (!isVisible())
+		return false;
+
 	return modSettings["active"].toBool();
 }
 

+ 1 - 1
launcher/modManager/cmodlistview_moc.cpp

@@ -521,7 +521,7 @@ QStringList CModListView::findDependentMods(QString mod, bool excludeDisabled)
 	{
 		auto current = modModel->getMod(modName);
 
-		if(!current.isInstalled())
+		if(!current.isInstalled() || !current.isVisible())
 			continue;
 
 		if(current.getDependencies().contains(mod, Qt::CaseInsensitive))

+ 78 - 65
launcher/translation/spanish.ts

@@ -6,84 +6,84 @@
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="22"/>
         <source>VCMI on Discord</source>
-        <translation type="unfinished">VCMI en Discord</translation>
+        <translation>VCMI en Discord</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="29"/>
         <source>Have a question? Found a bug? Want to help? Join us!</source>
-        <translation type="unfinished">¿Tienes alguna pregunta? ¿Encontraste algún error? ¿Quieres ayudar? ¡Únete a nosotros!</translation>
+        <translation>¿Tienes alguna pregunta? ¿Encontraste algún error? ¿Quieres ayudar? ¡Únete a nosotros!</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="36"/>
         <source>VCMI on Github</source>
-        <translation type="unfinished">VCMI en Github</translation>
+        <translation>VCMI en Github</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="55"/>
         <source>Our Community</source>
-        <translation type="unfinished"></translation>
+        <translation>Nuestra comunidad</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="62"/>
         <source>VCMI on Slack</source>
-        <translation type="unfinished">VCMI en Slack</translation>
+        <translation>VCMI en Slack</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="98"/>
         <source>Build Information</source>
-        <translation type="unfinished"></translation>
+        <translation>Información de la versión</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="115"/>
         <source>User data directory</source>
-        <translation type="unfinished">Directorio de datos del usuario</translation>
+        <translation>Directorio de datos del usuario</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="122"/>
         <location filename="../aboutProject/aboutproject_moc.ui" line="129"/>
         <location filename="../aboutProject/aboutproject_moc.ui" line="193"/>
         <source>Open</source>
-        <translation type="unfinished">Abrir</translation>
+        <translation>Abrir</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="136"/>
         <source>Check for updates</source>
-        <translation type="unfinished"></translation>
+        <translation>Comprobar actualizaciones</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="156"/>
         <source>Game version</source>
-        <translation type="unfinished"></translation>
+        <translation>Versión del juego</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="163"/>
         <source>Log files directory</source>
-        <translation type="unfinished">Directorio de archivos de registro</translation>
+        <translation>Directorio de archivos de registro</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="176"/>
         <source>Data Directories</source>
-        <translation type="unfinished">Directorios de datos</translation>
+        <translation>Directorios de datos</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="213"/>
         <source>Game data directory</source>
-        <translation type="unfinished"></translation>
+        <translation>Directorio de los datos del juego</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="220"/>
         <source>Operating System</source>
-        <translation type="unfinished"></translation>
+        <translation>Sistema operativo</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="273"/>
         <source>Project homepage</source>
-        <translation type="unfinished"></translation>
+        <translation>Página web del proyecto</translation>
     </message>
     <message>
         <location filename="../aboutProject/aboutproject_moc.ui" line="286"/>
         <source>Report a bug</source>
-        <translation type="unfinished"></translation>
+        <translation>Informar de un error</translation>
     </message>
 </context>
 <context>
@@ -121,7 +121,7 @@
     <message>
         <location filename="../modManager/cmodlistmodel_moc.cpp" line="48"/>
         <source>Maps</source>
-        <translation type="unfinished"></translation>
+        <translation>Mapas</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistmodel_moc.cpp" line="49"/>
@@ -180,7 +180,7 @@
     <message>
         <location filename="../modManager/cmodlistmodel_moc.cpp" line="62"/>
         <source>Compatibility</source>
-        <translation type="unfinished">Compatibilidad</translation>
+        <translation>Compatibilidad</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistmodel_moc.cpp" line="63"/>
@@ -319,7 +319,7 @@
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="292"/>
         <source>Size</source>
-        <translation type="unfinished"></translation>
+        <translation>Tamaño</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="294"/>
@@ -410,12 +410,12 @@
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="638"/>
         <source>Downloading %s%. %p% (%v MB out of %m MB) finished</source>
-        <translation type="unfinished"></translation>
+        <translation>Descargando %s%. %p% (%v MB de %m MB) completado</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="665"/>
         <source>Download failed</source>
-        <translation type="unfinished"></translation>
+        <translation>Descarga fallida</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="666"/>
@@ -424,30 +424,37 @@
 Encountered errors:
 
 </source>
-        <translation type="unfinished"></translation>
+        <translation>No se han podido descargar todos los ficheros.
+
+Errores encontrados:
+
+</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="667"/>
         <source>
 
 Install successfully downloaded?</source>
-        <translation type="unfinished"></translation>
+        <translation>
+
+Instalar lo correctamente descargado?</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="812"/>
         <source>Installing mod %1</source>
-        <translation type="unfinished"></translation>
+        <translation>Instalando mod %1</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="874"/>
         <source>Operation failed</source>
-        <translation type="unfinished"></translation>
+        <translation>Operación fallida</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="875"/>
         <source>Encountered errors:
 </source>
-        <translation type="unfinished"></translation>
+        <translation>Errores encontrados:
+</translation>
     </message>
     <message>
         <location filename="../modManager/cmodlistview_moc.cpp" line="910"/>
@@ -482,94 +489,94 @@ Install successfully downloaded?</source>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="230"/>
         <source>Interface Scaling</source>
-        <translation type="unfinished"></translation>
+        <translation>Escala de la interfaz</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="394"/>
         <source>Neutral AI in battles</source>
-        <translation type="unfinished"></translation>
+        <translation>IA neutral en batallas</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="169"/>
         <source>Enemy AI in battles</source>
-        <translation type="unfinished"></translation>
+        <translation>IA enemiga en batallas</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="176"/>
         <source>Additional repository</source>
-        <translation type="unfinished"></translation>
+        <translation>Repositorio adicional</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="210"/>
         <source>Adventure Map Allies</source>
-        <translation type="unfinished"></translation>
+        <translation>Aliados en el Mapa de aventuras</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="552"/>
         <source>Adventure Map Enemies</source>
-        <translation type="unfinished"></translation>
+        <translation>Enemigos en el Mapa de aventuras</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="428"/>
         <source>Windowed</source>
-        <translation type="unfinished"></translation>
+        <translation>Ventana</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="433"/>
         <source>Borderless fullscreen</source>
-        <translation type="unfinished"></translation>
+        <translation>Ventana completa sin bordes</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="438"/>
         <source>Exclusive fullscreen</source>
-        <translation type="unfinished"></translation>
+        <translation>Pantalla completa</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="593"/>
         <source>Autosave limit (0 = off)</source>
-        <translation type="unfinished"></translation>
+        <translation>Límite de autosaves (0 = sin límite)</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="401"/>
         <source>Friendly AI in battles</source>
-        <translation type="unfinished"></translation>
+        <translation>IA amistosa en batallas</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="370"/>
         <source>Framerate Limit</source>
-        <translation type="unfinished"></translation>
+        <translation>Límite de fotogramas</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="460"/>
         <source>Autosave prefix</source>
-        <translation type="unfinished"></translation>
+        <translation>Prefijo autoguardado</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="484"/>
         <source>empty = map name prefix</source>
-        <translation type="unfinished"></translation>
+        <translation>Vacio = prefijo del mapa</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="607"/>
         <source>Refresh now</source>
-        <translation type="unfinished"></translation>
+        <translation>Actualizar</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="614"/>
         <source>Default repository</source>
-        <translation type="unfinished"></translation>
+        <translation>Repositorio por defecto</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="624"/>
         <source>Renderer</source>
-        <translation type="unfinished"></translation>
+        <translation>Render</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="246"/>
         <location filename="../settingsView/csettingsview_moc.ui" line="476"/>
         <location filename="../settingsView/csettingsview_moc.ui" line="544"/>
         <source>On</source>
-        <translation>Encendido</translation>
+        <translation>Activado</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="115"/>
@@ -584,7 +591,7 @@ Install successfully downloaded?</source>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="349"/>
         <source>Reserved screen area</source>
-        <translation type="unfinished"></translation>
+        <translation>Área de pantalla reservada</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="155"/>
@@ -614,7 +621,7 @@ Install successfully downloaded?</source>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="562"/>
         <source>VSync</source>
-        <translation type="unfinished"></translation>
+        <translation>Sincronización vertical</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="135"/>
@@ -640,7 +647,13 @@ Windowed - game will run inside a window that covers part of your screen
 Borderless Windowed Mode - game will run in a window that covers entirely of your screen, using same resolution as your screen.
 
 Fullscreen Exclusive Mode - game will cover entirety of your screen and will use selected resolution.</source>
-        <translation type="unfinished"></translation>
+        <translation>Selecciona el modo de visualización del juego
+
+En ventana - el juego se ejecutará dentro de una ventana que forma parte de tu pantalla.
+
+Ventana sin bordes - el juego se ejecutará en una ventana que cubre completamente tu pantalla, usando la misma resolución.
+
+Pantalla completa - el juego cubrirá la totalidad de la pantalla y utilizará la resolución seleccionada.</translation>
     </message>
     <message>
         <location filename="../settingsView/csettingsview_moc.ui" line="522"/>
@@ -698,27 +711,27 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
     <message>
         <location filename="../lobby/chat_moc.ui" line="14"/>
         <source>Form</source>
-        <translation type="unfinished"></translation>
+        <translation>Formulario</translation>
     </message>
     <message>
         <location filename="../lobby/chat_moc.ui" line="40"/>
         <source>Users in lobby</source>
-        <translation type="unfinished"></translation>
+        <translation>Usuarios en la sala</translation>
     </message>
     <message>
         <location filename="../lobby/chat_moc.ui" line="50"/>
         <source>Global chat</source>
-        <translation type="unfinished"></translation>
+        <translation>Chat general</translation>
     </message>
     <message>
         <location filename="../lobby/chat_moc.ui" line="104"/>
         <source>type you message</source>
-        <translation type="unfinished"></translation>
+        <translation>Escribe tu mensaje</translation>
     </message>
     <message>
         <location filename="../lobby/chat_moc.ui" line="111"/>
         <source>send</source>
-        <translation type="unfinished"></translation>
+        <translation>Enviar</translation>
     </message>
 </context>
 <context>
@@ -792,12 +805,12 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.ui" line="702"/>
         <source>Interface Improvements</source>
-        <translation type="unfinished"></translation>
+        <translation>Mejora de la interfaz</translation>
     </message>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.ui" line="772"/>
         <source>Install mod that provides various interface improvements, such as better interface for random maps and selectable actions in battles</source>
-        <translation type="unfinished"></translation>
+        <translation>Instalar mod que proporciona varias mejoras en la interfaz, como mejor interacción en los mapas aleatorios y más opciones en las batallas</translation>
     </message>
     <message>
         <location filename="../firstLaunch/firstlaunch_moc.ui" line="127"/>
@@ -921,7 +934,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../languages.cpp" line="23"/>
         <source>Czech</source>
-        <translation type="unfinished"></translation>
+        <translation>Czech (Checo)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="24"/>
@@ -936,7 +949,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../languages.cpp" line="26"/>
         <source>Finnish</source>
-        <translation type="unfinished"></translation>
+        <translation>Finnish (Finlandés)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="27"/>
@@ -951,12 +964,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../languages.cpp" line="29"/>
         <source>Hungarian</source>
-        <translation type="unfinished"></translation>
+        <translation>Hungarian (Húngaro)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="30"/>
         <source>Italian</source>
-        <translation type="unfinished"></translation>
+        <translation>Italian (Italiano)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="31"/>
@@ -971,7 +984,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../languages.cpp" line="33"/>
         <source>Portuguese</source>
-        <translation type="unfinished"></translation>
+        <translation>Portuguese (Portugués)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="34"/>
@@ -986,12 +999,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../languages.cpp" line="36"/>
         <source>Swedish</source>
-        <translation type="unfinished"></translation>
+        <translation>Swedish (Sueco)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="37"/>
         <source>Turkish</source>
-        <translation type="unfinished"></translation>
+        <translation>Turkish (Turco)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="38"/>
@@ -1001,7 +1014,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../languages.cpp" line="39"/>
         <source>Vietnamese</source>
-        <translation type="unfinished"></translation>
+        <translation>Vietnamese (Vietnamita)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="40"/>
@@ -1011,12 +1024,12 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../languages.cpp" line="41"/>
         <source>Other (Cyrillic Script)</source>
-        <translation type="unfinished"></translation>
+        <translation>Otro (Escritura cirílica)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="42"/>
         <source>Other (West European)</source>
-        <translation type="unfinished"></translation>
+        <translation>Otro (Europa del Este)</translation>
     </message>
     <message>
         <location filename="../languages.cpp" line="64"/>
@@ -1151,7 +1164,7 @@ Ten en cuenta que para usar VCMI debes ser dueño de los archivos de datos origi
     <message>
         <location filename="../mainwindow_moc.ui" line="207"/>
         <source>Help</source>
-        <translation type="unfinished"></translation>
+        <translation>Ayuda</translation>
     </message>
     <message>
         <location filename="../mainwindow_moc.ui" line="276"/>

+ 5 - 1
lib/bonuses/CBonusSystemNode.cpp

@@ -273,6 +273,10 @@ CBonusSystemNode::~CBonusSystemNode()
 
 void CBonusSystemNode::attachTo(CBonusSystemNode & parent)
 {
+	// quick workaround to prevent multithreaded access to bonus system in RMG
+	static boost::mutex attachMutex;
+	boost::lock_guard<boost::mutex> lock(attachMutex);
+
 	assert(!vstd::contains(parents, &parent));
 	parents.push_back(&parent);
 
@@ -646,4 +650,4 @@ int64_t CBonusSystemNode::getTreeVersion() const
 	return treeChanged;
 }
 
-VCMI_LIB_NAMESPACE_END
+VCMI_LIB_NAMESPACE_END

+ 15 - 0
lib/rmg/modificators/ConnectionsPlacer.cpp

@@ -177,6 +177,21 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
 			int3 potentialPos = zone.areaPossible().nearest(borderPos);
 			assert(borderPos != potentialPos);
 
+			//Check if guard pos doesn't touch any 3rd zone. This would create unwanted passage to 3rd zone
+			bool adjacentZone = false;
+			map.foreach_neighbour(potentialPos, [this, &adjacentZone, otherZoneId](int3 & pos)
+			{
+				auto zoneId = map.getZoneID(pos);
+				if (zoneId != zone.getId() && zoneId != otherZoneId)
+				{
+					adjacentZone = true;
+				}
+			});
+			if (adjacentZone)
+			{
+				continue;
+			}
+
 			//Take into account distance to objects from both sides
 			float dist = std::min(map.getTileInfo(potentialPos).getNearestObjectDistance(),
 				map.getTileInfo(borderPos).getNearestObjectDistance());

+ 0 - 2
mapeditor/inspector/inspector.h

@@ -128,7 +128,6 @@ protected:
 		{
 			itemKey = keyItems[key];
 			table->setItem(table->row(itemKey), 1, itemValue);
-			if(delegate)
 				table->setItemDelegateForRow(table->row(itemKey), delegate);
 		}
 		else
@@ -139,7 +138,6 @@ protected:
 			table->setRowCount(row + 1);
 			table->setItem(row, 0, itemKey);
 			table->setItem(row, 1, itemValue);
-			if(delegate)
 				table->setItemDelegateForRow(row, delegate);
 			++row;
 		}