← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/building_encyclopedia into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/building_encyclopedia into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/building_encyclopedia/+merge/258719

The Tribal Encyclopedia now uses a tab panel and box layout.

Added help for Buildings and Workers.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/building_encyclopedia into lp:widelands.
=== modified file 'src/scripting/lua_coroutine.cc'
--- src/scripting/lua_coroutine.cc	2015-03-01 09:21:20 +0000
+++ src/scripting/lua_coroutine.cc	2015-05-10 11:02:17 +0000
@@ -105,6 +105,12 @@
 	++m_ninput_args;
 }
 
+void LuaCoroutine::push_arg(const Widelands::WorkerDescr* worker_descr) {
+	assert(worker_descr != nullptr);
+	to_lua<LuaMaps::LuaWorkerDescription>(m_L, new LuaMaps::LuaWorkerDescription(worker_descr));
+	++m_ninput_args;
+}
+
 std::string LuaCoroutine::pop_string() {
 	if (!m_nreturn_values) {
 		return "";

=== modified file 'src/scripting/lua_coroutine.h'
--- src/scripting/lua_coroutine.h	2015-03-01 09:21:20 +0000
+++ src/scripting/lua_coroutine.h	2015-05-10 11:02:17 +0000
@@ -33,6 +33,7 @@
 class Player;
 struct BuildingDescr;
 struct Coords;
+struct WorkerDescr;
 }  // namespace Widelands
 
 // Easy handling of function objects and coroutines.
@@ -61,6 +62,7 @@
 	void push_arg(const Widelands::Player*);
 	void push_arg(const Widelands::Coords&);
 	void push_arg(const Widelands::BuildingDescr*);
+	void push_arg(const Widelands::WorkerDescr*);
 
 	// Accesses the returned values from the run of the coroutine.
 	uint32_t pop_uint32();

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2015-04-18 11:20:53 +0000
+++ src/scripting/lua_map.cc	2015-05-10 11:02:17 +0000
@@ -1871,8 +1871,10 @@
 	PROP_RO(LuaWorkerDescription, becomes),
 	PROP_RO(LuaWorkerDescription, buildable),
 	PROP_RO(LuaWorkerDescription, buildcost),
+	PROP_RO(LuaWorkerDescription, helptext),
 	PROP_RO(LuaWorkerDescription, icon_name),
 	PROP_RO(LuaWorkerDescription, needed_experience),
+	PROP_RO(LuaWorkerDescription, tribename),
 	{nullptr, nullptr, nullptr},
 };
 
@@ -1944,6 +1946,16 @@
 	return 1;
 }
 
