← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1731652-worker-plant-attribute into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1731652-worker-plant-attribute into lp:widelands.

Commit message:
Removed "tribe:" parameter from workers' "plant" program

- The worker program "plant" no longer takes "tribe:" as a parameter - immovables are now
  identified via their attibutes only, and both world and tribe immovables are searched.

- Code cleanup: helptext_script() is now a function of MapObject. Renamed "build_cost"
  to "buildcost" for consistency.

- Documentation: Added immovables to in-game help and documented worker helptexts.


Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1338204 in widelands: "Add terrain affinity for tribe immovables"
  https://bugs.launchpad.net/widelands/+bug/1338204
  Bug #1731652 in widelands: "Worker program "plant": Allow "attrib:" for tribe immovables"
  https://bugs.launchpad.net/widelands/+bug/1731652

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1731652-worker-plant-attribute/+merge/333934
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1731652-worker-plant-attribute into lp:widelands.
=== removed file 'data/scripting/editor/format_editor.lua'
--- data/scripting/editor/format_editor.lua	2016-09-01 15:43:01 +0000
+++ data/scripting/editor/format_editor.lua	1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
--- RST
--- format_editor.lua
--- -----------------
---
--- Functions used in the ingame editor help windows for formatting the text and pictures.
-
-include "scripting/formatting.lua"
-
--- RST
--- .. function:: picture_li(imagepath, text)
---
---    Places a paragraph of text to the right of an image
-
---    :arg imagepath: the full path to the image file
---    :arg text: the text to be placed next to the image
---
---    :returns: the text wrapped in a paragraph and placed next to the image
-function picture_li(imagepath, text)
-   return "<rt image=" .. imagepath .. " image-align=left>"
-      .. p(text) .. "</rt>"
-end
-
--- RST
--- .. function:: spacer()
---
---    Adds a little space between two paragraphs
---
---    :returns: a small empty paragraph
-function spacer()
-   return rt(p("font-size=3", ""))
-end

=== modified file 'data/scripting/editor/terrain_help.lua'
--- data/scripting/editor/terrain_help.lua	2016-09-01 15:23:25 +0000
+++ data/scripting/editor/terrain_help.lua	2017-11-18 14:09:59 +0000
@@ -5,7 +5,7 @@
 -- This script returns a formatted entry for the terrain help in the editor.
 -- Pass the internal terrain name to the coroutine to select the terrain type.
 