+/* RST
+	.. attribute:: helptext
+
+			(RO) the helptext for this worker.
+*/
+int LuaWorkerDescription::get_helptext(lua_State * L) {
+	lua_pushstring(L, get()->helptext());
+	return 1;
+}
+
 
 /* RST
 	.. attribute:: icon_name
@@ -1966,6 +1978,17 @@
 	return 1;
 }
 
+/* RST
+	.. attribute:: tribename
+
+			(RO) the name of the worker's tribe.
+*/
+int LuaWorkerDescription::get_tribename(lua_State * L) {
+	lua_pushstring(L, get()->tribe().name());
+	return 1;
+}
+
+
 
 /*
  ==========================================================

=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h	2015-04-07 13:33:16 +0000
+++ src/scripting/lua_map.h	2015-05-10 11:02:17 +0000
@@ -416,8 +416,10 @@
 	int get_becomes(lua_State*);
 	int get_buildable(lua_State*);
 	int get_buildcost(lua_State*);
+	int get_helptext(lua_State*);
 	int get_icon_name(lua_State*);
 	int get_needed_experience(lua_State*);
+	int get_tribename(lua_State*);
 
 	/*
 	 * Lua methods

=== modified file 'src/wui/encyclopedia_window.cc'
--- src/wui/encyclopedia_window.cc	2015-01-30 23:10:35 +0000
+++ src/wui/encyclopedia_window.cc	2015-05-10 11:02:17 +0000
@@ -22,11 +22,14 @@
 #include <algorithm>
 #include <cstring>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <typeinfo>
 #include <vector>
 
+#include <boost/format.hpp>
+
 #include "base/i18n.h"
 #include "base/macros.h"
 #include "economy/economy.h"
@@ -37,6 +40,8 @@
 #include "logic/productionsite.h"
 #include "logic/tribe.h"
 #include "logic/warelist.h"
+#include "scripting/lua_interface.h"
+#include "scripting/lua_table.h"
 #include "ui_basic/table.h"
 #include "ui_basic/unique_window.h"
 #include "ui_basic/window.h"
@@ -47,6 +52,8 @@
 constexpr uint32_t quantityColumnWidth = 100;
 constexpr uint32_t wareColumnWidth = 250;
 #define PRODSITE_GROUPS_WIDTH (WINDOW_WIDTH - wareColumnWidth - quantityColumnWidth - 10)
+constexpr int kPadding = 5;
+constexpr int kTabHeight = 35;
 
 using namespace Widelands;
 
@@ -54,6 +61,13 @@
 	return dynamic_cast<InteractivePlayer&>(*get_parent());
 }
 
+namespace {
+const std::string heading(const std::string& text) {
+	return ((boost::format("<rt><p font-size=18 font-weight=bold font-color=D1D1D1>"
+								  "%s<br></p><p font-size=8> <br></p></rt>") % text).str());
+}
+} // namespace
+
 
 EncyclopediaWindow::EncyclopediaWindow
 	(InteractivePlayer & parent, UI::UniqueWindow::Registry & registry)
@@ -62,27 +76,140 @@
 		(&parent, "encyclopedia",
 		 &registry,
 		 WINDOW_WIDTH, WINDOW_HEIGHT,
-		 _("Tribal Ware Encyclopedia")),
-	wares            (this, 5, 5, WINDOW_WIDTH - 10, WINDOW_HEIGHT - 250),
-	prodSites        (this, 5, WINDOW_HEIGHT - 150, PRODSITE_GROUPS_WIDTH, 145),
-	condTable
-		(this,
-		 PRODSITE_GROUPS_WIDTH + 5, WINDOW_HEIGHT - 150, WINDOW_WIDTH - PRODSITE_GROUPS_WIDTH - 5, 145),
-	descrTxt         (this, 5, WINDOW_HEIGHT - 240, WINDOW_WIDTH - 10, 80, "")
+		 _("Tribal Encyclopedia")),
+	tabs_(this, 0, 0, nullptr),
+	buildings_tab_box_(&tabs_, 0, 0, UI::Box::Horizontal),
+	buildings_box_(&buildings_tab_box_, 0, 0, UI::Box::Horizontal),
+	buildings_    (&buildings_box_, 0, 0,
+						WINDOW_WIDTH / 2 - 1.5 * kPadding, WINDOW_HEIGHT - kTabHeight - 2 * kPadding),
+	building_text_(&buildings_box_, 0, 0,
+						WINDOW_WIDTH / 2 - 1.5 * kPadding, WINDOW_HEIGHT - kTabHeight - 2 * kPadding),
+
+	wares_tab_box_(&tabs_, 0, 0, UI::Box::Horizontal),
+	wares_box_(&wares_tab_box_, 0, 0, UI::Box::Vertical),
+	wares_details_box_(&wares_box_, 0, 0, UI::Box::Horizontal),
+	wares_            (&wares_box_, 0, 0, WINDOW_WIDTH - 2 * kPadding, WINDOW_HEIGHT - 270 - 2 * kPadding),
+	ware_text_        (&wares_box_, 0, 0, WINDOW_WIDTH - 2 * kPadding, 80, ""),
+	prod_sites_       (&wares_details_box_, 0, 0, PRODSITE_GROUPS_WIDTH, 145),
+	cond_table_
+		(&wares_details_box_,
+		 0, 0, WINDOW_WIDTH - PRODSITE_GROUPS_WIDTH - 2 * kPadding, 145),
+
+	workers_tab_box_(&tabs_, 0, 0, UI::Box::Horizontal),
+	workers_box_(&workers_tab_box_, 0, 0, UI::Box::Horizontal),
+	workers_    (&workers_box_, 0, 0,
+						WINDOW_WIDTH / 2 - 1.5 * kPadding, WINDOW_HEIGHT - kTabHeight - 2 * kPadding),
+	worker_text_(&workers_box_, 0, 0,
+						WINDOW_WIDTH / 2 - 1.5 * kPadding, WINDOW_HEIGHT - kTabHeight - 2 * kPadding)
 {
-	wares.selected.connect(boost::bind(&EncyclopediaWindow::ware_selected, this, _1));
-
-	prodSites.selected.connect(boost::bind(&EncyclopediaWindow::prod_site_selected, this, _1));
-	condTable.add_column
-			/** TRANSLATORS: Column title in the Tribal Wares Encyclopedia */
+	// Buildings
+	buildings_box_.add(&buildings_, UI::Align_Left);
+	buildings_box_.add_space(kPadding);
+	buildings_box_.add(&building_text_, UI::Align_Left);
+
+	buildings_tab_box_.add_space(kPadding);
+	buildings_tab_box_.add(&buildings_box_, UI::Align_Left);
+
+	// Wares
+	wares_details_box_.add(&prod_sites_, UI::Align_Left);
+	wares_details_box_.add(&cond_table_, UI::Align_Left);
+	wares_details_box_.set_size(WINDOW_WIDTH,
+										 tabs_.get_inner_h() - wares_.get_h() - ware_text_.get_h() - 4 * kPadding);
+
+	wares_box_.add(&wares_, UI::Align_Left);
+	wares_box_.add_space(kPadding);
+	wares_box_.add(&ware_text_, UI::Align_Left);
+	wares_box_.add_space(kPadding);
+	wares_box_.add(&wares_details_box_, UI::Align_Left);
+	wares_box_.set_size(WINDOW_WIDTH, wares_.get_h() + ware_text_.get_h() + 2 * kPadding);
+
+	wares_tab_box_.add_space(kPadding);
+	wares_tab_box_.add(&wares_box_, UI::Align_Left);
+
+	// Workers
+	workers_box_.add(&workers_, UI::Align_Left);
+	workers_box_.add_space(kPadding);
+	workers_box_.add(&worker_text_, UI::Align_Left);
+
+	workers_tab_box_.add_space(kPadding);
+	workers_tab_box_.add(&workers_box_, UI::Align_Left);
+
+	tabs_.add("encyclopedia_wares", g_gr->images().get("pics/genstats_nrwares.png"),
+				 &wares_tab_box_, _("Wares"));
+	tabs_.add("encyclopedia_workers", g_gr->images().get("pics/genstats_nrworkers.png"),
+				 &workers_tab_box_, _("Workers"));
+	tabs_.add("encyclopedia_buildings", g_gr->images().get("pics/genstats_nrbuildings.png"),
+				 &buildings_tab_box_, _("Buildings"));
+	tabs_.set_size(WINDOW_WIDTH, WINDOW_HEIGHT);
+
+	// Content
+	buildings_.selected.connect(boost::bind(&EncyclopediaWindow::building_selected, this, _1));
+
+	wares_.selected.connect(boost::bind(&EncyclopediaWindow::ware_selected, this, _1));
+	prod_sites_.selected.connect(boost::bind(&EncyclopediaWindow::prod_site_selected, this, _1));
+	cond_table_.add_column
+			/** TRANSLATORS: Column title in the Tribal Encyclopedia */
 			(wareColumnWidth, ngettext("Consumed Ware Type", "Consumed Ware Types", 0));
-	condTable.add_column (quantityColumnWidth, _("Quantity"));
-	condTable.focus();
-
+	cond_table_.add_column (quantityColumnWidth, _("Quantity"));
+	cond_table_.focus();
+
+	workers_.selected.connect(boost::bind(&EncyclopediaWindow::worker_selected, this, _1));
+
+	fill_buildings();
 	fill_wares();
+	fill_workers();
 
-	if (get_usedefaultpos())
+	if (get_usedefaultpos()) {
 		center_to_parent();
+	}
+}
+
+
+void EncyclopediaWindow::fill_buildings() {
+	const TribeDescr& tribe = iaplayer().player().tribe();
+	BuildingIndex const nr_buildings = tribe.get_nrbuildings();
+	std::vector<Building> building_vec;
+
+	for (BuildingIndex i = 0; i < nr_buildings; ++i) {
+		BuildingDescr const * building = tribe.get_building_descr(i);
+		Building b(i, building);
+		// We can't access helptexts for global militarysites
+		// TODO(GunChleoc): Add global militarysites in the one_tribe branch
+		if (!building->global()) {
+			building_vec.push_back(b);
+		}
+	}
+
+	std::sort(building_vec.begin(), building_vec.end());
+
+	for (uint32_t i = 0; i < building_vec.size(); i++) {
+		Building cur = building_vec[i];
+		buildings_.add(cur.descr_->descname(), cur.index_, cur.descr_->get_icon());
+	}
+}
+
+void EncyclopediaWindow::building_selected(uint32_t) {
+	const TribeDescr& tribe = iaplayer().player().tribe();
+	const Widelands::BuildingDescr& selected_building = *tribe.get_building_descr(buildings_.get_selected());
+
+	if (selected_building.has_help_text()) {
+		try {
+			std::unique_ptr<LuaTable> t(
+				iaplayer().egbase().lua().run_script(selected_building.helptext_script()));
+			std::unique_ptr<LuaCoroutine> cr(t->get_coroutine("func"));
+			cr->push_arg(&selected_building);
+			cr->resume();
+			const std::string help_text = cr->pop_string();
+			building_text_.set_text((boost::format("%s%s")
+											 % heading(selected_building.descname())
+											 % help_text).str());
+		} catch (LuaError& err) {
+			building_text_.set_text(err.what());
+		}
+	} else {
+		building_text_.set_text("There is no help available for this building.");
+	}
+	building_text_.scroll_to_top();
 }
 
 void EncyclopediaWindow::fill_wares() {
@@ -100,18 +227,18 @@
 
 	for (uint32_t i = 0; i < ware_vec.size(); i++) {
 		Ware cur = ware_vec[i];
-		wares.add(cur.m_descr->descname(), cur.m_i, cur.m_descr->icon());
+		wares_.add(cur.descr_->descname(), cur.index_, cur.descr_->icon());
 	}
 }
 
 void EncyclopediaWindow::ware_selected(uint32_t) {
 	const TribeDescr & tribe = iaplayer().player().tribe();
-	selectedWare = tribe.get_ware_descr(wares.get_selected());
-
-	descrTxt.set_text(selectedWare->helptext());
-
-	prodSites.clear();
-	condTable.clear();
+	selected_ware_ = tribe.get_ware_descr(wares_.get_selected());
+
+	ware_text_.set_text(selected_ware_->helptext());
+
+	prod_sites_.clear();
+	cond_table_.clear();
 
 	bool found = false;
 
@@ -123,25 +250,25 @@
 			if
 				((descr.is_buildable() || descr.is_enhanced())
 				 &&
-				 de->output_ware_types().count(wares.get_selected()))
+				 de->output_ware_types().count(wares_.get_selected()))
 			{
-				prodSites.add(de->descname(), i, de->get_icon());
+				prod_sites_.add(de->descname(), i, de->get_icon());
 				found = true;
 			}
 		}
 	}
 	if (found)