-include "scripting/editor/format_editor.lua"
+include "scripting/formatting.lua"
 
 return {
    func = function(terrain_name)

=== modified file 'data/scripting/editor/tree_help.lua'
--- data/scripting/editor/tree_help.lua	2016-09-01 15:23:25 +0000
+++ data/scripting/editor/tree_help.lua	2017-11-18 14:09:59 +0000
@@ -1,11 +1,12 @@
 -- RST
 -- tree_help.lua
--- ---------------
+-- -------------
 --
 -- This script returns a formatted entry for the tree help in the editor.
 -- Pass the internal tree name to the coroutine to select the tree type.
 
-include "scripting/editor/format_editor.lua"
+include "scripting/formatting.lua"
+include "scripting/help.lua"
 
 return {
    func = function(tree_name)
@@ -15,31 +16,9 @@
       local result = picture_li(tree.representative_image, "")
 
       -- TRANSLATORS: A header in the editor help. Terrains preferred by a type of tree.
-      result = result .. rt(p("font-size=3", "")) .. rt(h2(_"Preferred terrains")) .. spacer()
-      terrain_list = {}
-      for i, terrain in ipairs(world.terrain_descriptions) do
-         local probability = tree:probability_to_grow(terrain)
-         if (probability > 0.01) then
-            -- sort the terrains by percentage
-            i = 1
-            while (terrain_list[i] and (terrain_list[i].probability > probability)) do
-               i = i + 1
-            end
-
-            for j = #terrain_list, i, -1 do
-               terrain_list[j+1] = terrain_list[j]
-            end
-            terrain_list[i] = {terrain = terrain, probability = probability}
-         end
-      end
-
-      for k,v in ipairs(terrain_list) do
-         result = result .. picture_li(v.terrain.representative_image,
-               -- TRANSLATORS: Terrain name (Climate)
-               (_"%1% (%2%)"):bformat(v.terrain.descname, v.terrain.editor_category.descname) ..
-               "<br>" .. ("%2.1f%%"):bformat(100 * v.probability)
-            ) .. spacer()
-      end
+      result = result .. spacer() .. rt(h2(_"Preferred terrains")) .. spacer()
+      result = result .. terrain_affinity_help(tree)
+
       return {
          title = tree.species,
          text = result

=== modified file 'data/scripting/formatting.lua'
--- data/scripting/formatting.lua	2017-05-11 17:29:55 +0000
+++ data/scripting/formatting.lua	2017-11-18 14:09:59 +0000
@@ -278,3 +278,27 @@
 function paragraphdivider()
    return ("<br></p><p font-size=8><br></p><p line-spacing=3 font-size=12>")
 end
+
+-- RST
+-- .. function:: picture_li(imagepath, text)
+--
+--    Places a paragraph of text to the right of an image
+
+--    :arg imagepath: the full path to the image file
+--    :arg text: the text to be placed next to the image
+--
+--    :returns: the text wrapped in a paragraph and placed next to the image
+function picture_li(imagepath, text)
+   return "<rt image=" .. imagepath .. " image-align=left>"
+      .. p(text) .. "</rt>"
+end
+
+-- RST
+-- .. function:: spacer()
+--
+--    Adds a little space between two paragraphs
+--
+--    :returns: a small empty paragraph
+function spacer()
+   return rt(p("font-size=3", ""))
+end

=== added file 'data/scripting/help.lua'
--- data/scripting/help.lua	1970-01-01 00:00:00 +0000
+++ data/scripting/help.lua	2017-11-18 14:09:59 +0000
@@ -0,0 +1,54 @@
+-- RST
+-- help.lua
+-- --------
+--
+-- This script contains functions that are used both in the Tribal Encyclopedia
+-- and the Editor help.
+
+include "scripting/formatting.lua"
+
+
+-- RST
+-- .. function:: terrain_affinity_help(immovable_description)
+--
+--    Returns a formatted help string for the terrains that the given
+--    immovable is most likely to grow on.
+--
+--    :arg immovable_description: The immovable type that we want the information for.
+--    :type immovable_description: :class:`LuaImmovableDescription`
+--    :returns: a richtext-formatted list of terrain images, terrain names and probabilities.
+--
+function terrain_affinity_help(immovable_description)
+   set_textdomain("widelands")
+   local world = wl.World();
+   local result = ""
+   terrain_list = {}
+   for i, terrain in ipairs(world.terrain_descriptions) do
+      local probability = immovable_description:probability_to_grow(terrain)
+      if (probability > 0.01) then
+         -- sort the terrains by percentage
+         i = 1
+         while (terrain_list[i] and (terrain_list[i].probability > probability)) do
+            i = i + 1
+         end
+
+         for j = #terrain_list, i, -1 do
+            terrain_list[j+1] = terrain_list[j]
+         end
+         terrain_list[i] = {terrain = terrain, probability = probability}
+      end
+   end
+
+   for k,v in ipairs(terrain_list) do
+      if (k <= 10 or v.probability > 0.25) then
+         result = result .. picture_li(v.terrain.representative_image,
+               -- TRANSLATORS: Terrain name (Climate)
+               (_"%1% (%2%)"):bformat(v.terrain.descname, v.terrain.editor_category.descname) .. "<br>" ..
+               -- TRANSLATORS: Help text - Probability to grow for an immovable
+               (_("%2.1f%%")):bformat(100 * v.probability)
+            ) .. spacer()
+      end
+   end
+   return result
+end
+

=== modified file 'data/tribes/immovables/ashes/helptexts.lua'
--- data/tribes/immovables/ashes/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/ashes/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a tribe immovable
+      default = _("The remains of a destroyed building.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/ashes/init.lua'
--- data/tribes/immovables/ashes/init.lua	2016-10-18 09:06:47 +0000
+++ data/tribes/immovables/ashes/init.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,8 @@
 -- RST
 -- .. _lua_tribes_immovables:
 --
--- Tribe Immovables
--- ----------------
+-- Immovables
+-- ==========
 --
 -- Immovables are entities not connected to a road that a tribe can own,
 -- for example a corn field or a ship under construction.
@@ -28,6 +28,8 @@
 --    **descname**: The translatable display name. Use ``pgettext`` with the
 --    ``msgctxt`` above to fetch the string.
 --
+--    **helptext_script**:  The full path to the ``helptexts.lua`` script for this immovable.
+--
 --    **programs**: A table with the programs that this immovable will perform,
 --    e.g. ``{ animate=idle 4500,  remove= }``
 --
@@ -38,6 +40,7 @@
    name = "ashes",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Ashes"),
+   helptext_script = dirname .. "helptexts.lua",
    programs = {
       program = {
          "animate=idle 45000",
@@ -52,3 +55,22 @@
       },
    }
 }
+
+
+-- RST
+--
+-- Help Texts
+-- ----------
+--
+-- Each tribe immovable has a ``helptexts.lua`` script, which is located in the same directory as its ``init.lua`` script.
+-- The function in this file returns texts that are used for the immovable by the Tribal Encyclopedia.
+--
+-- .. function:: immovable_helptext([tribe])
+--
+--    Returns a localized string with a helptext for this immovable type.
+--
+--    :arg tribe: the name of the tribe to fetch this helptext for.
+--    :type tribe: :class:`string`
+--
+--    This function works exactly the same as :any:`ware_helptext`.
+--

=== modified file 'data/tribes/immovables/blackrootfield_harvested/helptexts.lua'
--- data/tribes/immovables/blackrootfield_harvested/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/blackrootfield_harvested/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field has been harvested.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/blackrootfield_harvested/init.lua'
--- data/tribes/immovables/blackrootfield_harvested/init.lua	2016-04-27 18:50:19 +0000
+++ data/tribes/immovables/blackrootfield_harvested/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "blackrootfield_harvested",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Blackroot Field (harvested)"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "field" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/blackrootfield_medium/helptexts.lua'
--- data/tribes/immovables/blackrootfield_medium/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/blackrootfield_medium/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/blackrootfield_medium/init.lua'
--- data/tribes/immovables/blackrootfield_medium/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/blackrootfield_medium/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "blackrootfield_medium",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Blackroot Field (medium)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/blackrootfield_ripe/helptexts.lua'
--- data/tribes/immovables/blackrootfield_ripe/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/blackrootfield_ripe/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is ready for harvesting.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/blackrootfield_ripe/init.lua'
--- data/tribes/immovables/blackrootfield_ripe/init.lua	2015-11-20 18:21:27 +0000
+++ data/tribes/immovables/blackrootfield_ripe/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "blackrootfield_ripe",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Blackroot Field (ripe)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "ripe_blackroot", "field" },
    programs = {

=== modified file 'data/tribes/immovables/blackrootfield_small/helptexts.lua'
--- data/tribes/immovables/blackrootfield_small/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/blackrootfield_small/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/blackrootfield_small/init.lua'
--- data/tribes/immovables/blackrootfield_small/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/blackrootfield_small/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "blackrootfield_small",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Blackroot Field (small)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/blackrootfield_tiny/helptexts.lua'
--- data/tribes/immovables/blackrootfield_tiny/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/blackrootfield_tiny/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field has just been planted.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/blackrootfield_tiny/init.lua'
--- data/tribes/immovables/blackrootfield_tiny/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/blackrootfield_tiny/init.lua	2017-11-18 14:09:59 +0000
@@ -5,8 +5,9 @@
    name = "blackrootfield_tiny",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Blackroot Field (tiny)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
-   attributes = { "field" },
+   attributes = { "field", "seed_blackroot" },
    programs = {
       program = {
          "animate=idle 30000",

=== modified file 'data/tribes/immovables/cornfield_harvested/helptexts.lua'
--- data/tribes/immovables/cornfield_harvested/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/cornfield_harvested/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field has been harvested.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/cornfield_harvested/init.lua'
--- data/tribes/immovables/cornfield_harvested/init.lua	2016-04-27 18:50:19 +0000
+++ data/tribes/immovables/cornfield_harvested/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "cornfield_harvested",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Cornfield (harvested)"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "field" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/cornfield_medium/helptexts.lua'
--- data/tribes/immovables/cornfield_medium/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/cornfield_medium/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/cornfield_medium/init.lua'
--- data/tribes/immovables/cornfield_medium/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/cornfield_medium/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "cornfield_medium",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Cornfield (medium)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/cornfield_ripe/helptexts.lua'
--- data/tribes/immovables/cornfield_ripe/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/cornfield_ripe/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is ready for harvesting.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/cornfield_ripe/init.lua'
--- data/tribes/immovables/cornfield_ripe/init.lua	2015-11-20 18:21:27 +0000
+++ data/tribes/immovables/cornfield_ripe/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "cornfield_ripe",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Cornfield (ripe)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "ripe_corn", "field" },
    programs = {

=== modified file 'data/tribes/immovables/cornfield_small/helptexts.lua'
--- data/tribes/immovables/cornfield_small/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/cornfield_small/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/cornfield_small/init.lua'
--- data/tribes/immovables/cornfield_small/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/cornfield_small/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "cornfield_small",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Cornfield (small)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/cornfield_tiny/helptexts.lua'
--- data/tribes/immovables/cornfield_tiny/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/cornfield_tiny/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field has just been planted.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/cornfield_tiny/init.lua'
--- data/tribes/immovables/cornfield_tiny/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/cornfield_tiny/init.lua	2017-11-18 14:09:59 +0000
@@ -5,8 +5,9 @@
    name = "cornfield_tiny",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Cornfield (tiny)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
-   attributes = { "field" },
+   attributes = { "field", "seed_corn" },
    programs = {
       program = {
          "animate=idle 30000",

=== modified file 'data/tribes/immovables/destroyed_building/helptexts.lua'
--- data/tribes/immovables/destroyed_building/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/destroyed_building/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a tribe immovable
+      default = _("The remains of a destroyed building.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/destroyed_building/init.lua'
--- data/tribes/immovables/destroyed_building/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/destroyed_building/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "destroyed_building",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Destroyed building"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "big",
    programs = {
       program = {

=== modified file 'data/tribes/immovables/field_harvested/helptexts.lua'
--- data/tribes/immovables/field_harvested/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/field_harvested/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field has been harvested.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/field_harvested/init.lua'
--- data/tribes/immovables/field_harvested/init.lua	2016-04-27 18:50:19 +0000
+++ data/tribes/immovables/field_harvested/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "field_harvested",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Field (harvested)"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "field" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/field_medium/helptexts.lua'
--- data/tribes/immovables/field_medium/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/field_medium/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/field_medium/init.lua'
--- data/tribes/immovables/field_medium/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/field_medium/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "field_medium",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Field (medium)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/field_ripe/helptexts.lua'
--- data/tribes/immovables/field_ripe/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/field_ripe/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is ready for harvesting.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/field_ripe/init.lua'
--- data/tribes/immovables/field_ripe/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/field_ripe/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "field_ripe",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Field (ripe)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "ripe_wheat", "field" },
    programs = {

=== modified file 'data/tribes/immovables/field_small/helptexts.lua'
--- data/tribes/immovables/field_small/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/field_small/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/field_small/init.lua'
--- data/tribes/immovables/field_small/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/field_small/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "field_small",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Field (small)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/field_tiny/helptexts.lua'
--- data/tribes/immovables/field_tiny/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/field_tiny/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a field
+      default = _("This field has just been planted.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/field_tiny/init.lua'
--- data/tribes/immovables/field_tiny/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/field_tiny/init.lua	2017-11-18 14:09:59 +0000
@@ -5,8 +5,18 @@
    name = "field_tiny",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Field (tiny)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
-   attributes = { "field" },
+   attributes = { "field", "seed_wheat" },
+
+   -- NOCOM for testing only. Remove before merging.
+   terrain_affinity = {
+      preferred_temperature = 110,
+      preferred_humidity = 0.4,
+      preferred_fertility = 0.6,
+      pickiness = 0.6,
+   },
+
    programs = {
       program = {
          "animate=idle 30000",

=== modified file 'data/tribes/immovables/grapevine_medium/helptexts.lua'
--- data/tribes/immovables/grapevine_medium/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/grapevine_medium/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a grapevine
+      default = _("This grapevine is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/grapevine_medium/init.lua'
--- data/tribes/immovables/grapevine_medium/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/grapevine_medium/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "grapevine_medium",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Grapevine (medium)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "medium",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/grapevine_ripe/helptexts.lua'
--- data/tribes/immovables/grapevine_ripe/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/grapevine_ripe/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a grapevine
+      default = _("This grapevine is ready for harvesting.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/grapevine_ripe/init.lua'
--- data/tribes/immovables/grapevine_ripe/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/grapevine_ripe/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "grapevine_ripe",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Grapevine (ripe)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "medium",
    attributes = { "ripe_grapes", "field" },
    programs = {

=== modified file 'data/tribes/immovables/grapevine_small/helptexts.lua'
--- data/tribes/immovables/grapevine_small/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/grapevine_small/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a grapevine
+      default = _("This grapevine is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/grapevine_small/init.lua'
--- data/tribes/immovables/grapevine_small/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/grapevine_small/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "grapevine_small",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Grapevine (small)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "medium",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/grapevine_tiny/helptexts.lua'
--- data/tribes/immovables/grapevine_tiny/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/grapevine_tiny/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a grapevine
+      default = _("This grapevine has just been planted.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/grapevine_tiny/init.lua'
--- data/tribes/immovables/grapevine_tiny/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/grapevine_tiny/init.lua	2017-11-18 14:09:59 +0000
@@ -5,8 +5,9 @@
    name = "grapevine_tiny",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Grapevine (tiny)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "medium",
-   attributes = { "field" },
+   attributes = { "field", "seed_grapes" },
    programs = {
       program = {
          "animate=idle 22000",

=== modified file 'data/tribes/immovables/reed_medium/helptexts.lua'
--- data/tribes/immovables/reed_medium/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/reed_medium/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a reed field
+      default = _("This reed is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/reed_medium/init.lua'
--- data/tribes/immovables/reed_medium/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/reed_medium/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "reed_medium",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Reed (medium)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/reed_ripe/helptexts.lua'
--- data/tribes/immovables/reed_ripe/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/reed_ripe/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a reed field
+      default = _("This reed is ready for harvesting.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/reed_ripe/init.lua'
--- data/tribes/immovables/reed_ripe/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/reed_ripe/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "reed_ripe",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Reed (ripe)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "ripe_reed", "field" },
    programs = {

=== modified file 'data/tribes/immovables/reed_small/helptexts.lua'
--- data/tribes/immovables/reed_small/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/reed_small/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a reed field
+      default = _("This reed is growing.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/reed_small/init.lua'
--- data/tribes/immovables/reed_small/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/reed_small/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "reed_small",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Reed (small)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
    attributes = { "field" },
    programs = {

=== modified file 'data/tribes/immovables/reed_tiny/helptexts.lua'
--- data/tribes/immovables/reed_tiny/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/reed_tiny/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a reed field
+      default = _("This reed has just been planted.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/reed_tiny/init.lua'
--- data/tribes/immovables/reed_tiny/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/reed_tiny/init.lua	2017-11-18 14:09:59 +0000
@@ -5,8 +5,9 @@
    name = "reed_tiny",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Reed (tiny)"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
-   attributes = { "field" },
+   attributes = { "field", "seed_reed" },
    programs = {
       program = {
          "animate=idle 22000",

=== modified file 'data/tribes/immovables/resi_coal1/helptexts.lua'
--- data/tribes/immovables/resi_coal1/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_coal1/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,10 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Coal
-      default = "Coal veins contain coal that can be dug up by coal mines." .. " " .. "There is only a little bit of coal here."
+      default = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a resource: Coal
+         _("Coal veins contain coal that can be dug up by coal mines."),
+         -- TRANSLATORS: Helptext for a resource: Coal
+         _("There is only a little bit of coal here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_coal1/init.lua'
--- data/tribes/immovables/resi_coal1/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_coal1/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_coal1",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Coal Vein"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_coal2/helptexts.lua'
--- data/tribes/immovables/resi_coal2/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_coal2/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,10 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Coal
-      default = "Coal veins contain coal that can be dug up by coal mines." .. " " .. "There is a lot of coal here."
+      default = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a resource: Coal
+         _("Coal veins contain coal that can be dug up by coal mines."),
+         -- TRANSLATORS: Helptext for a resource: Coal
+         _("There is a lot of coal here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_coal2/init.lua'
--- data/tribes/immovables/resi_coal2/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_coal2/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_coal2",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Main Coal Vein"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_gold1/helptexts.lua'
--- data/tribes/immovables/resi_gold1/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_gold1/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,10 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Gold
-      default = "Gold veins contain gold ore that can be dug up by gold mines." .. " " .. "There is only a little bit of gold here."
+      default = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a resource: Gold
+         _("Gold veins contain gold ore that can be dug up by gold mines."),
+         -- TRANSLATORS: Helptext for a resource: Gold
+         _("There is only a little bit of gold here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_gold1/init.lua'
--- data/tribes/immovables/resi_gold1/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_gold1/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_gold1",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Gold Vein"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_gold2/helptexts.lua'
--- data/tribes/immovables/resi_gold2/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_gold2/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,10 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Gold
-      default = "Gold veins contain gold ore that can be dug up by gold mines." .. " " .. "There is a lot of gold here."
+      default = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a resource: Gold
+         _("Gold veins contain gold ore that can be dug up by gold mines."),
+         -- TRANSLATORS: Helptext for a resource: Gold
+         _("There is a lot of gold here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_gold2/init.lua'
--- data/tribes/immovables/resi_gold2/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_gold2/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_gold2",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Main Gold Vein"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_iron1/helptexts.lua'
--- data/tribes/immovables/resi_iron1/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_iron1/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,10 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Iron
-      default = "Iron veins contain iron ore that can be dug up by iron mines." .. " " .. "There is only a little bit of iron here."
+      default = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a resource: Iron
+         _("Iron veins contain iron ore that can be dug up by iron mines."),
+         -- TRANSLATORS: Helptext for a resource: Iron
+         _("There is only a little bit of iron here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_iron1/init.lua'
--- data/tribes/immovables/resi_iron1/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_iron1/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_iron1",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Iron Vein"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_iron2/helptexts.lua'
--- data/tribes/immovables/resi_iron2/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_iron2/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,10 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Iron
-      default = "Iron veins contain iron ore that can be dug up by iron mines." .. " " .. "There is a lot of iron here."
+      default = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a resource: Iron
+         _("Iron veins contain iron ore that can be dug up by iron mines."),
+         -- TRANSLATORS: Helptext for a resource: Iron
+         _("There is a lot of iron here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_iron2/init.lua'
--- data/tribes/immovables/resi_iron2/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_iron2/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_iron2",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Main Iron Vein"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_none/helptexts.lua'
--- data/tribes/immovables/resi_none/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_none/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: No resources
-      default = "There are no resources in the ground here."
+      -- TRANSLATORS: Helptext for a resource: No resources
+      default = _("There are no resources in the ground here.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_none/init.lua'
--- data/tribes/immovables/resi_none/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_none/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_none",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "No Resources"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_stones1/helptexts.lua'
--- data/tribes/immovables/resi_stones1/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_stones1/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,13 +1,20 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Stones
-      atlanteans = "Precious stones are used in the construction of big buildings. They can be dug up by a crystal mine." .. " " .. "There are only a few precious stones here.",
-      -- TRANSLATORS#: Helptext for a resource: Stones
-      barbarians = "Granite is a basic building material and can be dug up by a granite mine." .. " " .. "There is only a little bit of granite here.",
-      -- TRANSLATORS#: Helptext for a resource: Stones
-      empire = "Marble is a basic building material and can be dug up by a marble mine. You will also get granite from the mine." .. " " .. "There is only a little bit of marble here."
+      atlanteans = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for an Atlantean resource: Stones
+         _("Precious stones are used in the construction of big buildings. They can be dug up by a crystal mine."),
+         -- TRANSLATORS: Helptext for an Atlantean resource: Stones
+         _("There are only a few precious stones here.")),
+      barbarians = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a Barbarian resource: Stones
+         _("Granite is a basic building material and can be dug up by a granite mine."),
+         -- TRANSLATORS: Helptext for a Barbarian resource: Stones
+         _("There is only a little bit of granite here.")),
+      empire = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for an Empire resource: Stones
+         _("Marble is a basic building material and can be dug up by a marble mine. You will also get granite from the mine."),
+         -- TRANSLATORS: Helptext for an Empire resource: Stones
+         _("There is only a little bit of marble here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_stones1/init.lua'
--- data/tribes/immovables/resi_stones1/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_stones1/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_stones1",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Some Stones"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_stones2/helptexts.lua'
--- data/tribes/immovables/resi_stones2/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_stones2/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,13 +1,20 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Stones
-      atlanteans = "Precious stones are used in the construction of big buildings. They can be dug up by a crystal mine." .. " " .. "There are many precious stones here.",
-      -- TRANSLATORS#: Helptext for a resource: Stones
-      barbarians = "Granite is a basic building material and can be dug up by a granite mine." .. " " .. "There is a lot of granite here.",
-      -- TRANSLATORS#: Helptext for a resource: Stones
-      empire = "Marble is a basic building material and can be dug up by a marble mine. You will also get granite from the mine." .. " " .. "There is a lot of marble here."
+      atlanteans = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for an Atlantean resource: Stones
+         _("Precious stones are used in the construction of big buildings. They can be dug up by a crystal mine."),
+         -- TRANSLATORS: Helptext for an Atlantean resource: Stones
+         _("There are many precious stones here.")),
+      barbarians = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for a Barbarian resource: Stones
+         _("Granite is a basic building material and can be dug up by a granite mine."),
+         -- TRANSLATORS: Helptext for a Barbarian resource: Stones
+         _("There is a lot of granite here.")),
+      empire = pgettext("sentence_separator", "%s %s"):bformat(
+         -- TRANSLATORS: Helptext for an Empire resource: Stones
+         _("Marble is a basic building material and can be dug up by a marble mine. You will also get granite from the mine."),
+         -- TRANSLATORS: Helptext for an Empire resource: Stones
+         _("There is a lot of marble here."))
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_stones2/init.lua'
--- data/tribes/immovables/resi_stones2/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_stones2/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_stones2",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "A Lot of Stones"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/resi_water1/helptexts.lua'
--- data/tribes/immovables/resi_water1/helptexts.lua	2015-12-02 04:01:09 +0000
+++ data/tribes/immovables/resi_water1/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,9 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      -- TRANSLATORS#: Helptext for a resource: Water
-      default = "There is water in the ground here that can be pulled up by a well."
+      -- TRANSLATORS: Helptext for a resource: Water
+      default = _("There is water in the ground here that can be pulled up by a well.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/resi_water1/init.lua'
--- data/tribes/immovables/resi_water1/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/resi_water1/init.lua	2017-11-18 14:09:59 +0000
@@ -5,6 +5,7 @@
    name = "resi_water1",
    -- TRANSLATORS: This is a resource name used in lists of resources
    descname = pgettext("immovable", "Water Vein"),
+   helptext_script = dirname .. "helptexts.lua",
    attributes = { "resi" },
    programs = {
       program = {

=== modified file 'data/tribes/immovables/shipconstruction_atlanteans/helptexts.lua'
--- data/tribes/immovables/shipconstruction_atlanteans/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/shipconstruction_atlanteans/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a ship construction site.
+      default = _("A ship is being constructed at this site.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/shipconstruction_atlanteans/init.lua'
--- data/tribes/immovables/shipconstruction_atlanteans/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/shipconstruction_atlanteans/init.lua	2017-11-18 14:09:59 +0000
@@ -5,7 +5,9 @@
    name = "atlanteans_shipconstruction",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Ship Under Construction"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
+   attributes = { "shipconstruction" },
    programs = {
       program = {
          "construction=idle 5000 210000",

=== modified file 'data/tribes/immovables/shipconstruction_barbarians/helptexts.lua'
--- data/tribes/immovables/shipconstruction_barbarians/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/shipconstruction_barbarians/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a ship construction site.
+      default = _("A ship is being constructed at this site.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/shipconstruction_barbarians/init.lua'
--- data/tribes/immovables/shipconstruction_barbarians/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/shipconstruction_barbarians/init.lua	2017-11-18 14:09:59 +0000
@@ -5,7 +5,9 @@
    name = "barbarians_shipconstruction",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Ship Under Construction"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
+   attributes = { "shipconstruction" },
    programs = {
       program = {
          "construction=idle 5000 210000",

=== modified file 'data/tribes/immovables/shipconstruction_empire/helptexts.lua'
--- data/tribes/immovables/shipconstruction_empire/helptexts.lua	2015-10-31 12:11:44 +0000
+++ data/tribes/immovables/shipconstruction_empire/helptexts.lua	2017-11-18 14:09:59 +0000
@@ -1,8 +1,7 @@
--- TODO(GunChleoc): This is unused
-
 function immovable_helptext(tribe)
    local helptext = {
-      default = ""
+      -- TRANSLATORS: Helptext for a ship construction site.
+      default = _("A ship is being constructed at this site.")
    }
    local result = ""
    if tribe then

=== modified file 'data/tribes/immovables/shipconstruction_empire/init.lua'
--- data/tribes/immovables/shipconstruction_empire/init.lua	2015-11-03 18:18:27 +0000
+++ data/tribes/immovables/shipconstruction_empire/init.lua	2017-11-18 14:09:59 +0000
@@ -5,7 +5,9 @@
    name = "empire_shipconstruction",
    -- TRANSLATORS: This is an immovable name used in lists of immovables
    descname = pgettext("immovable", "Ship Under Construction"),
+   helptext_script = dirname .. "helptexts.lua",
    size = "small",
+   attributes = { "shipconstruction" },
    programs = {
       program = {
          "construction=idle 5000 210000",

=== modified file 'data/tribes/scripting/help/building_help.lua'
--- data/tribes/scripting/help/building_help.lua	2016-10-01 07:43:45 +0000
+++ data/tribes/scripting/help/building_help.lua	2017-11-18 14:09:59 +0000
@@ -453,7 +453,7 @@
          else
             result = result .. rt(h3(_"Build cost:"))
          end
-         for ware, amount in pairs(building_description.build_cost) do
+         for ware, amount in pairs(building_description.buildcost) do
             local ware_description = wl.Game():get_ware_description(ware)
             result = result .. help_ware_amount_line(ware_description, amount)
          end
@@ -494,7 +494,7 @@
          for index, former in pairs(former_buildings) do
             former_building = wl.Game():get_building_description(former.name)
             if (former_building.buildable) then
-               for ware, amount in pairs(former_building.build_cost) do
+               for ware, amount in pairs(former_building.buildcost) do
                   if (warescost[ware]) then
                      warescost[ware] = warescost[ware] + amount
                   else

=== added file 'data/tribes/scripting/help/immovable_help.lua'
--- data/tribes/scripting/help/immovable_help.lua	1970-01-01 00:00:00 +0000
+++ data/tribes/scripting/help/immovable_help.lua	2017-11-18 14:09:59 +0000
@@ -0,0 +1,85 @@
+-- RST
+-- immovable_help.lua
+-- ------------------
+--
+-- This script returns a formatted entry for the in-game immovable help (Tribal Encyclopedia).
+-- Pass the internal tribe name and immovable name to the coroutine to select the
+-- immovable type.
+
+include "tribes/scripting/help/format_help.lua"
+
+--  =======================================================
+--  ************ Main immovable help functions ************
+--  =======================================================
+
+-- RST
+-- .. function:: immovable_help_string(tribe, immovable_description)
+--
+--    Displays the immovable with a helptext.
+--
+--    :arg tribe: the tribe that we are displaying this help for; the same immovable
+--       can be used by various tribes in different ways.
+--    :type tribe: :class:`LuaTribeDescription`
+--
+--    :arg immovable_description: the immovable_description that the help is
+--       being displayed for.
+--    :type immovable_description: :class:`LuaImmovableDescription`
+--
+--    :returns: Help string for the immovable
+--
+function immovable_help_string(tribe, immovable_description)
+   include(immovable_description.helptext_script)
+
+   -- TRANSLATORS: Put 2 sentences one after the other. Languages using Chinese script probably want to lose the blank space here.
+   local purpose_text = pgettext("sentence_separator", "%s %s"):bformat(immovable_helptext(), immovable_helptext(tribe.name))
+
+   local result = rt("image=" .. immovable_description.representative_image, p(purpose_text))
+
+   -- Build cost
+   local buildcost = ""
+   for ware, amount in pairs(immovable_description.buildcost) do
+      local ware_description = wl.Game():get_ware_description(ware)
+      buildcost = buildcost .. help_ware_amount_line(ware_description, amount)
+   end
+
+   -- Space required
+   local space_required = ""
+   if (immovable_description.size == "small") then
+      space_required = space_required .. text_line(_"Space required:",_"Small plot","images/wui/overlays/small.png")
+   elseif (immovable_description.size == "medium") then
+      space_required = space_required .. text_line(_"Space required:",_"Medium plot","images/wui/overlays/medium.png")
+   elseif (immovable_description.size == "big") then
+      space_required = space_required .. text_line(_"Space required:",_"Big plot","images/wui/overlays/big.png")
+   end
+
+   if (buildcost ~= "" or space_required ~= "") then
+      result = result .. rt(spacer() .. h2(_"Requirements"))
+      if (buildcost ~= "") then
+         result = result .. rt(h3(_"Build cost:")) .. buildcost
+      end
+      result = result .. space_required
+   end
+
+   -- Terrain affinity
+   local affinity = immovable_description.terrain_affinity
+   if (affinity ~= nil) then
+      include "scripting/help.lua"
+      result = result .. rt(h2(_"Preferred Terrains"))
+      result = result .. terrain_affinity_help(immovable_description)
+   end
+
+   return result
+end
+
+
+return {
+   func = function(tribename, immovablename)
+      set_textdomain("tribes_encyclopedia")
+      local tribe = wl.Game():get_tribe_description(tribename)
+      local immovable_description = wl.Game():get_immovable_description(immovablename)
+      return {
+         title = immovable_description.descname,
+         text = immovable_help_string(tribe, immovable_description)
+      }
+   end
+}

=== modified file 'data/tribes/scripting/help/init.lua'
--- data/tribes/scripting/help/init.lua	2016-10-19 08:50:16 +0000
+++ data/tribes/scripting/help/init.lua	2017-11-18 14:09:59 +0000
@@ -40,6 +40,12 @@
    return map_object_entries(tribename, "tribes/scripting/help/worker_help.lua", tribe.workers)
 end
 
+-- Returns help entries for all the immovables that the tribe can use
+function immovable_entries(tribename)
+   local tribe = wl.Game():get_tribe_description(tribename)
+   return map_object_entries(tribename, "tribes/scripting/help/immovable_help.lua", tribe.immovables)
+end
+
 -- Main function
 return {
    func = function(tribename, game_type)
@@ -94,6 +100,13 @@
                icon = "images/wui/stats/genstats_nrbuildings.png",
                entries = building_entries(tribename)
             },
+            {
+               name = "immovables",
+               -- TRANSLATORS Tab title: immovable help
+               title = _"Immovables",
+               icon = "tribes/immovables/field_ripe/idle_00.png",
+               entries = immovable_entries(tribename)
+            },
          }
       }
    end

=== modified file 'data/tribes/scripting/help/ware_help.lua'
--- data/tribes/scripting/help/ware_help.lua	2017-01-21 09:39:55 +0000
+++ data/tribes/scripting/help/ware_help.lua	2017-11-18 14:09:59 +0000
@@ -1,6 +1,5 @@
 include "tribes/scripting/help/format_help.lua"
 
-
 -- RST
 -- ware_help.lua
 -- ---------------
@@ -28,8 +27,7 @@
    if (purpose_text ~= "") then
       purpose_text = purpose_text .. " "
    end
-   -- TRANSLATORS: Put 2 sentences one after the other.
-   -- Languages using Chinese script probably want to lose the blank space here.
+   -- TRANSLATORS: Put 2 sentences one after the other. Languages using Chinese script probably want to lose the blank space here.
    purpose_text = pgettext("sentence_separator", "%s %s"):bformat(ware_helptext(), ware_helptext(tribe.name))
 
    -- TODO(GunChleoc): Split into purpose and note

=== modified file 'data/tribes/wares/armor/init.lua'
--- data/tribes/wares/armor/init.lua	2017-02-20 14:07:53 +0000
+++ data/tribes/wares/armor/init.lua	2017-11-18 14:09:59 +0000
@@ -2,7 +2,7 @@
 -- .. _lua_tribes_wares:
 --
 -- Wares
--- -----
+-- =====
 --
 -- Wares are used to build buildings, produce other wares and recruit units.
 --
@@ -66,3 +66,29 @@
       },
    }
 }
+
+-- RST
+--
+-- Help Texts
+-- ----------
+--
+-- Each ware has a ``helptexts.lua`` script, which is located in the same directory as its ``init.lua`` script.
+-- The function in this file returns texts that are used for the ware by the Tribal Encyclopedia.
+--
+-- .. function:: ware_helptext([tribe])
+--
+--    Returns a localized string with a helptext for this ware type.
+--
+--    :arg tribe: the name of the tribe to fetch this helptext for.
+--    :type tribe: :class:`string`
+--
+--    If you call this function without a tribe name, it will deliver a default
+--    help text, if present. Both a default and a tribe helptext can be defined
+--    at the same time, and they are designed in such a way that they are supposed
+--    to be concatenated. Example call of this function::
+--
+--        pgettext("sentence_separator", "%s %s"):bformat(ware_helptext(), ware_helptext(tribename))
+--
+--    If you wish to define helptexts of your own, best copy over this function
+--    from another ware and then fill in the data.
+--

=== modified file 'data/tribes/workers/atlanteans/blackroot_farmer/init.lua'
--- data/tribes/workers/atlanteans/blackroot_farmer/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/atlanteans/blackroot_farmer/init.lua	2017-11-18 14:09:59 +0000
@@ -44,7 +44,7 @@
          "findspace size:any radius:2",
          "walk coords",
          "animation planting 4000",
-         "plant tribe:blackrootfield_tiny",
+         "plant attrib:seed_blackroot",
          "animation planting 4000",
          "return"
       },

=== modified file 'data/tribes/workers/atlanteans/farmer/init.lua'
--- data/tribes/workers/atlanteans/farmer/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/atlanteans/farmer/init.lua	2017-11-18 14:09:59 +0000
@@ -44,7 +44,7 @@
          "findspace size:any radius:2",
          "walk coords",
          "animation planting 4000",
-         "plant tribe:cornfield_tiny",
+         "plant attrib:seed_corn",
          "animation planting 4000",
          "return"
       },

=== modified file 'data/tribes/workers/atlanteans/shipwright/init.lua'
--- data/tribes/workers/atlanteans/shipwright/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/atlanteans/shipwright/init.lua	2017-11-18 14:09:59 +0000
@@ -32,7 +32,7 @@
    programs = {
       buildship = {
          "walk object-or-coords",
-         "plant tribe:atlanteans_shipconstruction unless object",
+         "plant attrib:shipconstruction unless object",
          "play_sound sound/sawmill sawmill 230",
          "animation idle 500",
          "construct",

=== modified file 'data/tribes/workers/barbarians/farmer/init.lua'
--- data/tribes/workers/barbarians/farmer/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/barbarians/farmer/init.lua	2017-11-18 14:09:59 +0000
@@ -44,7 +44,7 @@
          "findspace size:any radius:2 space",
          "walk coords",
          "animation planting 4000",
-         "plant tribe:field_tiny",
+         "plant attrib:seed_wheat",
          "animation planting 4000",
          "return"
       },

=== modified file 'data/tribes/workers/barbarians/gardener/init.lua'
--- data/tribes/workers/barbarians/gardener/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/barbarians/gardener/init.lua	2017-11-18 14:09:59 +0000
@@ -39,7 +39,7 @@
          "findspace size:any radius:1",
          "walk coords",
          "animation planting 1500",
-         "plant tribe:reed_tiny",
+         "plant attrib:seed_reed",
          "animation planting 1500",
          "return"
       },

=== modified file 'data/tribes/workers/barbarians/shipwright/init.lua'
--- data/tribes/workers/barbarians/shipwright/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/barbarians/shipwright/init.lua	2017-11-18 14:09:59 +0000
@@ -36,7 +36,7 @@
    programs = {
       buildship = {
          "walk object-or-coords",
-         "plant tribe:barbarians_shipconstruction unless object",
+         "plant attrib:shipconstruction unless object",
          "play_sound sound/sawmill sawmill 230",
          "animation work 500",
          "construct",

=== modified file 'data/tribes/workers/empire/farmer/init.lua'
--- data/tribes/workers/empire/farmer/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/empire/farmer/init.lua	2017-11-18 14:09:59 +0000
@@ -44,7 +44,7 @@
          "findspace size:any radius:2 space",
          "walk coords",
          "animation planting 4000",
-         "plant tribe:field_tiny",
+         "plant attrib:seed_wheat",
          "animation planting 4000",
          "return",
       },

=== modified file 'data/tribes/workers/empire/shipwright/init.lua'
--- data/tribes/workers/empire/shipwright/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/empire/shipwright/init.lua	2017-11-18 14:09:59 +0000
@@ -36,7 +36,7 @@
    programs = {
       buildship = {
          "walk object-or-coords",
-         "plant tribe:empire_shipconstruction unless object",
+         "plant attrib:shipconstruction unless object",
          "play_sound sound/sawmill sawmill 230",
          "animation work 500",
          "construct",

=== modified file 'data/tribes/workers/empire/vinefarmer/init.lua'
--- data/tribes/workers/empire/vinefarmer/init.lua	2017-02-12 09:10:57 +0000
+++ data/tribes/workers/empire/vinefarmer/init.lua	2017-11-18 14:09:59 +0000
@@ -45,7 +45,7 @@
          "findspace size:any radius:1",
          "walk coords",
          "animation dig 2000",
-         "plant tribe:grapevine_tiny",
+         "plant attrib:seed_grapes",
          "animation planting 3000",
          "return"
       },

=== modified file 'src/economy/flag.h'
--- src/economy/flag.h	2017-04-23 12:11:19 +0000
+++ src/economy/flag.h	2017-11-18 14:09:59 +0000
@@ -37,7 +37,7 @@
 class FlagDescr : public MapObjectDescr {
 public:
 	FlagDescr(char const* const init_name, char const* const init_descname)
-	   : MapObjectDescr(MapObjectType::FLAG, init_name, init_descname) {
+	   : MapObjectDescr(MapObjectType::FLAG, init_name, init_descname, "") {
 	}
 	~FlagDescr() override {
 	}

=== modified file 'src/economy/fleet.h'
--- src/economy/fleet.h	2017-06-24 08:47:46 +0000
+++ src/economy/fleet.h	2017-11-18 14:09:59 +0000
@@ -37,7 +37,7 @@
 class FleetDescr : public MapObjectDescr {
 public:
 	FleetDescr(char const* const init_name, char const* const init_descname)
-	   : MapObjectDescr(MapObjectType::FLEET, init_name, init_descname) {
+	   : MapObjectDescr(MapObjectType::FLEET, init_name, init_descname, "") {
 	}
 	~FleetDescr() override {
 	}

=== modified file 'src/economy/portdock.cc'
--- src/economy/portdock.cc	2017-11-10 09:31:46 +0000
+++ src/economy/portdock.cc	2017-11-18 14:09:59 +0000
@@ -48,7 +48,7 @@
 }
 
 PortdockDescr::PortdockDescr(char const* const init_name, char const* const init_descname)
-   : MapObjectDescr(MapObjectType::PORTDOCK, init_name, init_descname) {
+   : MapObjectDescr(MapObjectType::PORTDOCK, init_name, init_descname, "") {
 }
 
 PortDock::PortDock(Warehouse* wh)

=== modified file 'src/economy/road.h'
--- src/economy/road.h	2017-04-23 12:11:19 +0000
+++ src/economy/road.h	2017-11-18 14:09:59 +0000
@@ -34,7 +34,7 @@
 class RoadDescr : public MapObjectDescr {
 public:
 	RoadDescr(char const* const init_name, char const* const init_descname)
-	   : MapObjectDescr(MapObjectType::ROAD, init_name, init_descname) {
+	   : MapObjectDescr(MapObjectType::ROAD, init_name, init_descname, "") {
 	}
 	~RoadDescr() override {
 	}

=== modified file 'src/logic/map_objects/immovable.cc'
--- src/logic/map_objects/immovable.cc	2017-11-10 09:31:46 +0000
+++ src/logic/map_objects/immovable.cc	2017-11-18 14:09:59 +0000
@@ -205,6 +205,9 @@
 	if (!is_animation_known("idle")) {
 		throw GameDataError("Immovable %s has no idle animation", table.get_string("name").c_str());
 	}
+	if (input_type == MapObjectDescr::OwnerType::kTribe && helptext_script().empty()) {
+		throw GameDataError("Tribe immovable %s has no helptext script", name().c_str());
+	}
 
 	if (table.has_key("size")) {
 		size_ = BaseImmovable::string_to_size(table.get_string("size"));

=== modified file 'src/logic/map_objects/map_object.cc'
--- src/logic/map_objects/map_object.cc	2017-11-13 08:03:31 +0000
+++ src/logic/map_objects/map_object.cc	2017-11-18 14:09:59 +0000
@@ -215,14 +215,17 @@
 */
 MapObjectDescr::MapObjectDescr(const MapObjectType init_type,
                                const std::string& init_name,
-                               const std::string& init_descname)
-   : type_(init_type), name_(init_name), descname_(init_descname) {
+                               const std::string& init_descname,
+										 const std::string& init_helptext_script)
+   : type_(init_type), name_(init_name), descname_(init_descname),
+	  helptext_script_(init_helptext_script) {
 }
 MapObjectDescr::MapObjectDescr(const MapObjectType init_type,
                                const std::string& init_name,
                                const std::string& init_descname,
                                const LuaTable& table)
-   : MapObjectDescr(init_type, init_name, init_descname) {
+   : MapObjectDescr(init_type, init_name, init_descname, table.has_key("helptext_script") ? table.get_string("helptext_script") : "")
+	   {
 	if (table.has_key("animations")) {
 		std::unique_ptr<LuaTable> anims(table.get_table("animations"));
 		for (const std::string& animation : anims->keys<std::string>()) {

=== modified file 'src/logic/map_objects/map_object.h'
--- src/logic/map_objects/map_object.h	2017-11-10 19:42:51 +0000
+++ src/logic/map_objects/map_object.h	2017-11-18 14:09:59 +0000
@@ -101,7 +101,7 @@
 
 	MapObjectDescr(const MapObjectType init_type,
 	               const std::string& init_name,
-	               const std::string& init_descname);
+	               const std::string& init_descname, const std::string& init_helptext_script);
 	MapObjectDescr(const MapObjectType init_type,
 	               const std::string& init_name,
 	               const std::string& init_descname,
@@ -115,6 +115,10 @@
 		return descname_;
 	}
 
+	const std::string& helptext_script() const {
+		return helptext_script_;
+	}
+
 	// Type of the MapObjectDescr.
 	MapObjectType type() const {
 		return type_;
@@ -176,6 +180,8 @@
 	const MapObjectType type_;    /// Subclasses pick from the enum above
 	std::string const name_;      /// The name for internal reference
 	std::string const descname_;  /// A localized Descriptive name
+	/// The path and filename to the helptext script. Can be empty, but some subtypes like buildings, wares and workers require it.
+	const std::string helptext_script_;
 	Attributes attributes_;
 	Anims anims_;
 	static uint32_t dyn_attribhigh_;  ///< highest attribute ID used

=== modified file 'src/logic/map_objects/tribes/battle.h'
--- src/logic/map_objects/tribes/battle.h	2017-05-20 19:26:55 +0000
+++ src/logic/map_objects/tribes/battle.h	2017-11-18 14:09:59 +0000
@@ -27,7 +27,7 @@
 class BattleDescr : public MapObjectDescr {
 public:
 	BattleDescr(char const* const init_name, char const* const init_descname)
-	   : MapObjectDescr(MapObjectType::BATTLE, init_name, init_descname) {
+	   : MapObjectDescr(MapObjectType::BATTLE, init_name, init_descname, "") {
 	}
 	~BattleDescr() override {
 	}

=== modified file 'src/logic/map_objects/tribes/building.cc'
--- src/logic/map_objects/tribes/building.cc	2017-08-19 22:22:20 +0000
+++ src/logic/map_objects/tribes/building.cc	2017-11-18 14:09:59 +0000
@@ -69,11 +69,14 @@
      enhanced_building_(false),
      hints_(table.get_table("aihints")),
      vision_range_(0) {
+	if (helptext_script().empty()) {
+		throw GameDataError("Building %s has no helptext script", name().c_str());
+	}
 	if (!is_animation_known("idle")) {
-		throw GameDataError("Building %s has no idle animation", table.get_string("name").c_str());
+		throw GameDataError("Building %s has no idle animation", name().c_str());
 	}
 	if (icon_filename().empty()) {
-		throw GameDataError("Building %s needs a menu icon", table.get_string("name").c_str());
+		throw GameDataError("Building %s needs a menu icon", name().c_str());
 	}
 
 	i18n::Textdomain td("tribes");
@@ -155,8 +158,6 @@
 		}
 	}
 
-	helptext_script_ = table.get_string("helptext_script");
-
 	needs_seafaring_ = table.has_key("needs_seafaring") ? table.get_bool("needs_seafaring") : false;
 
 	if (table.has_key("vision_range")) {

=== modified file 'src/logic/map_objects/tribes/building.h'
--- src/logic/map_objects/tribes/building.h	2017-09-10 18:17:55 +0000
+++ src/logic/map_objects/tribes/building.h	2017-11-18 14:09:59 +0000
@@ -108,9 +108,6 @@
 		return return_enhanced_;
 	}
 
-	std::string helptext_script() const {
-		return helptext_script_;
-	}
 	int32_t get_size() const {
 		return size_;
 	}
@@ -179,7 +176,6 @@
 	Buildcost return_dismantle_;   // Returned wares on dismantle
 	Buildcost enhance_cost_;       // cost for enhancing
 	Buildcost return_enhanced_;    // Returned ware for dismantling an enhanced building
-	std::string helptext_script_;  // The path and filename to the building's helptext script
 	int32_t size_;                 // size of the building
 	bool mine_;
 	bool port_;

=== modified file 'src/logic/map_objects/tribes/tribe_descr.cc'
--- src/logic/map_objects/tribes/tribe_descr.cc	2017-07-19 20:40:32 +0000
+++ src/logic/map_objects/tribes/tribe_descr.cc	2017-11-18 14:09:59 +0000
@@ -178,9 +178,9 @@
 				}
 
 				// Register construction materials
-				for (const auto& build_cost : get_building_descr(index)->buildcost()) {
-					if (!is_construction_material(build_cost.first)) {
-						construction_materials_.insert(build_cost.first);
+				for (const auto& buildcost : get_building_descr(index)->buildcost()) {
+					if (!is_construction_material(buildcost.first)) {
+						construction_materials_.insert(buildcost.first);
 					}
 				}
 				for (const auto& enhancement_cost : get_building_descr(index)->enhancement_cost()) {
@@ -282,6 +282,9 @@
 const std::set<DescriptionIndex>& TribeDescr::workers() const {
 	return workers_;
 }
+const std::set<DescriptionIndex>& TribeDescr::immovables() const {
+	return immovables_;
+}
 
 bool TribeDescr::has_building(const DescriptionIndex& index) const {
 	return std::find(buildings_.begin(), buildings_.end(), index) != buildings_.end();

=== modified file 'src/logic/map_objects/tribes/tribe_descr.h'
--- src/logic/map_objects/tribes/tribe_descr.h	2017-07-19 20:40:32 +0000
+++ src/logic/map_objects/tribes/tribe_descr.h	2017-11-18 14:09:59 +0000
@@ -69,6 +69,7 @@
 	const std::vector<DescriptionIndex>& buildings() const;
 	const std::set<DescriptionIndex>& wares() const;
 	const std::set<DescriptionIndex>& workers() const;
+	const std::set<DescriptionIndex>& immovables() const;
 
 	bool has_building(const DescriptionIndex& index) const;
 	bool has_ware(const DescriptionIndex& index) const;

=== modified file 'src/logic/map_objects/tribes/ware_descr.cc'
--- src/logic/map_objects/tribes/ware_descr.cc	2017-01-25 18:55:59 +0000
+++ src/logic/map_objects/tribes/ware_descr.cc	2017-11-18 14:09:59 +0000
@@ -37,17 +37,17 @@
  */
 WareDescr::WareDescr(const std::string& init_descname, const LuaTable& table)
    : MapObjectDescr(MapObjectType::WARE, table.get_string("name"), init_descname, table) {
-
+	if (helptext_script().empty()) {
+		throw GameDataError("Ware %s has no helptext script", name().c_str());
+	}
 	if (!is_animation_known("idle")) {
-		throw GameDataError("Ware %s has no idle animation", table.get_string("name").c_str());
+		throw GameDataError("Ware %s has no idle animation", name().c_str());
 	}
 	if (icon_filename().empty()) {
-		throw GameDataError("Ware %s has no menu icon", table.get_string("name").c_str());
+		throw GameDataError("Ware %s has no menu icon", name().c_str());
 	}
 	i18n::Textdomain td("tribes");
 
-	helptext_script_ = table.get_string("helptext_script");
-
 	std::unique_ptr<LuaTable> items_table = table.get_table("default_target_quantity");
 	for (const std::string& key : items_table->keys<std::string>()) {
 		default_target_quantities_.emplace(key, items_table->get_int(key));

=== modified file 'src/logic/map_objects/tribes/ware_descr.h'
--- src/logic/map_objects/tribes/ware_descr.h	2017-01-25 18:55:59 +0000
+++ src/logic/map_objects/tribes/ware_descr.h	2017-11-18 14:09:59 +0000
@@ -62,10 +62,6 @@
 	///  and should not be configurable.
 	DescriptionIndex default_target_quantity(const std::string& tribename) const;
 
-	std::string helptext_script() const {
-		return helptext_script_;
-	}
-
 	bool has_demand_check(const std::string& tribename) const;
 
 	/// Called when a demand check for this ware type is encountered during
@@ -91,8 +87,6 @@
 
 	std::set<DescriptionIndex> consumers_;  // Buildings that consume this ware
 	std::set<DescriptionIndex> producers_;  // Buildings that produce this ware
-
-	std::string helptext_script_;  // The path and filename to the ware's helptext script
 	DISALLOW_COPY_AND_ASSIGN(WareDescr);
 };
 }

=== modified file 'src/logic/map_objects/tribes/worker.cc'
--- src/logic/map_objects/tribes/worker.cc	2017-11-12 08:59:45 +0000
+++ src/logic/map_objects/tribes/worker.cc	2017-11-18 14:09:59 +0000
@@ -726,54 +726,46 @@
 	// affinity). We will pick one of them at random later. The container is
 	// picked to be a stable sorting one, so that no deyncs happen in
 	// multiplayer.
-	std::set<std::tuple<double, DescriptionIndex>> best_suited_immovables_index;
+	std::set<std::tuple<double, DescriptionIndex, MapObjectDescr::OwnerType>> best_suited_immovables_index;
 
 	// Checks if the 'immovable_description' has a terrain_affinity, if so use it. Otherwise assume
-	// it
-	// to be 1. (perfect fit). Adds it to the best_suited_immovables_index.
+	// it to be 1 (perfect fit). Adds it to the best_suited_immovables_index.
 	const auto test_suitability = [&best_suited_immovables_index, &fpos, &map, &game](
-	   const DescriptionIndex index, const ImmovableDescr& immovable_description) {
+	   const uint32_t attribute_id, const DescriptionIndex index, const ImmovableDescr& immovable_description, MapObjectDescr::OwnerType owner_type) {
+		if (!immovable_description.has_attribute(attribute_id)) {
+			return;
+		}
 		double p = 1.;
 		if (immovable_description.has_terrain_affinity()) {
 			p = probability_to_grow(
 			   immovable_description.terrain_affinity(), fpos, map, game.world().terrains());
 		}
-		best_suited_immovables_index.insert(std::make_tuple(p, index));
+		best_suited_immovables_index.insert(std::make_tuple(p, index, owner_type));
 		if (best_suited_immovables_index.size() > 6) {
 			best_suited_immovables_index.erase(best_suited_immovables_index.begin());
 		}
 	};
 
-	if (action.sparamv.size() != 1) {
-		throw GameDataError("plant takes only one argument.");
-	}
-
-	std::vector<std::string> const list(split_string(action.sparamv[0], ":"));
-
-	if (list.size() != 2) {
-		throw GameDataError("plant takes either tribe:<immovable> or attrib:<attribute>");
-	}
-
-	if (list[0] == "attrib") {
-		state.svar1 = "world";
-
-		const DescriptionMaintainer<ImmovableDescr>& immovables = game.world().immovables();
-
-		const uint32_t attribute_id = ImmovableDescr::get_attribute_id(list[1]);
-		for (uint32_t i = 0; i < immovables.size(); ++i) {
-			const ImmovableDescr& immovable_descr = immovables.get(i);
-			if (!immovable_descr.has_attribute(attribute_id)) {
-				continue;
-			}
-			test_suitability(i, immovable_descr);
-		}
-	} else {
-		state.svar1 = "tribe";
-		DescriptionIndex immovable_index = game.tribes().immovable_index(list[1]);
-
-		if (game.tribes().immovable_exists(immovable_index)) {
-			const ImmovableDescr* imm = game.tribes().get_immovable_descr(immovable_index);
-			test_suitability(immovable_index, *imm);
+	if (action.sparamv.empty()) {
+		throw GameDataError("plant needs at least one attrib:<attribute>.");
+	}
+
+	// Collect all world and tribe immovable types for all the attributes along with a suitability metric
+	for (const std::string& attrib : action.sparamv) {
+		if (attrib.empty()) {
+			throw GameDataError("plant has an empty attrib:<attribute>");
+		}
+		const uint32_t attribute_id = ImmovableDescr::get_attribute_id(attrib);
+
+		// Add world immovables
+		const DescriptionMaintainer<ImmovableDescr>& world_immovables = game.world().immovables();
+		for (uint32_t i = 0; i < world_immovables.size(); ++i) {
+			test_suitability(attribute_id, i, world_immovables.get(i), MapObjectDescr::OwnerType::kWorld);
+		}
+
+		// Add tribe immovables
+		for (const DescriptionIndex i : owner().tribe().immovables()) {
+			test_suitability(attribute_id, i, *owner().tribe().get_immovable_descr(i), MapObjectDescr::OwnerType::kTribe);
 		}
 	}
 
@@ -794,10 +786,10 @@
 	}
 
 	double choice = logic_rand_as_double(&game) * total_weight;
-
 	for (const auto& bsii : best_suited_immovables_index) {
 		double weight = std::get<0>(bsii);
 		state.ivar2 = std::get<1>(bsii);
+		state.ivar3 = static_cast<int>(std::get<2>(bsii));
 		choice -= weight * weight;
 		if (0 > choice) {
 			break;
@@ -805,12 +797,11 @@
 	}
 
 	Immovable& newimm = game.create_immovable(
-	   pos, state.ivar2, state.svar1 == "tribe" ? MapObjectDescr::OwnerType::kTribe :
-	                                              MapObjectDescr::OwnerType::kWorld,
-	   get_owner());
+	   pos, state.ivar2, static_cast<Widelands::MapObjectDescr::OwnerType>(state.ivar3), get_owner());
 
-	if (action.iparam1 == Action::plantUnlessObject)
+	if (action.iparam1 == Action::plantUnlessObject) {
 		state.objvar1 = &newimm;
+	}
 
 	++state.ivar1;
 	schedule_act(game, 10);

=== modified file 'src/logic/map_objects/tribes/worker_descr.cc'
--- src/logic/map_objects/tribes/worker_descr.cc	2017-11-10 09:31:46 +0000
+++ src/logic/map_objects/tribes/worker_descr.cc	2017-11-18 14:09:59 +0000
@@ -44,8 +44,11 @@
      needed_experience_(INVALID_INDEX),
      becomes_(INVALID_INDEX),
      egbase_(egbase) {
+	if (helptext_script().empty()) {
+		throw GameDataError("Worker %s has no helptext script", name().c_str());
+	}
 	if (icon_filename().empty()) {
-		throw GameDataError("Worker %s has no menu icon", table.get_string("name").c_str());
+		throw GameDataError("Worker %s has no menu icon", name().c_str());
 	}
 	i18n::Textdomain td("tribes");
 	std::unique_ptr<LuaTable> items_table;
@@ -77,8 +80,6 @@
 		}
 	}
 
-	helptext_script_ = table.get_string("helptext_script");
-
 	// Read the walking animations
 	add_directional_animation(&walk_anims_, "walk");
 

=== modified file 'src/logic/map_objects/tribes/worker_descr.h'
--- src/logic/map_objects/tribes/worker_descr.h	2017-02-20 14:15:07 +0000
+++ src/logic/map_objects/tribes/worker_descr.h	2017-11-18 14:09:59 +0000
@@ -82,10 +82,6 @@
 			default_target_quantity_ = 1;
 	}
 
-	std::string helptext_script() const {
-		return helptext_script_;
-	}
-
 	const DirAnimations& get_walk_anims() const {
 		return walk_anims_;
 	}
@@ -121,7 +117,6 @@
 
 protected:
 	Quantity default_target_quantity_;
-	std::string helptext_script_;  // The path and filename to the worker's helptext script
 	DirAnimations walk_anims_;
 	DirAnimations walkload_anims_;
 	bool buildable_;

=== modified file 'src/logic/map_objects/tribes/worker_program.cc'
--- src/logic/map_objects/tribes/worker_program.cc	2017-08-30 11:58:41 +0000
+++ src/logic/map_objects/tribes/worker_program.cc	2017-11-18 14:09:59 +0000
@@ -412,7 +412,7 @@
          "findspace size:any radius:2 space", -- The farmer will want to walk to this field again later for harvesting his crop
          "walk coords",
          "animation planting 4000",
-         "plant tribe:field_tiny",
+         "plant attrib:seed_wheat",
          "animation planting 4000",
          "return",
       },
@@ -505,7 +505,7 @@
          "findspace size:any radius:2",
          "walk coords", -- Walk to the space found by the command above
          "animation planting 4000",
-         "plant tribe:blackrootfield_tiny",
+         "plant attrib:seed_blackroot",
          "animation planting 4000",
          "return"
       },
@@ -522,7 +522,7 @@
 
       buildship = {
          "walk object-or-coords", -- Walk to coordinates from 1. or to object from 2.
-         "plant tribe:barbarians_shipconstruction unless object", -- 2. This will create an object for us if we don't have one yet
+         "plant attrib:shipconstruction unless object", -- 2. This will create an object for us if we don't have one yet
          "play_sound sound/sawmill sawmill 230",
          "animation work 500",
          "construct", -- 1. This will find a space for us if no object has been planted yet
@@ -563,7 +563,7 @@
          "findspace size:any radius:1",
          "walk coords",
          "animation dig 2000", -- Play a digging animation for 2 seconds.
-         "plant tribe:grapevine_tiny",
+         "plant attrib:seed_grapes",
          "animation planting 3000", -- Play a planting animation for 3 seconds.
          "return"
       },
@@ -649,13 +649,10 @@
 /* RST
 plant
 ^^^^^
-.. function:: plant \<immmovable_type\> [\<immovable_type\> ...] [unless object]
-
-   :arg string immovable_type: The immovable to be planted. This can be specified
-      in two different ways:
-
-      * ``attrib:<attribute>``: Select at random any immovable that has this attribute.
-      * ``tribe:<immovable_name>``: Name a specific immovable to be planted.
+.. function:: plant attrib:\<attribute\> [attrib:\<attribute\> ...] [unless object]
+
+   :arg string attrib\:\<attribute\>: Select at random any world immovable or immovable
+      of the worker's tribe that has this attribute.
 
    :arg empty unless object: Do not plant the immovable if it already exists at
       the current position.
@@ -677,14 +674,14 @@
          "findspace size:any radius:2 space",
          "walk coords",
          "animation planting 4000",
-         "plant tribe:field_tiny", -- Plant the tiny field immovable that the worker's tribe knows about
+         "plant attrib:seed_wheat", -- Plant a random wheat field immovable that the worker's tribe knows about
          "animation planting 4000",
          "return",
       },
 
       buildship = {
          "walk object-or-coords",
-         "plant tribe:empire_shipconstruction unless object", -- Only create a shipconstruction if we don't already have one
+         "plant attrib:shipconstruction unless object", -- Only create a shipconstruction if we don't already have one
          "play_sound sound/sawmill sawmill 230",
          "animation work 500",
          "construct",
@@ -693,12 +690,12 @@
       }
 */
 /**
- * sparamv  list of object names
+ * sparamv  list of attributes
  * iparam1  one of plantXXX
  */
 void WorkerProgram::parse_plant(Worker::Action* act, const std::vector<std::string>& cmd) {
 	if (cmd.size() < 2)
-		throw wexception("Usage: plant <immovable type> <immovable type> ... [unless object]");
+		throw wexception("Usage: plant plant attrib:<attribute> [attrib:<attribute> ...] [unless object]");
 
 	act->function = &Worker::run_plant;
 	act->iparam1 = Worker::Action::plantAlways;
@@ -717,21 +714,18 @@
 
 		// Check if immovable type exists
 		std::vector<std::string> const list(split_string(cmd[i], ":"));
-		if (list.size() != 2) {
-			throw GameDataError("plant takes either tribe:<immovable> or attrib:<attribute>");
-		}
-
-		if (list[0] == "attrib") {
-			// This will throw a GameDataError if the attribute doesn't exist.
-			ImmovableDescr::get_attribute_id(list[1]);
-		} else {
-			DescriptionIndex idx = tribes_.safe_immovable_index(list[1]);
-			if (!tribes_.immovable_exists(idx)) {
-				throw GameDataError(
-				   "There is no tribe immovable %s for workers to plant.", list[1].c_str());
-			}
-		}
-		act->sparamv.push_back(cmd[i]);
+		if (list.size() != 2 || list.at(0) != "attrib") {
+			throw GameDataError("plant takes a list of attrib:<attribute> that reference world and/or tribe immovables");
+		}
+
+		const std::string& attrib_name = list[1];
+		if (attrib_name.empty()) {
+		   throw GameDataError("plant has an empty attrib:<attribute> at position %d", i);
+		}
+
+		// This will throw a GameDataError if the attribute doesn't exist.
+		ImmovableDescr::get_attribute_id(attrib_name);
+		act->sparamv.push_back(attrib_name);
 	}
 }
 
@@ -919,7 +913,7 @@
 
       buildship = {
          "walk object-or-coords", -- Walk to coordinates from 1. or to object from 2.
-         "plant tribe:barbarians_shipconstruction unless object", -- 2. This will create an object for us if we don't have one yet
+         "plant attrib:shipconstruction unless object", -- 2. This will create an object for us if we don't have one yet
          "play_sound sound/sawmill sawmill 230",
          "animation work 500",
          "construct", -- 1. Add the current ware to the shipconstruction. This will find a space for us if no shipconstruction object has been planted yet

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2017-11-10 09:31:46 +0000
+++ src/scripting/lua_map.cc	2017-11-18 14:09:59 +0000
@@ -1325,6 +1325,7 @@
    PROP_RO(LuaTribeDescription, descname),
    PROP_RO(LuaTribeDescription, geologist),
    PROP_RO(LuaTribeDescription, headquarters),
+	PROP_RO(LuaTribeDescription, immovables),
    PROP_RO(LuaTribeDescription, name),
    PROP_RO(LuaTribeDescription, port),
    PROP_RO(LuaTribeDescription, ship),
@@ -1428,6 +1429,23 @@
 }
 
 /* RST
+   .. attribute:: immovables
+
+      (RO) an array of :class:`LuaImmovableDescription` with all the immovables that the tribe can use.
+*/
+int LuaTribeDescription::get_immovables(lua_State* L) {
+	const TribeDescr& tribe = *get();
+	lua_newtable(L);
+	int counter = 0;
+	for (DescriptionIndex immovable : tribe.immovables()) {
+		lua_pushinteger(L, ++counter);
+		to_lua<LuaImmovableDescription>(L, new LuaImmovableDescription(tribe.get_immovable_descr(immovable)));
+		lua_settable(L, -3);
+	}
+	return 1;
+}
+
+/* RST
    .. attribute:: name
 
          (RO) a :class:`string` with the tribe's internal name
@@ -1571,6 +1589,7 @@
 };
 const PropertyType<LuaMapObjectDescription> LuaMapObjectDescription::Properties[] = {
    PROP_RO(LuaMapObjectDescription, descname),
+	PROP_RO(LuaMapObjectDescription, helptext_script),
    PROP_RO(LuaMapObjectDescription, icon_name),
    PROP_RO(LuaMapObjectDescription, name),
    PROP_RO(LuaMapObjectDescription, type_name),
@@ -1605,6 +1624,16 @@
 }
 
 /* RST
+   .. attribute:: helptext_script
+
+         (RO) The path and filename to the helptext script. Can be empty.
+*/
+int LuaMapObjectDescription::get_helptext_script(lua_State* L) {
+	lua_pushstring(L, get()->helptext_script());
+	return 1;
+}
+
+/* RST
    .. attribute:: icon_name
 
          (RO) the filename for the menu icon.
@@ -1737,7 +1766,7 @@
 };
 const PropertyType<LuaImmovableDescription> LuaImmovableDescription::Properties[] = {
    PROP_RO(LuaImmovableDescription, species),
-   PROP_RO(LuaImmovableDescription, build_cost),
+   PROP_RO(LuaImmovableDescription, buildcost),
    PROP_RO(LuaImmovableDescription, editor_category),
    PROP_RO(LuaImmovableDescription, terrain_affinity),
    PROP_RO(LuaImmovableDescription, owner_type),
@@ -1774,12 +1803,12 @@
 }
 
 /* RST
-   .. attribute:: build_cost
+   .. attribute:: buildcost
 
          (RO) a table of ware-to-count pairs, describing the build cost for the
          immovable.
 */
-int LuaImmovableDescription::get_build_cost(lua_State* L) {
+int LuaImmovableDescription::get_buildcost(lua_State* L) {
 	return wares_or_workers_map_to_lua(L, get()->buildcost(), MapObjectType::WARE);
 }
 
@@ -1944,11 +1973,10 @@
    {nullptr, nullptr},
 };
 const PropertyType<LuaBuildingDescription> LuaBuildingDescription::Properties[] = {
-   PROP_RO(LuaBuildingDescription, build_cost),
+   PROP_RO(LuaBuildingDescription, buildcost),
    PROP_RO(LuaBuildingDescription, buildable),
    PROP_RO(LuaBuildingDescription, conquers),
    PROP_RO(LuaBuildingDescription, destructible),
-   PROP_RO(LuaBuildingDescription, helptext_script),
    PROP_RO(LuaBuildingDescription, enhanced),
    PROP_RO(LuaBuildingDescription, enhanced_from),
    PROP_RO(LuaBuildingDescription, enhancement_cost),
@@ -1983,11 +2011,11 @@
  */
 
 /* RST
-   .. attribute:: build_cost
+   .. attribute:: buildcost
 
          (RO) a list of ware build cost for the building.
 */
-int LuaBuildingDescription::get_build_cost(lua_State* L) {
+int LuaBuildingDescription::get_buildcost(lua_State* L) {
 	return wares_or_workers_map_to_lua(L, get()->buildcost(), MapObjectType::WARE);
 }
 
@@ -2021,15 +2049,6 @@
 	return 1;
 }
 
-/* RST
-   .. attribute:: helptext_script
-
-         (RO) The path and filename to the building's helptext script
-*/
-int LuaBuildingDescription::get_helptext_script(lua_State* L) {
-	lua_pushstring(L, get()->helptext_script());
-	return 1;
-}
 
 /* RST
    .. attribute:: enhanced
@@ -2813,7 +2832,6 @@
 };
 const PropertyType<LuaWareDescription> LuaWareDescription::Properties[] = {
    PROP_RO(LuaWareDescription, consumers),
-   PROP_RO(LuaWareDescription, helptext_script),
    PROP_RO(LuaWareDescription, producers),
    {nullptr, nullptr, nullptr},
 };
@@ -2856,16 +2874,6 @@
 }
 
 /* RST
-   .. attribute:: helptext_script
-
-         (RO) The path and filename to the ware's helptext script
-*/
-int LuaWareDescription::get_helptext_script(lua_State* L) {
-	lua_pushstring(L, get()->helptext_script());
-	return 1;
-}
-
-/* RST
    .. method:: is_construction_material
 
       :arg tribename: the name of the tribe that this ware gets checked for
@@ -2924,7 +2932,6 @@
    PROP_RO(LuaWorkerDescription, becomes),
    PROP_RO(LuaWorkerDescription, buildcost),
    PROP_RO(LuaWorkerDescription, employers),
-   PROP_RO(LuaWorkerDescription, helptext_script),
    PROP_RO(LuaWorkerDescription, is_buildable),
    PROP_RO(LuaWorkerDescription, needed_experience),
    {nullptr, nullptr, nullptr},
@@ -3001,15 +3008,6 @@
 	return 1;
 }
 
-/* RST
-   .. attribute:: helptext_script
-
-         (RO) The path and filename to the worker's helptext script
-*/
-int LuaWorkerDescription::get_helptext_script(lua_State* L) {
-	lua_pushstring(L, get()->helptext_script());
-	return 1;
-}
 
 /* RST
    .. attribute:: is_buildable

=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h	2017-09-22 19:54:27 +0000
+++ src/scripting/lua_map.h	2017-11-18 14:09:59 +0000
@@ -130,6 +130,7 @@
 	int get_carrier2(lua_State*);
 	int get_descname(lua_State*);
 	int get_headquarters(lua_State*);
+	int get_immovables(lua_State*);
 	int get_geologist(lua_State*);
 	int get_name(lua_State*);
 	int get_port(lua_State*);
@@ -186,6 +187,7 @@
 	 */
 	int get_descname(lua_State*);
 	int get_icon_name(lua_State*);
+	int get_helptext_script(lua_State*);
 	int get_name(lua_State*);
 	int get_type_name(lua_State*);
 	int get_representative_image(lua_State*);
@@ -238,7 +240,7 @@
 	 * Properties
 	 */
 	int get_species(lua_State*);
-	int get_build_cost(lua_State*);
+	int get_buildcost(lua_State*);
 	int get_editor_category(lua_State*);
 	int get_terrain_affinity(lua_State*);
 	int get_owner_type(lua_State*);
@@ -279,11 +281,10 @@
 	/*
 	 * Properties
 	 */
-	int get_build_cost(lua_State*);
+	int get_buildcost(lua_State*);
 	int get_buildable(lua_State*);
 	int get_conquers(lua_State*);
 	int get_destructible(lua_State*);
-	int get_helptext_script(lua_State*);
 	int get_enhanced(lua_State*);
 	int get_enhanced_from(lua_State*);
 	int get_enhancement_cost(lua_State*);
@@ -556,7 +557,6 @@
 	 * Properties
 	 */
 	int get_consumers(lua_State*);
-	int get_helptext_script(lua_State*);
 	int get_producers(lua_State*);
 
 	/*
@@ -596,7 +596,6 @@
 	int get_becomes(lua_State*);
 	int get_buildcost(lua_State*);
 	int get_employers(lua_State*);
-	int get_helptext_script(lua_State*);
 	int get_is_buildable(lua_State*);
 	int get_needed_experience(lua_State*);
 

=== modified file 'test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua'
--- test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua	2016-07-10 19:03:33 +0000
+++ test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua	2017-11-18 14:09:59 +0000
@@ -35,13 +35,13 @@
    assert_equal("Alder", egbase:get_immovable_description("alder_summer_old").species)
 end
 
-function test_descr:test_immovable_build_cost()
-   local build_cost = egbase:get_immovable_description(
-      "atlanteans_shipconstruction").build_cost
-   assert_equal(10, build_cost["planks"])
-   assert_equal(2, build_cost["log"])
-   assert_equal(4, build_cost["spidercloth"])
-   assert_equal(nil, build_cost["wine"])
+function test_descr:test_immovable_buildcost()
+   local buildcost = egbase:get_immovable_description(
+      "atlanteans_shipconstruction").buildcost
+   assert_equal(10, buildcost["planks"])
+   assert_equal(2, buildcost["log"])
+   assert_equal(4, buildcost["spidercloth"])
+   assert_equal(nil, buildcost["wine"])
 
    local total_cost = function(t)
       local cost = 0
@@ -50,7 +50,7 @@
       end
       return cost
    end
-   assert_equal(16, total_cost(build_cost))
+   assert_equal(16, total_cost(buildcost))
 end
 
 function test_descr:test_immovable_editor_category()
@@ -164,7 +164,7 @@
    assert_equal("barbarians_coalmine", egbase:get_building_description("barbarians_coalmine").name)
 end
 
-function test_descr:test_build_cost()
+function test_descr:test_buildcost()
    local total_cost = function(t)
       local cost = 0
       for name, count in pairs(t) do
@@ -172,9 +172,9 @@
       end
       return cost
    end
-   assert_equal(2, total_cost(egbase:get_building_description("barbarians_sentry").build_cost))
-   assert_equal(20, total_cost(egbase:get_building_description("barbarians_fortress").build_cost))
-   assert_equal(0, total_cost(egbase:get_building_description("barbarians_citadel").build_cost))
+   assert_equal(2, total_cost(egbase:get_building_description("barbarians_sentry").buildcost))
+   assert_equal(20, total_cost(egbase:get_building_description("barbarians_fortress").buildcost))
+   assert_equal(0, total_cost(egbase:get_building_description("barbarians_citadel").buildcost))
 end
 
 function test_descr:test_buildable()


Follow ups