-		prodSites.select(0);
+		prod_sites_.select(0);
 
 }
 
 void EncyclopediaWindow::prod_site_selected(uint32_t) {
-	assert(prodSites.has_selection());
+	assert(prod_sites_.has_selection());
 	size_t no_of_wares = 0;
-	condTable.clear();
+	cond_table_.clear();
 	const TribeDescr & tribe = iaplayer().player().tribe();
 
-	upcast(ProductionSiteDescr const, descr, tribe.get_building_descr(prodSites.get_selected()));
+	upcast(ProductionSiteDescr const, descr, tribe.get_building_descr(prod_sites_.get_selected()));
 	const ProductionSiteDescr::Programs & programs = descr->programs();
 
 	//  TODO(unknown): This needs reworking. A program can indeed produce iron even if
@@ -153,16 +280,16 @@
 	//  Only shows information from the first program that has a name indicating
 	//  that it produces the considered ware type.
 	std::map<std::string, ProductionProgram *>::const_iterator programIt =
-		programs.find(std::string("produce_") + selectedWare->name());
-
-	if (programIt == programs.end())
-		programIt = programs.find(std::string("smelt_")  + selectedWare->name());
-
-	if (programIt == programs.end())
-		programIt = programs.find(std::string("smoke_")  + selectedWare->name());
-
-	if (programIt == programs.end())
-		programIt = programs.find(std::string("mine_")   + selectedWare->name());
+		programs.find(std::string("produce_") + selected_ware_->name());
+
+	if (programIt == programs.end())
+		programIt = programs.find(std::string("smelt_")  + selected_ware_->name());
+
+	if (programIt == programs.end())
+		programIt = programs.find(std::string("smoke_")  + selected_ware_->name());
+
+	if (programIt == programs.end())
+		programIt = programs.find(std::string("mine_")   + selected_ware_->name());
 
 	if (programIt == programs.end())
 		programIt = programs.find("work");
@@ -194,15 +321,55 @@
 
 					//  picture only of first ware type in group
 					UI::Table<uintptr_t>::EntryRecord & tableEntry =
-						condTable.add(0);
+						cond_table_.add(0);
 					tableEntry.set_picture
 						(0, tribe.get_ware_descr(*ware_types.begin())->icon(), ware_type_names);
 					tableEntry.set_string(1, std::to_string(static_cast<unsigned int>(temp_group.second)));
-					condTable.set_sort_column(0);
-					condTable.sort();
+					cond_table_.set_sort_column(0);
+					cond_table_.sort();
 				}
 			}
 		}
 	}
-	condTable.set_column_title(0, ngettext("Consumed Ware Type", "Consumed Ware Types", no_of_wares));
+	cond_table_.set_column_title(0, ngettext("Consumed Ware Type", "Consumed Ware Types", no_of_wares));
+}
+
+void EncyclopediaWindow::fill_workers() {
+	const TribeDescr& tribe = iaplayer().player().tribe();
+	WareIndex const nr_workers = tribe.get_nrworkers();
+	std::vector<Worker> worker_vec;
+
+	for (WareIndex i = 0; i < nr_workers; ++i) {
+		WorkerDescr const * worker = tribe.get_worker_descr(i);
+		Worker w(i, worker);
+		worker_vec.push_back(w);
+	}
+
+	std::sort(worker_vec.begin(), worker_vec.end());
+
+	for (uint32_t i = 0; i < worker_vec.size(); i++) {
+		Worker cur = worker_vec[i];
+		workers_.add(cur.descr_->descname(), cur.index_, cur.descr_->icon());
+	}
+}
+
+void EncyclopediaWindow::worker_selected(uint32_t) {
+	const TribeDescr& tribe = iaplayer().player().tribe();
+	const Widelands::WorkerDescr& selected_worker = *tribe.get_worker_descr(workers_.get_selected());
+
+	try {
+		std::unique_ptr<LuaTable> t(
+			iaplayer().egbase().lua().run_script("tribes/scripting/worker_help.lua"));
+		std::unique_ptr<LuaCoroutine> cr(t->get_coroutine("func"));
+		cr->push_arg(&selected_worker);
+		cr->resume();
+		const std::string help_text = cr->pop_string();
+		worker_text_.set_text((boost::format("%s%s")
+									  % heading(selected_worker.descname())
+									  % help_text).str());
+	} catch (LuaError& err) {
+		worker_text_.set_text(err.what());
+	}
+
+	worker_text_.scroll_to_top();
 }

=== modified file 'src/wui/encyclopedia_window.h'
--- src/wui/encyclopedia_window.h	2015-02-08 18:16:41 +0000
+++ src/wui/encyclopedia_window.h	2015-05-10 11:02:17 +0000
@@ -20,16 +20,22 @@
 #ifndef WL_WUI_ENCYCLOPEDIA_WINDOW_H
 #define WL_WUI_ENCYCLOPEDIA_WINDOW_H
 
+#include "logic/building.h"
 #include "logic/ware_descr.h"
+#include "logic/worker_descr.h"
+#include "ui_basic/box.h"
 #include "ui_basic/listselect.h"
 #include "ui_basic/multilinetextarea.h"
 #include "ui_basic/table.h"
+#include "ui_basic/tabpanel.h"
 #include "ui_basic/unique_window.h"
 #include "ui_basic/window.h"
 
 namespace Widelands {
+struct BuildingDescr;
+class TribeDescr;
 struct WareDescr;
-class TribeDescr;
+class WorkerDescr;
 }
 
 class InteractivePlayer;
@@ -37,29 +43,80 @@
 struct EncyclopediaWindow : public UI::UniqueWindow {
 	EncyclopediaWindow(InteractivePlayer &, UI::UniqueWindow::Registry &);
 private:
+	struct Building {
+		Building(Widelands::BuildingIndex i, const Widelands::BuildingDescr * descr)
+			:
+			index_(i),
+			descr_(descr)
+			{}
+		Widelands::BuildingIndex index_;
+		const Widelands::BuildingDescr * descr_;
+
+		bool operator<(const Building o) const {
+			return descr_->descname() < o.descr_->descname();
+		}
+	};
+
 	struct Ware {
 		Ware(Widelands::WareIndex i, const Widelands::WareDescr * descr)
 			:
-			m_i(i),
-			m_descr(descr)
+			index_(i),
+			descr_(descr)
 			{}
-		Widelands::WareIndex m_i;
-		const Widelands::WareDescr * m_descr;
+		Widelands::WareIndex index_;
+		const Widelands::WareDescr * descr_;
 
 		bool operator<(const Ware o) const {
-			return m_descr->descname() < o.m_descr->descname();
-		}
-	};
+			return descr_->descname() < o.descr_->descname();
+		}
+	};
+
+	struct Worker {
+		Worker(Widelands::WareIndex i, const Widelands::WorkerDescr * descr)
+			:
+			index_(i),
+			descr_(descr)
+			{}
+		Widelands::WareIndex index_;
+		const Widelands::WorkerDescr * descr_;
+
+		bool operator<(const Worker o) const {
+			return descr_->descname() < o.descr_->descname();
+		}
+	};
+
 
 	InteractivePlayer & iaplayer() const;
-	UI::Listselect<Widelands::WareIndex> wares;
-	UI::Listselect<Widelands::BuildingIndex> prodSites;
-	UI::Table     <uintptr_t>                 condTable;
-	UI::MultilineTextarea    descrTxt;
-	Widelands::WareDescr const * selectedWare;
+	UI::TabPanel tabs_;
+
+	// Buildings
+	UI::Box buildings_tab_box_;  // Wrapper box so we can add some padding
+	UI::Box buildings_box_;      // Main contents box for Buildings tab
+	UI::Listselect<Widelands::BuildingIndex> buildings_;
+	UI::MultilineTextarea building_text_;
+	void fill_buildings();
+	void building_selected(uint32_t);
+
+	// Wares
+	UI::Box wares_tab_box_;      // Wrapper box so we can add some padding
+	UI::Box wares_box_;          // Main contents box for Wares tab
+	UI::Box wares_details_box_;  // Horizontal alignment for prod_sites_ and cond_table_
+	UI::Listselect<Widelands::WareIndex> wares_;
+	UI::MultilineTextarea    ware_text_;
+	UI::Listselect<Widelands::BuildingIndex> prod_sites_;
+	UI::Table     <uintptr_t>                 cond_table_;
+	Widelands::WareDescr const * selected_ware_;
 	void fill_wares();
 	void ware_selected(uint32_t);
 	void prod_site_selected(uint32_t);
+
+	// Workers
+	UI::Box workers_tab_box_;  // Wrapper box so we can add some padding
+	UI::Box workers_box_;      // Main contents box for Workers tab
+	UI::Listselect<Widelands::WareIndex> workers_;
+	UI::MultilineTextarea worker_text_;
+	void fill_workers();
+	void worker_selected(uint32_t);
 };
 
 #endif  // end of include guard: WL_WUI_ENCYCLOPEDIA_WINDOW_H

=== modified file 'src/wui/interactive_player.cc'
--- src/wui/interactive_player.cc	2015-02-14 22:11:44 +0000
+++ src/wui/interactive_player.cc	2015-05-10 11:02:17 +0000
@@ -106,7 +106,7 @@
 	 ("menu_toggle_oldmessage_menu", "messages", _("Messages"))),
 m_toggle_help
 	(INIT_BTN
-	 ("menu_help", "help", _("Tribal Ware Encyclopedia")))
+	 ("menu_help", "help", _("Tribal Encyclopedia")))
 
 {
 	m_toggle_chat.sigclicked.connect

=== modified file 'tribes/barbarians/barrier/help.lua'
--- tribes/barbarians/barrier/help.lua	2014-07-20 15:19:51 +0000
+++ tribes/barbarians/barrier/help.lua	2015-05-10 11:02:17 +0000
@@ -1,7 +1,7 @@
 -- The Barbarian Sentry
 
 include "scripting/formatting.lua"
-include "scripting/format_help.lua"
+include "tribes/scripting/format_help.lua"
 
 set_textdomain("tribe_barbarians")
 

=== added file 'tribes/scripting/worker_help.lua'
--- tribes/scripting/worker_help.lua	1970-01-01 00:00:00 +0000
+++ tribes/scripting/worker_help.lua	2015-05-10 11:02:17 +0000
@@ -0,0 +1,113 @@
+set_textdomain("tribes")
+
+--  =======================================================
+--  *************** Basic helper functions ****************
+--  =======================================================
+
+-- RST
+-- .. function:: image_line(image, count[, text = nil])
+--
+--    Aligns the image to a row on the right side with text on the left.
+--
+--    :arg image: the picture to be aligned to a row.
+--    :arg count: length of the picture row.
+--    :arg text: if given the text aligned on the left side, formatted via
+--       formatting.lua functions.
+--    :returns: the text on the left and a picture row on the right.
+--
+function image_line(image, count, text)
+	local imgs={}
+	for i=1,count do
+		imgs[#imgs + 1] = image
+	end
+	local imgstr = table.concat(imgs, ";")
+
+	if text then
+		return rt("image=" .. imgstr .. " image-align=right", "  " .. text)
+	else
+		return rt("image=" .. imgstr .. " image-align=right", "")
+	end
+end
+
+
+--  =======================================================
+--  ************* Main worker help functions *************
+--  =======================================================
+
+-- RST
+-- .. function worker_help_string(worker_description)
+--
+--    Displays the worker with a helptext, an image and the tool used
+--
+--    :arg worker_description: the worker_description from C++.
+--    :returns: Help string for the worker
+--
+function worker_help_string(worker_description)
+	local result = rt(h2(_"Lore")) ..
+		rt("image=" .. worker_description.icon_name, p(worker_description.helptext))
+
+	-- Get the tools for the workers.
+	local toolnames = {}
+	if(worker_description.buildable) then
+		for j, buildcost in ipairs(worker_description.buildcost) do
+			if( not (buildcost == "carrier" or buildcost == "none" or buildcost == nil)) then
+				toolnames[#toolnames + 1] = buildcost
+			end
+		end
+	end
+
+	if(#toolnames > 0) then
+		result = result .. worker_help_tool_string(worker_description.tribename, toolnames)
+	end
+
+	-- TODO(GunChleoc): Add "enhanced from" info in one_tribe branch
+	local becomes_description = worker_description.becomes
+	if(becomes_description) then
+
+		result = result .. rt(h3(_"Experience levels:"))
+		local exp_string = _"%s to %s (%s EP)":format(
+				worker_description.descname,
+				becomes_description.descname,
+				worker_description.needed_experience
+			)
+
+		worker_description = becomes_description
+		becomes_description = worker_description.becomes
+		if(becomes_description) then
+			exp_string = exp_string .. "<br>" .. _"%s to %s (%s EP)":format(
+					worker_description.descname,
+					becomes_description.descname,
+					worker_description.needed_experience
+				)
+		end
+		result = result ..  rt("text-align=right", p(exp_string))
+	end
+	return result
+end
+
+
+-- RST
+-- .. function worker_help_tool_string(tribename, toolname)
+--
+--    Displays tools with an intro text and images
+--
+--    :arg tribename: e.g. "barbarians".
+--    :arg toolnames: e.g. {"shovel", "basket"}.
+--    :returns: image_line for the tools
+--
+function worker_help_tool_string(tribename, toolnames)
+	local result = rt(h3(ngettext("Worker uses:","Workers use:", 1)))
+	local game  = wl.Game();
+	for i, toolname in ipairs(toolnames) do
+		local ware_description = game:get_ware_description(tribename, toolname)
+		result = result .. image_line(ware_description.icon_name, 1, p(ware_description.descname))
+	end
+	return result
+end
+
+
+return {
+   func = function(worker_description)
+	return worker_help_string(worker_description)
+  end
+}


Follow ups