← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/empire-mission-3 into lp:widelands

 

hessenfarmer has proposed merging lp:~widelands-dev/widelands/empire-mission-3 into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/empire-mission-3/+merge/321434

branch not fully tested. 
merge request donr to get an appveyor build
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/empire-mission-3 into lp:widelands.
=== modified file 'data/campaigns/campaigns.conf'
--- data/campaigns/campaigns.conf	2015-02-27 09:38:51 +0000
+++ data/campaigns/campaigns.conf	2017-03-30 10:06:26 +0000
@@ -85,6 +85,11 @@
 path="campaigns/emp02.wmf"
 
 [empiretut02]
+name=_"Neptune's Revenge"
+visible=0
+path="campaigns/emp03.wmf"
+
+[empiretut03]
 name=_"Not yet implemented"
 newvisi="campsect2"
 visible=0

=== modified file 'data/campaigns/emp02.wmf/scripting/mission_thread.lua'
--- data/campaigns/emp02.wmf/scripting/mission_thread.lua	2017-01-17 08:52:14 +0000
+++ data/campaigns/emp02.wmf/scripting/mission_thread.lua	2017-03-30 10:06:26 +0000
@@ -261,7 +261,6 @@
    campaign_message_box(seven_days_later)
    campaign_message_box(diary_page_11)
 
-   p1:reveal_campaign("campsect2")
    p1:reveal_scenario("empiretut02")
 end
 

=== added directory 'data/campaigns/emp03.wmf'
=== added directory 'data/campaigns/emp03.wmf/binary'
=== added file 'data/campaigns/emp03.wmf/binary/heights'
Binary files data/campaigns/emp03.wmf/binary/heights	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/binary/heights	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/binary/mapobjects'
Binary files data/campaigns/emp03.wmf/binary/mapobjects	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/binary/mapobjects	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/binary/resource'
Binary files data/campaigns/emp03.wmf/binary/resource	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/binary/resource	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/binary/terrain'
Binary files data/campaigns/emp03.wmf/binary/terrain	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/binary/terrain	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/elemental'
--- data/campaigns/emp03.wmf/elemental	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/elemental	2017-03-30 10:06:26 +0000
@@ -0,0 +1,13 @@
+# Automatically created by Widelands bzr8330[empire-mission-3] (Debug)
+
+[global]
+packet_version="1"
+map_w="112"
+map_h="96"
+nr_players="2"
+name="Neptune's Revenge"
+author="hessenfarmer"
+descr="On their way home to defend the empire the crew of Lutius was surprised by the will of the gods. "
+hint=
+background="pics/background.jpg"
+tags="artifacts,seafaring,unbalanced"

=== added file 'data/campaigns/emp03.wmf/minimap.png'
Binary files data/campaigns/emp03.wmf/minimap.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/minimap.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/objective'
--- data/campaigns/emp03.wmf/objective	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/objective	2017-03-30 10:06:26 +0000
@@ -0,0 +1,4 @@
+# Automatically created by Widelands bzr8330[empire-mission-3] (Debug)
+
+[global]
+packet_version="2"

=== added directory 'data/campaigns/emp03.wmf/pics'
=== added file 'data/campaigns/emp03.wmf/pics/Amalea.png'
Binary files data/campaigns/emp03.wmf/pics/Amalea.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/Amalea.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/pics/Amalea2.png'
Binary files data/campaigns/emp03.wmf/pics/Amalea2.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/Amalea2.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/pics/Amalea3.png'
Binary files data/campaigns/emp03.wmf/pics/Amalea3.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/Amalea3.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/pics/Lutius.png'
Binary files data/campaigns/emp03.wmf/pics/Lutius.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/Lutius.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/pics/Saledus.png'
Binary files data/campaigns/emp03.wmf/pics/Saledus.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/Saledus.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/pics/Saledus2.png'
Binary files data/campaigns/emp03.wmf/pics/Saledus2.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/Saledus2.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/pics/Saledus3.png'
Binary files data/campaigns/emp03.wmf/pics/Saledus3.png	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/Saledus3.png	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/pics/background.jpg'
Binary files data/campaigns/emp03.wmf/pics/background.jpg	1970-01-01 00:00:00 +0000 and data/campaigns/emp03.wmf/pics/background.jpg	2017-03-30 10:06:26 +0000 differ
=== added file 'data/campaigns/emp03.wmf/player_names'
--- data/campaigns/emp03.wmf/player_names	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/player_names	2017-03-30 10:06:26 +0000
@@ -0,0 +1,16 @@
+# Automatically created by Widelands bzr8330[empire-mission-3] (Debug)
+
+[global]
+packet_version="2"
+
+[player_1]
+name="Lutius"
+tribe="empire"
+ai=
+closeable="false"
+
+[player_2]
+name="Baraso"
+tribe="barbarians"
+ai=
+closeable="false"

=== added file 'data/campaigns/emp03.wmf/player_position'
--- data/campaigns/emp03.wmf/player_position	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/player_position	2017-03-30 10:06:26 +0000
@@ -0,0 +1,6 @@
+# Automatically created by Widelands bzr8330[empire-mission-3] (Debug)
+
+[global]
+packet_version="2"
+player_1="4 6"
+player_2="34 74"

=== added file 'data/campaigns/emp03.wmf/port_spaces'
--- data/campaigns/emp03.wmf/port_spaces	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/port_spaces	2017-03-30 10:06:26 +0000
@@ -0,0 +1,13 @@
+# Automatically created by Widelands bzr8330[empire-mission-3] (Debug)
+
+[global]
+packet_version="1"
+number_of_port_spaces="6"
+
+[port_spaces]
+0="105 1"
+1="17 17"
+2="47 18"
+3="93 26"
+4="5 34"
+5="37 77"

=== added directory 'data/campaigns/emp03.wmf/scripting'
=== added file 'data/campaigns/emp03.wmf/scripting/helper_functions.lua'
--- data/campaigns/emp03.wmf/scripting/helper_functions.lua	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/scripting/helper_functions.lua	2017-03-30 10:06:26 +0000
@@ -0,0 +1,25 @@
+-- Helper functions for campaign emp03
+
+function count_buildings(plr, tbl)
+   -- return overall amount of buildings:
+   -- plr : Player to count for
+   -- tbl : Table in form of {"building_name1", "building_name2", ...}
+   local amount = 0
+   for idx, bldng in ipairs(tbl) do
+      amount = amount + #plr:get_buildings(bldng)
+   end
+   return amount
+end
+
+function count_in_warehouses(ware)
+   local whs = array_combine(
+      p1:get_buildings("empire_headquarters_shipwreck"),
+      p1:get_buildings("empire_warehouse"),
+      p1:get_buildings("empire_port")
+   )
+   local rv = 0
+   for idx,wh in ipairs(whs) do
+      rv = rv + wh:get_wares(ware)
+   end
+   return rv
+end

=== added file 'data/campaigns/emp03.wmf/scripting/init.lua'
--- data/campaigns/emp03.wmf/scripting/init.lua	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/scripting/init.lua	2017-03-30 10:06:26 +0000
@@ -0,0 +1,23 @@
+-- =======================================================================
+--                         Empire Campaign Mission 3
+-- =======================================================================
+set_textdomain("scenario_emp03.wmf")
+
+include "scripting/coroutine.lua"
+include "scripting/objective_utils.lua"
+include "scripting/infrastructure.lua"
+include "scripting/table.lua"
+include "scripting/ui.lua"
+
+
+p1 = wl.Game().players[1]
+p2 = wl.Game().players[2]
+
+include "map:scripting/texts.lua"
+include "map:scripting/mission_thread.lua"
+
+map = wl.Game().map
+mv = wl.ui.MapView()
+sf = map.player_slots[1].starting_field
+
+

=== added file 'data/campaigns/emp03.wmf/scripting/mission_thread.lua'
--- data/campaigns/emp03.wmf/scripting/mission_thread.lua	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/scripting/mission_thread.lua	2017-03-30 10:06:26 +0000
@@ -0,0 +1,450 @@
+include "scripting/messages.lua"
+include "map:scripting/helper_functions.lua"
+
+function check_stonemason()  -- check for completed stonemason
+   while #p1:get_buildings("empire_stonemasons_house") < 1 do sleep(3000) end
+   campaign_message_box(amalea_3)
+
+   -- don't use all your marble for columns
+   o3 = add_campaign_objective(obj_lower_marble_column_demand)
+   run(economy_settings)
+end
+
+function explore_sea() --  if more than 3 ships are available it is time to explore the whole map
+   while #p1:get_ships() < 3 do sleep(3000) end
+   if #p1:get_buildings("empire_port") == 5 then
+      run(artifacts)
+   else
+      campaign_message_box(amalea_11)
+      o11 = add_campaign_objective(obj_find_all_ports)
+      -- check if all ports possible are build
+      while #p1:get_buildings("empire_port") < 5 do sleep(3000) end
+      o11.done = true
+      campaign_message_box(amalea_12)
+      run(artifacts)
+   end
+end
+
+function artifacts()  -- check for control of all artifacts
+   local artifact_fields = {}
+   local map = wl.Game().map
+   local i = 1
+   -- find all artifacts
+   for x=0, map.width-1 do
+      for y=0, map.height-1 do
+         local field = map:get_field(x,y)
+         if field.immovable and field.immovable:has_attribute("artifact") then
+            -- this assumes that the immovable has size small or medium, i.e. only occupies one field
+            artifact_fields[i] = map:get_field(x,y)
+            i = i + 1
+         end
+      end
+   end
+
+   while true do
+      sleep(4000)  
+      -- objective will be triggered if 50+ buildings are build
+      local number_buildings = {
+         "empire_headquarters_shipwreck", 
+         "empire_warehouse", 
+         "empire_port", 
+         "empire_quarry", 
+         "empire_lumberjacks_house", 
+         "empire_foresters_house", 
+         "empire_fishers_house", 
+         "empire_hunters_house", 
+         "empire_well", 
+         "empire_scouts_house", 
+         "empire_stonemasons_house", 
+         "empire_sawmill", 
+         "empire_mill", 
+         "empire_bakery", 
+         "empire_brewery", 
+         "empire_vineyard", 
+         "empire_winery", 
+         "empire_tavern", 
+         "empire_inn", 
+         "empire_charcoal_kiln", 
+         "empire_smelting_works", 
+         "empire_toolsmithy", 
+         "empire_armorsmithy", 
+         "empire_shipyard", 
+         "empire_donkeyfarm", 
+         "empire_farm", 
+         "empire_piggery", 
+         "empire_sheepfarm", 
+         "empire_weaving_mill", 
+         "empire_weaponsmithy", 
+         "empire_marblemine", 
+         "empire_marblemine_deep", 
+         "empire_coalmine", 
+         "empire_coalmine_deep", 
+         "empire_ironmine", 
+         "empire_ironmine_deep", 
+         "empire_goldmine", 
+         "empire_goldmine_deep", 
+         "empire_arena", 
+         "empire_colosseum", 
+         "empire_trainingcamp", 
+         "empire_blockhouse",
+         "empire_sentry", 
+         "empire_outpost", 
+         "empire_barrier", 
+         "empire_tower", 
+         "empire_fortress", 
+         "empire_castle",
+      }
+      if count_buildings(p1, number_buildings) > 50 then
+         break
+      end
+      sleep(4000)
+   end
+   campaign_message_box(saledus_8)
+   o12 = add_campaign_objective(obj_find_artifacts)
+
+   local artifacts_owner = {}
+   repeat
+      sleep(2000)
+      local all_artifacts_found = true
+      for idx, f in ipairs(artifact_fields) do
+         if f.owner then
+            if not artifacts_owner[f] then
+               if f.owner ~= p1 then
+                  artifacts_owner[f] = nil
+                  all_artifacts_found = false
+               else
+                  artifacts_owner[f] = f.owner
+                  sleep(2000)
+                  campaign_message_box(diary_page_6)
+                  scroll_to_field(f)
+               end
+            end
+         else
+            all_artifacts_found = false
+         end
+      end
+   until all_artifacts_found	 
+   campaign_message_box(saledus_9)
+   o12.done = true  
+end
+
+function check_wood_industry()  -- check for completed Woddcutter and sawmill
+   while not check_for_buildings(p1, { empire_lumberjacks_house = 1, empire_sawmill = 1}) do sleep(2000) end
+   campaign_message_box(amalea_10)
+end
+
+function check_military()  -- check for too much military buildings
+   local too_much_mil_build = nil
+   while not too_much_mil_build do
+      local number_mil_buildings = {
+         "empire_sentry", 
+         "empire_blockhouse", 
+         "empire_outpost", 
+         "empire_barrier", 
+         "empire_tower",
+      }
+      if count_buildings(p1, number_mil_buildings) > 2 and #p1:get_buildings("empire_port") < 2 then
+         too_much_mil_build = 1
+         break
+      end
+   sleep(3000)
+   end
+   campaign_message_box(amalea_9)
+end
+
+function economy_settings()  -- check for opened economy options window
+   while not hq.flag.economy:ware_target_quantity("marble_column") == 4 do sleep(2434) end
+   sleep(40000)
+   o3.done = true 
+   campaign_message_box(amalea_8)   
+end
+
+function building_industry()  -- check for completed building industry
+   run(check_stonemason)
+   run(check_wood_industry)
+   while not check_for_buildings(p1, { empire_lumberjacks_house = 1, empire_sawmill = 1, empire_stonemasons_house = 1})
+      do sleep(2343) end
+   o2.done = true
+   end
+
+function port_build()  -- check for port build to realize we need gold
+   while not check_for_buildings(p1, {empire_port = 1}) do sleep(2434) end
+   campaign_message_box(amalea_6)
+   p1:allow_buildings{ 
+      "empire_brewery",
+      "empire_coalmine",
+      "empire_coalmine_deep",
+      "empire_ironmine",
+      "empire_ironmine_deep",
+      "empire_goldmine",
+      "empire_goldmine_deep",
+      "empire_vineyard",
+      "empire_winery",
+      "empire_mill",
+      "empire_bakery",
+      "empire_piggery",
+      "empire_donkeyfarm",
+      "empire_tavern",
+      "empire_inn",
+      "empire_toolsmithy",
+      "empire_armorsmithy",
+      "empire_weaponsmithy",
+      "empire_smelting_works",
+       }
+   p2:allow_buildings{
+      "barbarians_coalmine",
+      "barbarians_ironmine",
+      "barbarians_goldmine",
+      "barbarians_granitemine",
+      "barbarians_coalmine_deep",
+      "barbarians_ironmine_deep",
+      "barbarians_goldmine_deep",
+      "barbarians_coalmine_deeper",
+      "barbarians_ironmine_deeper",
+      "barbarians_goldmine_deeper",
+      "barbarians_port",
+      "barbarians_cattlefarm",
+      "barbarians_charcoal_kiln",
+      "barbarians_weaving_mill",
+      }
+   o7 = add_campaign_objective(obj_produce_gold)
+   run(check_gold)
+end
+
+function check_gold()  -- check for gold to be able to send out expeditions
+   while p1:get_produced_wares_count('gold') < 6 do sleep(2434) end
+   campaign_message_box(amalea_7)
+   o7.done = true
+end
+
+function ship_industry()
+   run(port_build)
+   while not check_for_buildings(p1, { empire_port = 1, empire_shipyard =1 }) do sleep(2434) end
+   campaign_message_box(diary_page_4)
+   o5.done = true
+end
+
+function wheat() -- check for enough wheat in warehouses
+   while count_in_warehouses("wheat") < 50 do sleep(2434) end
+   campaign_message_box(amalea_5)
+   p1:allow_buildings{"empire_well"}
+   p2:allow_buildings{"barbarians_warehouse" }
+   o6.done = true
+   -- We need to turn the wheat into cloth for building ships
+   o8 = add_campaign_objective(obj_produce_cloth)
+   p1:allow_buildings{ 
+      "empire_sheepfarm",
+      "empire_weaving_mill",
+      "empire_charcoal_kiln",
+      "empire_marblemine",
+      "empire_marblemine_deep"
+   }
+   p2:allow_buildings{
+      "barbarians_port",
+      "barbarians_shipyard", 
+      "barbarians_brewery", 
+      "barbarians_inn",
+      "barbarians_smelting_works",
+      "barbarians_metal_workshop",
+      "barbarians_ax_workshop",
+      "barbarians_warmill",
+      "barbarians_helmsmithy",
+      "barbarians_barracks",
+      "barbarians_battlearena",
+      "barbarians_trainingcamp",
+      "barbarians_big_inn",
+   }
+
+   while p1:get_produced_wares_count('cloth') < 6 do sleep(2434) end
+   o8.done = true
+   run(expedition)
+end
+
+function expedition()
+   -- now we should explore our little world
+   while not o5.done == true do sleep(2434) end
+   campaign_message_box(saledus_5)
+   o9 = add_campaign_objective(obj_build_expedition_ports)
+
+   while not check_for_buildings(p1, { empire_port = 3 }) do sleep(2434) end
+   campaign_message_box(saledus_6)
+
+   p1:allow_buildings{"empire_barracks",
+                      "empire_fortress", 
+                      "empire_arena", 
+                      "empire_trainingcamp",
+                      "empire_colosseum",
+                      "empire_warehouse",
+                      "empire_castle",
+                      "empire_scouts_house",
+   }
+   p2:allow_buildings{"barbarians_scouts_hut",
+                      "barbarians_citadel",
+   }
+
+   o9.done = true
+   o10 = add_campaign_objective(obj_conquer_all)
+   run(explore_sea)
+   run(soldiers)
+
+   while true do
+      local barmil = {
+         "barbarians_headquarters", 
+         "barbarians_warehouse", 
+         "barbarians_port"}
+      if count_buildings(p2, barmil) < 1 then
+         break
+      end
+      sleep(2342)
+   end
+   o10.done = true
+
+   -- Babarians defeated. 
+   campaign_message_box(saledus_7)
+
+   while not o12.done == true do sleep(3000) end -- to get home we need as well all artifacts 
+   sleep(25000) -- Sleep a while to have some time between the last objective done message and final victory
+   campaign_message_box(diary_page_5)
+
+   p1:reveal_campaign("campsect2")
+   p1:reveal_scenario("empiretut03")
+end
+
+function soldiers() -- after discovery of babarian ruins we should hurry to build a full training capability
+   local ruins = map:get_field(86,82)
+   local ruin_fortress = map:get_field(85,80)
+
+   while not p1:sees_field(ruins) == true do sleep(3000) end
+   scroll_to_field(ruin_fortress,5)
+   campaign_message_box(saledus_12)
+   p1: reveal_fields(ruin_fortress:region(5))
+
+   local training = p1:get_buildings{
+      "empire_trainingcamp", 
+      "empire_barracks", 
+      "empire_arena", 
+      "empire_colosseum"
+   }
+
+   if #training.empire_trainingcamp > 0 and 
+      #training.empire_barracks > 0 and 
+      (#training.empire_arena > 0 or #training.empire_colosseum > 0) then
+      campaign_message_box(saledus_10)
+   else
+      campaign_message_box(saledus_11)
+      o13 = add_campaign_objective(obj_training)
+   end
+
+   while not (#training.empire_trainingcamp > 0 and 
+              #training.empire_barracks > 0 and 
+              (#training.empire_arena > 0 or #training.empire_colosseum > 0)) do 
+      sleep(3000) 
+      training = p1:get_buildings{
+         "empire_trainingcamp", 
+         "empire_barracks", 
+         "empire_arena", 
+         "empire_colosseum"
+      }
+      end
+   o13.done = true
+   campaign_message_box(saledus_10)
+end
+
+function mission_thread()
+   sleep(1000)
+
+   -- Initial messages
+   local sea = map:get_field(28, 8)
+   scroll_to_field(sea,5)
+
+   campaign_message_box(diary_page_1)
+
+   -- Show the sea
+   p1:reveal_fields(sea:region(5))
+   local ship = p1:place_ship(sea)
+   sleep(2000)
+   campaign_message_box(diary_page_2)
+
+   -- Hide the sea after 2 seconds
+   sleep(500)
+   ship:remove()
+   sleep(500)
+   p1:hide_fields(sea:region(5), true)
+   sleep(500)
+
+   -- Stranded again
+   scroll_to_field(sf)  --scroll to the place where the ship is finally stranded
+   include "map:scripting/starting_conditions.lua"  --now we place the shipwreck headquarters and fill it with workers and wares
+   campaign_message_box(diary_page_3)
+   sleep(400)
+   campaign_message_box(saledus)
+   sleep(400)
+   campaign_message_box(amalea)
+   sleep(400)
+   campaign_message_box(saledus_1)
+   o = add_campaign_objective(obj_build_first_outpost)
+   while #p1:get_buildings("empire_outpost") < 1 do sleep(3249) end
+   o.done = true
+
+   -- Outpost is completed now
+   campaign_message_box(saledus_2)
+   o1 = add_campaign_objective(obj_build_quarry)
+   campaign_message_box(amalea_1)
+   while #p1:get_buildings("empire_quarry") < 1 do sleep(3000) end
+   o1.done = true
+
+   -- quarry is now build but we need more basic infrastructure
+   campaign_message_box(amalea_2)
+   p1:allow_buildings{
+      "empire_barrier", 
+      "empire_sawmill", 
+      "empire_stonemasons_house", 
+      "empire_foresters_house", 
+      "empire_tower",
+   }
+   p2:allow_buildings{
+      "barbarians_tower", 
+      "barbarians_fortress",
+   }
+   o2 = add_campaign_objective(obj_build_sawmill_stonemason_and_lumberjacks)
+   -- in the same time we need to discover more land and a port space
+   run(building_industry)
+   sleep(40000)
+   campaign_message_box(saledus_3)
+   p1:allow_buildings{
+      "empire_port", 
+      "empire_shipyard",
+   }
+   o4 = add_campaign_objective(obj_find_port_space)
+
+   local port = map:get_field(17, 17)
+   local fowned = nil
+   while not fowned do
+      if port.owner == p1 then
+         fowned = 1
+         break
+      end
+   sleep(3000)
+   end
+
+   sleep(3213)
+   o4.done = true
+
+   -- Portspace discovered now we can build a port
+   campaign_message_box(saledus_4)
+   p1:allow_buildings{
+      "empire_farm", 
+      "empire_fishers_house", 
+      "empire_hunters_house",
+   }
+   o5 = add_campaign_objective(obj_build_port_and_shipyard)
+   run(ship_industry)
+
+   -- patience we have to think about how to get enough cloth to build a ship
+   campaign_message_box(amalea_4)
+   o6 = add_campaign_objective(obj_produce_wheat)
+   run(wheat) 
+end
+
+run(mission_thread)
+run(check_military)

=== added file 'data/campaigns/emp03.wmf/scripting/starting_conditions.lua'
--- data/campaigns/emp03.wmf/scripting/starting_conditions.lua	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/scripting/starting_conditions.lua	2017-03-30 10:06:26 +0000
@@ -0,0 +1,144 @@
+-- =======================================================================
+--                                 Player 1
+-- =======================================================================
+-- p1.see_all = true
+p1:forbid_buildings("all")
+p1:allow_buildings{
+   "empire_outpost",
+   "empire_sentry",
+   "empire_blockhouse",
+   "empire_lumberjacks_house",
+   "empire_quarry",
+}
+hq = prefilled_buildings(p1,
+   {"empire_headquarters_shipwreck", 4, 6,
+      wares = {
+         basket = 1,
+         empire_bread = 8,
+         bread_paddle = 2,
+         cloth = 5,
+         coal = 12,
+         felling_ax = 6,
+         fire_tongs = 2,
+         fish = 6,
+         fishing_rod = 3,
+         flour = 6,
+         gold = 2,
+         granite = 20,
+         grape = 4,
+         hammer = 12,
+         armor_helmet = 4,
+         hunting_spear = 2,
+         iron = 12,
+         iron_ore = 5,
+         kitchen_tools = 4,
+         log = 30,
+         marble = 25,
+         marble_column = 6,
+         meal = 4,
+         meat = 6,
+         pick = 14,
+         planks = 45,
+         ration = 12,
+         saw = 3,
+         scythe = 5,
+         shovel = 6,
+         spear_wooden = 5,
+         water = 12,
+         wheat = 6,
+         wine = 8,
+         wool = 4,
+      },
+      workers = {
+         empire_armorsmith = 1,
+         empire_brewer = 1,
+         empire_builder = 10,
+         empire_carrier = 40,
+         empire_charcoal_burner = 1,
+         empire_donkey = 20,
+         empire_geologist = 4,
+         empire_lumberjack = 3,
+         empire_miner = 4,
+         empire_stonemason = 2,
+         empire_toolsmith = 2,
+         empire_weaponsmith = 1,
+      },
+      soldiers = {
+         [{0,0,0,0}] = 45,
+      }
+   }
+)
+
+-- =======================================================================
+--                                 Player 2
+-- =======================================================================
+p2:forbid_buildings("all")
+p2:allow_buildings{
+   "barbarians_bakery",
+   "barbarians_barrier",
+   "barbarians_farm",
+   "barbarians_fishers_hut",
+   "barbarians_hunters_hut",
+   "barbarians_lime_kiln",
+   "barbarians_lumberjacks_hut",
+   "barbarians_micro_brewery",
+   "barbarians_rangers_hut",
+   "barbarians_reed_yard",
+   "barbarians_sentry",
+   "barbarians_tavern",
+   "barbarians_well",
+   "barbarians_wood_hardener",
+   "barbarians_quarry",
+   "barbarians_gamekeepers_hut",
+}
+
+prefilled_buildings(p2,
+   {"barbarians_headquarters", 34, 74,
+   wares = {
+      ax = 6,
+      blackwood = 32,
+      barbarians_bread = 8,
+      bread_paddle = 2,
+      cloth = 5,
+      coal = 12,
+      fire_tongs = 2,
+      fish = 6,
+      fishing_rod = 2,
+      gold = 4,
+      granite = 40,
+      grout = 12,
+      hammer = 12,
+      hunting_spear = 2,
+      iron = 12,
+      iron_ore = 5,
+      kitchen_tools = 4,
+      log = 80,
+      meal = 4,
+      meat = 6,
+      pick = 14,
+      ration = 12,
+      scythe = 6,
+      shovel = 4,
+      snack = 3,
+      thatch_reed = 24,
+   },
+   workers = {
+      barbarians_blacksmith = 2,
+      barbarians_brewer = 1,
+      barbarians_builder = 10,
+      barbarians_carrier = 40,
+      barbarians_charcoal_burner = 1,
+      barbarians_gardener = 1,
+      barbarians_geologist = 4,
+      barbarians_lime_burner = 1,
+      barbarians_lumberjack = 3,
+      barbarians_miner = 4,
+      barbarians_ranger = 1,
+      barbarians_stonemason = 2,
+   },
+
+    soldiers = {
+       [{0,0,0,0}] = 45,
+    }
+  }
+)

=== added file 'data/campaigns/emp03.wmf/scripting/texts.lua'
--- data/campaigns/emp03.wmf/scripting/texts.lua	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/scripting/texts.lua	2017-03-30 10:06:26 +0000
@@ -0,0 +1,574 @@
+-- =========================
+-- Some formating functions
+-- =========================
+
+include "scripting/formatting.lua"
+include "scripting/format_scenario.lua"
+
+function lutius(title, text)
+   return speech("map:Lutius.png", "2F9131", title, text)
+end
+function saledus2(title, text)
+   return speech("map:Saledus2.png", "8F9131", title, text)
+end
+function saledus3(title, text)
+   return speech("map:Saledus3.png", "8F9131", title, text)
+end
+function saledus4(title, text)
+   return speech("map:Saledus.png", "8F9131", title, text)
+end
+function amalea1(title, text)
+   return speech("map:Amalea.png", "AF7511", title, text)
+end
+function amalea2(title, text)
+   return speech("map:Amalea2.png", "AF7511", title, text)
+end
+function amalea3(title, text)
+   return speech("map:Amalea3.png", "AF7511", title, text)
+end
+-- =======================================================================
+--                           Texts - No logic here
+-- =======================================================================
+
+
+-- ===========
+-- objectives
+-- ===========
+obj_build_first_outpost = {
+    name = "build_a_first_outpost",
+    title=_"Build a first outpost",
+    number = 1,
+    body = objective_text(_"First Outpost",
+       listitem_bullet(_[[Build a outpost at the yellow house symbol to the east of your provisional headquarters.]])
+    ),
+}
+
+obj_build_quarry = {
+   name = "build_quarry",
+   title=_"Build a quarry",
+   number = 1,
+   body = objective_text(_"Quarry",
+      listitem_bullet(_[[Build a quarry close to the lots of stone. So we can free some building lots and get some valued resources.]])
+   ),
+}
+
+
+obj_build_sawmill_stonemason_and_lumberjacks = {
+   name = "build_sawmill_stonemason_and_lumberjacks",
+   title=_"Build at least a lumberjack’s house, a sawmill and a stonemason to complete the building material supply chain",
+   number = 3,
+   body = objective_text(_"Lumberjack’s House, Sawmill and Stonemason",
+      listitem_bullet(_[[Build at least a lumberjack’s house, a sawmill and a stonemason as soon as there is enough space for them.]])
+   ),
+}
+
+obj_lower_marble_column_demand = {
+   name = "lower marble column demand",
+   title=_"Lower the demand for marble columns in the economy settings",
+   number = 1,
+   body = objective_text(_"Lower demand for marble columns",
+      listitem_bullet(_[[We should spare some marble for buildings. So please lower the demand for marble columns.]])
+   ),
+}
+
+obj_find_port_space = {
+   name = "find a portspace",
+   title=_"Find a portspace on the small island",
+   number = 1,
+   body = objective_text(_"Port Space",
+      listitem_bullet(_[[To get back to the sea we first must discover a portspace.]])
+   ),
+}
+
+obj_build_port_and_shipyard = {
+   name = "build a port and a shipyard",
+   title=_"Build a Port and a shipyard on the island",
+   number = 2,
+   body = objective_text(_"Ship Industry",
+      listitem_bullet(_[[Build a port to set sail from this island.]])..
+	  listitem_bullet(_[[Build a shipyard to produce the ships to sail on.]])),
+}
+
+obj_produce_wheat = {
+   name = "produce 50 wheat",
+   title=_"Produce an amount of 50 wheat",
+   number = 1,
+   body = objective_text(_"Wheat production",
+      listitem_bullet(_[[To start a wool production we need an amount of at least 50 wheat.]])
+   ),
+}
+
+obj_produce_cloth = {
+   name = "produce cloth",
+   title=_"Produce cloth for building our first ship",
+   number = 1,
+   body = objective_text(_"Cloth production",
+      listitem_bullet(_[[Now let's turn all the wheat into wool (at least 50) and all the wool into cloth to build a ship.]])
+   ),
+}
+
+obj_build_expedition_ports = {
+   name = "build two expedition ports",
+   title=_"Build 2 expedition ports",
+   number = 2,
+   body = objective_text(_"Build 2 expedition ports",
+      listitem_bullet(_[[We should explore the Island in the south and build an expedition port. Let's try to find some mining ressources there.]])..
+	  listitem_bullet(_[[We should send a ship to the north to get certainty about the barbarians. Try to build a port on the island to found an outpost.]])
+   ),
+}
+
+obj_produce_gold = {
+   name = "produce gold",
+   title=_"Produce gold to send out expeditions",
+   number = 1,
+   body = objective_text(_"Gold production",
+      listitem_bullet(_[[We need to produce at least 6 gold to be able to colonize our vicinity.]])
+   ),
+}
+
+obj_conquer_all = {
+   name = "Conquer all",
+   title=_"Defeat the barbarians",
+   number = 1,
+   body = objective_text(_"Defeat the enemy",
+      listitem_bullet(_[[We should end the barbarians existence in this piece of the world.]])
+   ),
+}
+
+obj_find_all_ports = {
+   name = "Explore additional islands and search for port spaces",
+   title=_"Explore further and build ports",
+   number = 1,
+   body = objective_text(_"Explore additional islands and search for port spaces",
+      listitem_bullet(_[[We should discover more land and build as much ports as we can.]])
+   ),
+}
+
+obj_find_artifacts = {
+   name = "Find the pieces of Neptune's shrine",
+   title=_"Recover the shrine",
+   number = 1,
+   body = objective_text(_"Find all pieces of the holy shrine",
+      listitem_bullet(_[[We need to find and secure all pieces of the holy shrine of Neptune.]])
+   ),
+}
+
+obj_training = {
+   name = "Build training infrastructure",
+   title=_"Build at least a trainingcamp, some barracks and an arena or colosseum",
+   number = 1,
+   body = objective_text(_"Training Infrastructure",
+      listitem_bullet(_[[Build a trainingcamp, some barracks and an arena or colosseum to train our soldiers.]])
+   ),
+}
+
+
+-- ==================
+-- Texts to the user
+-- ==================
+diary_page_1 = {
+   title =_"Journey home",
+   body=lutius(_"Diary of Lutius",
+      -- TRANSLATORS: Lutius - Diary
+      _([[Finally we were set to Fremil again. I couldn't await the chance to clear my records of this big defeat by the babarians.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Lutius - Diary
+      _([[But the gods themselves didn't want us to get home so quickly!]])),
+	
+   posy=1,
+}
+
+diary_page_2 = {
+   title=_"The wrath of Neptune",
+   body= lutius(_"Diary of Lutius",
+      -- TRANSLATORS: Lutius - Diary
+      _([[Neptune himself was against us and drove us into a dark, wild storm again. But this time it felt even worse than last time. The waves were double the height of our brave ship and the winds drove us into unsafe waters.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Lutius - Diary
+      _([[Our ship is heavily damaged. The mast has gone overboard and the hull is taking in more and more water. We would be glad to survive this black night with barely more than our lives.]])),
+
+   posy=1,
+}
+
+diary_page_3 = {
+   title=_"Shipwrecked again",
+   body= lutius(_"Diary of Lutius",
+      -- TRANSLATORS: Lutius - Diary
+      _([[Finally, the wrath of the gods and the ocean seems to be over.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Lutius - Diary
+      _([[We landed on an unknown coast and found some rest under the palm trees growing at the shore. But that is about as good as it gets. The truth is: when I woke up this morning, I saw nothing but sand and stone around us.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Lutius - Diary
+      _([[It really seems as if we have landed on a very small island with little space.]])
+	  .. paragraphdivider() ..
+      -- TRANSLATORS: Lutius - Diary
+      _([[To make it even worse all the land we can see is blocked by stone and trees. I fear we won’t find any help we need to build a new ship.]])
+	  .. paragraphdivider() ..
+      -- TRANSLATORS: Lutius - Diary
+      _([[I really don't know if and how we will get back home. And the war is going on without us. I hope my comrades defend our empire well.]])),
+
+   posy=1,
+}
+
+saledus = {
+    title=_"No sight",
+    body= saledus2(_"Saledus looks around nervously…",
+       -- TRANSLATORS: Saledus
+       _([[Sire, we do not know anything about the island. And I believe we are not safe as well. Probably it would be reasonable to build a tower to explore the island and add some military strength.]])),
+ 
+    posy=1,
+}
+
+amalea = {
+    title=_"Amalea interrupting",
+    body= amalea1(_"Amalea raises her hand…",
+    -- TRANSLATORS: Amalea
+    _([[Salve Lutius. As we don't know how much resources we can get we should be very restrictive in spending them. Even for military buildings we should be very careful.]])),
+
+    posy=1,
+}
+
+saledus_1 = {
+   title=_"Spare ressources",
+   body= saledus2(_"Saledus is nodding in agreement…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, Amalea is right about the resources. Therefore I correct myself. We should only build an outpost as this is the most effective military building.]]))
+      .. new_objectives(obj_build_first_outpost),
+	  
+   posy=1,
+}
+
+saledus_2 = {
+   title=_"Stone, nothing but stone",
+   body= saledus3(_"Saledus speaks with a sigh of relief…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, I saw that the construction of the outpost was completed, so I have assigned some of my best soldiers to it to keep the watch.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Saledus
+      _([[But although this is a good step forward I can't see much space for buildings. There is only stone all over the place. How can we ever build a new ship or even have some basic infrastructure to make our lives more comfortable.]])),
+   posy=1,
+}
+
+amalea_1 = {
+   title=_"Amalea's plan",
+   body= amalea2(_"Amalea smiles…",
+      -- TRANSLATORS: Amalea
+      _([[Lutius this can be very tricky but it is reachable. First of all we need patience as well as speed and a plan to succeed in this part of the world.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[I think we should try to reveal some building space by cutting all the stone in a quarry.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[Additionally this would gain us some stone and some marble to build up our new world. We can use them as soon as there is enough space for buildings finally.]]))
+      .. new_objectives(obj_build_quarry),
+   posy=1,
+}
+
+amalea_2 = {
+   title=_"Amalea's new instructions",
+   body= amalea3(_"Amalea recommends…",
+      -- TRANSLATORS: Amalea
+      _([[Good news from the people, Lutius. I got the message that our first quarry has started it's work today.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[Perhaps it would be a good idea to wait until it has cleared some space for building up a basic construction material industry.]]))
+	  .. new_objectives(obj_build_sawmill_stonemason_and_lumberjacks),
+   posy=1,
+}
+
+amalea_3 = {
+   title=_"Amalea's recommendations",
+   body= amalea2(_"Amalea comes in…",
+      -- TRANSLATORS: Amalea
+      _([[I’ve got important things to talk about… First the good news:]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[I noticed that our stonemason has started it’s work finally. He will cut the number of columns defined in our basic economy settings.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[But here is the problem, if we use all of our marble for columns we might ran out of it. So we should lower the settings for marble columns in the economy settings to a smaller amount. I think a reserve of 4 columns might be sufficient for the moment being.]]))
+      .. new_objectives(obj_lower_marble_column_demand),
+   posy=1,
+}
+
+amalea_10 = {
+   title=_"Amalea looks happy",
+   body= amalea2(_"Amalea comes in…",
+      -- TRANSLATORS: Amalea
+      _([[Ave Lutius. I have very good progress to report now.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[I found out that the construction of the lumberjack and the sawmill is complete, so we can begin to harvest the logs and make planks out of it.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[This is a great step forward in constructing advanced buildings. And we can think of using some planks to build new ships.]])),
+   posy=1,
+}
+
+saledus_3 = {
+   title=_"We need a port",
+   body= saledus2(_"Saledus thoughtfully…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, I just thought about our way home. It is utmost important to build a port for loading our ships and start an expedition.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Saledus
+      _([[The problem is that a port is a building which needs a very special place to be build. So while buidling our economy we should nevertheless expand further to discover the whole island. Let's try to find such a valuable place.]]))
+      .. new_objectives(obj_find_port_space),
+   posy=1,
+}
+
+saledus_4 = {
+   title=_"A Step closer to get home",
+   body= saledus3(_"Saledus looks excited…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, today we got a lot closer to finally get home again. Our military has spotted a space to build a port on. We should start to build a port quickly.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Saledus
+      _([[Now we truly can look forward to build some ships. So we should build a shipyard as well.]]))
+	  .. new_objectives(obj_build_port_and_shipyard),
+   posy=1,
+}
+
+amalea_4 = {
+   title=_"Amalea's wisdom",
+   body= amalea2(_"Amalea recommends…",
+      -- TRANSLATORS: Amalea
+      _([[I understand the euphoria of saledus but we have some serious problems to solve first.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[To send out an expeditionary ship we first need a ship. Unfortunately we have only 5 cloth left which we will need to build the port and the shipyard.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[So we need more cloth to finally be able to build ships. But there is no space on the island to build a whole economy to produce cloth. Therefore we need to build the necessary wares in a more serial way.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[So let's think this over. To produce cloth we need some wool. And to produce wool we need wheat so let'S find a space for a big building and build a wheat farm first.]])
+	  .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[After the production of enough wheat we can dismantle the farm and build a sheepfarm to produce wool. Later on we could build a weaving mill in the same spot to use our wool for weaving cloth. But for the moment being let's start with producing a reasonable amount of wheat.]])
+	  .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[I think for the beginning a stock of 50 wheat would be enough. Perhaps we have to adjust the target quantity for wheat to achieve this.]]))
+      .. new_objectives(obj_produce_wheat),
+   posy=1,
+}
+
+
+diary_page_4 = {
+   title=_"Seafaring possible again",
+   body= lutius(_"Diary of Lutius",
+      -- TRANSLATORS: Lutius - Diary
+      _([[Praise the gods. We finally have a ship industry.]])),
+   posy=1,
+}
+
+
+amalea_5 = {
+   title=_"Amalea's pride",
+   body= amalea2(_"Amalea cheers…",
+      -- TRANSLATORS: Amalea
+      _([[Well done so far. We have produced enough wheat. Now dismantle the farm and build the next building in the production chain.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[Don't forget to check the target quantity of wool and cloth in the economy settings. We need to turn all the wheat into wool and then the all the wool into cloth.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[Perhaps it would be a good idea to stop the shipyard's production until we have some cloth available to not waste any logs or planks.]]))
+      .. new_objectives(obj_produce_cloth),
+   posy=1,
+}
+
+saledus_5 = {
+   title=_"We should explore the islands",
+   body= saledus2(_"Saledus is excited…",
+      -- TRANSLATORS: Saledus
+      _([[Now that we have all ressources ready to built a ship, we should explore the surrounding islands.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Saledus
+      _([[First we need to find some more ressources to back up our growing economy. I have spotted an island with some mountains in the south. Perhaps we can find some valuable ressources like iron there.]])
+	  .. paragraphdivider() ..
+      -- TRANSLATORS: Saledus
+      _([[But even more important is the following objective.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Saledus
+      _([[I think I have heard the wind carrying some weird but well known sounds from the north. If I'm not totally wrong I heard some barbarian war drums, so we should better going to look what is going on up there.]]))
+	  .. new_objectives(obj_build_expedition_ports),
+   posy=1,
+}
+
+amalea_6 = {
+   title=_"Amalea has some advice",
+   body= amalea3(_"Amalea looks thoughtfully…",
+      -- TRANSLATORS: Amalea
+      _([[Salve Lutius. While talking to all our brave builders, they told me that they had to use all our remaining gold for building the port. Now we don't have any gold left.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[But the problem is that for sending out an expedition we need some gold.]])
+      .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[Fortunately I recognized there is a mountain which looks very promising to have some mining ressources. Perhaps we should send some geologists to explore the hidden ressources.]])
+      .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[I strongly recommend to build a production chain for mining and melting some gold. I think we need a vineyard, a winery, a tavern, a fisher's house or a hunter's house and a smelting works. And the mines themselves of course.]])
+	  .. paragraphdivider() ..
+      -- TRANSLATORS: Amalea
+      _([[If there are difficulties to build all the buildings needed, we should think about all we have learned so far. We can cut all the stone. We should perhaps optimize our roads to free up some building site, or even dismantle some military buildings to get more space for our economy.]]))
+      .. new_objectives(obj_produce_gold),
+   posy=1,
+}
+
+saledus_6 = {
+   title=_"We should conquer the whole islands",
+   body= saledus3(_"Saledus is excited…",
+      -- TRANSLATORS: Saledus
+      _([[Now it is time to conquer the islands.]])
+      .. paragraphdivider() ..
+      _([[Let's finish the barbarians off and provide a nice colony to the caesar of our empire.]]))
+      .. new_objectives(obj_conquer_all),
+   posy=1,
+}
+
+amalea_7 = {
+   title=_"Amalea's luck",
+   body= amalea2(_"Amalea is really proud of the achievements…",
+      -- TRANSLATORS: Amalea
+      _([[Lutius we have just solved another problem. We managed to melt enough gold to send out at least 3 expeditions. Perhaps we might even keep some gold to make some jewelry.]])
+      .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[I'm just kidding. Of course we should spare as much gold as we can for building an Arena and other buildings to train our soldiers.]])),
+   posy=1,
+}
+
+amalea_8 = {
+   title=_"Amalea is pleased",
+   body= amalea1(_"Amalea is content that we will manage all our challenges",
+      -- TRANSLATORS: Amalea
+      _([[Well done so far. I really think we will need this feature quite often to adjust our economy. Remember our industry is just working until the given amount in the economy settings is reached.]])
+      .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[For example it might be a good idea to produce a reasonable amount of a ware and afterwards dismantle the building to gain space for another building.]])),
+   posy=1,
+}
+
+amalea_9 = {
+   title=_"Amalea shaking head",
+   body= amalea3(_"Amalea is reminding ...",
+      -- TRANSLATORS: Amalea
+      _([[Lutius. I really appreciate that you and Saledus are so concerned about our security. But I think we could use the little space on this island better than building a lot of military buildings.]])
+      .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[I strongly recommend to dismantle the most of them to be able to build industry buildings. I don't think there is much danger on this island, but if you want to be cautious you can keep some sentries or blockhouses at the waterline.]])
+      .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[But be careful not to waste any bigger building lots.]])),
+   posy=1,
+}
+
+amalea_11 = {
+   title=_"Amalea excited",
+   body= amalea1(_"Amalea is looking forward for exploration ...",
+      -- TRANSLATORS: Amalea
+      _([[Lutius. We have made so much progress so far. I just got the information that we have completed our third ship. ]])
+      .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[Now that our fleet is growing and growing we should discover the complete region. Let's try to find more land and eventually get more ressources.]])
+      .. paragraphdivider() ..
+	  -- TRANSLATORS: Amalea
+      _([[Especially it would be very helpful to find more marble either within stone fields or in the mountains to mine it.]]))
+	  .. new_objectives(obj_find_all_ports),
+   posy=1,
+}
+
+amalea_12 = {
+   title=_"Amalea is very content",
+   body= amalea2(_"Amalea is clapping her hands...",
+      -- TRANSLATORS: Amalea
+      _([[Lutius. Well done. Well done. We have discovered all possible port locations in the complete region. Now we can backup our economy and we will manage to sail home soon.]])),
+   posy=1,
+}
+   
+saledus_7 = {
+   title=_"Victory is our's",
+   body= saledus3(_"Saledus is cheering out…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, finally we have defeated the babarians in this region. And furthermore we have build a nice colony for our empire.]])
+      .. paragraphdivider() ..
+      _([[Caesar will be very pleased about our victory.]])),
+   posy=1,
+}
+
+saledus_8 = {
+   title=_"Pleasing Neptune",
+   body= saledus4(_"Saledus is very sad and anxious…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, we are making good progress to get home eventually. But there is one thing I need to talk about:]])
+      .. paragraphdivider() ..
+      _([[As we have seen the last time it is of great importance that the gods and especially Neptune are in a good mood to guard our journey.]])
+      .. paragraphdivider() ..
+      _([[Unfortunately we lost our holy shrine of Neptune in the great storm, so we can't worship him well. I think we should search the whole region to see if we can recover the shrine with all its 5 pieces.]])
+      .. paragraphdivider() ..
+      _([[To ease up the search I made some models of the pieces as you can see. You can give them to our soldiers and sailors to look for them.]]))
+	  .. new_objectives(obj_find_artifacts),
+   posy=1,
+}
+
+saledus_9 = {
+   title=_"Praise, praise, praise",
+   body= saledus2(_"Saledus is happily worshipping…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, we recovered the holy shrine of Neptune. Now we can seek his protection for our journey.]])
+      .. paragraphdivider() ..
+      _([[Oh great Neptune safeguard our journey. Oh great Neptune let the winds be friendly for our course. Oh great Neptune beware us from the creatures of the sea. Oh great Neptune......]])),
+   posy=1,
+}
+
+saledus_12 = {
+   title=_"Unpleasant discoveries",
+   body= saledus3(_"Saledus looks very worried…",
+      -- TRANSLATORS: Saledus
+      _([[Sire, we found the ruins of a former babarian fortress and village. I'm somewhat worried we will have to fight against them sooner than we wanted.]])),
+   posy=1,
+}
+
+saledus_10 = {
+   title=_"Train faster, train harder",
+   body= saledus2(_"Saledus is demanding some discipline",
+      -- TRANSLATORS: Saledus
+      _([[Sire, we have all buildings available to train our soldiers but we should increase our efforts to train them to the highest level and to train more of them.]])
+      .. paragraphdivider() ..
+      _([[We need a lot of food, a lot of iron and a lot of gold to do so. So we have lots of challenges to cope with.]])),
+   posy=1,
+}
+
+saledus_11 = {
+   title=_"Training infrastructure is needed",
+   body= saledus3(_"Saledus has security concerns",
+      -- TRANSLATORS: Saledus
+      _([[Sire, we need to train some of our people to serve in your great army. It is important to increase the number of our soldiers as fast as we can. And we should train them well to improve their fighting abilities.]])
+      .. paragraphdivider() ..
+      _([[Therefore we need to build a full training infrastructure despite the limited space available. We need some barracks, a trainingcamp and an arena or a colosseum.]]))
+	  .. new_objectives(obj_training),
+   posy=1,
+}
+
+
+
+diary_page_5 = {
+   title=_"Now it's time to get home again",
+   body= lutius(_"Diary of Lutius",
+      -- TRANSLATORS: Lutius - Diary
+      _([[Yes my fellow comrades, we have done it. We managed all the challenges that were put on us. But my heart is still with our home. We shall set sail as soon as possible to help defend the empire from the babarian tribe.]])
+	  .. paragraphdivider() ..
+      _([[You have completed this mission. You may continue playing if you wish, otherwise move on to the next mission.]])),
+   posy=1,
+}
+
+
+diary_page_6 = {
+   title=_"Artifact found",
+   body= lutius(_"Diary of Lutius",
+      -- TRANSLATORS: Lutius - Diary
+      _([[Finally we found a piece of our shrine. Praise Neptune.]])),
+   posy=1,
+}
\ No newline at end of file

=== added file 'data/campaigns/emp03.wmf/version'
--- data/campaigns/emp03.wmf/version	1970-01-01 00:00:00 +0000
+++ data/campaigns/emp03.wmf/version	2017-03-30 10:06:26 +0000
@@ -0,0 +1,11 @@
+# Automatically created by Widelands bzr8330[empire-mission-3] (Debug)
+
+[global]
+map_source_url=
+map_release=
+map_creator_version="bzr8330[empire-mission-3]"
+map_version_major="0"
+map_version_minor="1"
+map_version_timestamp="1490533022"
+packet_version="1"
+packet_compatibility="1"

=== modified file 'src/logic/player.cc'
--- src/logic/player.cc	2017-03-03 18:13:55 +0000
+++ src/logic/player.cc	2017-03-30 10:06:26 +0000
@@ -1024,9 +1024,10 @@
 	field.vision = fvision;
 }
 
-void Player::unsee_node(MapIndex const i, Time const gametime, bool const forward) {
+/// If 'hide_completely', fields will be marked as unexplored. Else, player no longer sees what's currently going on.
+void Player::unsee_node(MapIndex const i, Time const gametime, const bool hide_completely,  bool const forward) {
 	Field& field = fields_[i];
-	if (field.vision <= 1)  //  Already does not see this
+	if ((!hide_completely && field.vision <= 1) || field.vision < 1)  //  Already does not see this
 		return;
 
 	//  If this is not already a forwarded call, we should inform allied players
@@ -1035,13 +1036,18 @@
 		update_team_players();
 	if (!forward && !team_player_.empty()) {
 		for (uint8_t j = 0; j < team_player_.size(); ++j)
-			team_player_[j]->unsee_node(i, gametime, true);
+			team_player_[j]->unsee_node(i, gametime, hide_completely, true);
 	}
 
-	--field.vision;
-	if (field.vision == 1)
+	if (hide_completely) {
+		field.vision = 0;
+	} else {
+		--field.vision;
+		assert(1 <= field.vision);
+	}
+	if (field.vision < 2) {
 		field.time_node_last_unseen = gametime;
-	assert(1 <= field.vision);
+	}
 }
 
 /**

=== modified file 'src/logic/player.h'
--- src/logic/player.h	2017-01-25 18:55:59 +0000
+++ src/logic/player.h	2017-03-30 10:06:26 +0000
@@ -445,7 +445,7 @@
 	              const bool forward = false);
 
 	/// Decrement this player's vision for a node.
-	void unsee_node(const MapIndex, const Time, const bool forward = false);
+	void unsee_node(const MapIndex, const Time, const bool hide_completely = false, const bool forward = false);
 
 	/// Call see_node for each node in the area.
 	void see_area(const Area<FCoords>& area) {

=== modified file 'src/scripting/lua_game.cc'
--- src/scripting/lua_game.cc	2017-01-25 18:55:59 +0000
+++ src/scripting/lua_game.cc	2017-03-30 10:06:26 +0000
@@ -620,6 +620,9 @@
       :arg fields: The fields to hide
       :type fields: :class:`array` of :class:`wl.map.Fields`
 
+      :arg hide_completely: *Optional*. The fields will be marked as unexplored.
+      :type hide_completely: :class:`boolean`
+
       :returns: :const:`nil`
 */
 int LuaPlayer::hide_fields(lua_State* L) {
@@ -628,11 +631,12 @@
 	Map& m = egbase.map();
 
 	luaL_checktype(L, 2, LUA_TTABLE);
+	const bool hide_completely = !lua_isnone(L, 3) && luaL_checkboolean(L, 3);
 
 	lua_pushnil(L); /* first key */
 	while (lua_next(L, 2) != 0) {
-		p.unsee_node(
-		   (*get_user_class<LuaField>(L, -1))->fcoords(L).field - &m[0], egbase.get_gametime());
+		p.unsee_node((*get_user_class<LuaField>(L, -1))->fcoords(L).field - &m[0],
+		             egbase.get_gametime(), hide_completely);
 		lua_pop(L, 1);
 	}
 

=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc	2017-01-30 14:40:12 +0000
+++ src/scripting/lua_map.cc	2017-03-30 10:06:26 +0000
@@ -3342,6 +3342,134 @@
  */
 
 /* RST
+Economy
+-------
+.. class:: LuaEconomy
+
+   Provides access to an economy. A player can have multiple economies;
+   you can get an economy from a :class:`Flag`.
+*/
+const char LuaEconomy::className[] = "Economy";
+const MethodType<LuaEconomy> LuaEconomy::Methods[] = {
+   METHOD(LuaEconomy, ware_target_quantity),
+   METHOD(LuaEconomy, worker_target_quantity),
+   METHOD(LuaEconomy, set_ware_target_quantity),
+   METHOD(LuaEconomy, set_worker_target_quantity),
+   {nullptr, nullptr},
+};
+const PropertyType<LuaEconomy> LuaEconomy::Properties[] = {
+   {nullptr, nullptr, nullptr},
+};
+
+void LuaEconomy::__persist(lua_State* L) {
+	const Widelands::Economy* economy = get();
+	const Widelands::Player& player = economy->owner();
+	PERS_UINT32("player", player.player_number());
+	PERS_UINT32("economy", player.get_economy_number(economy));
+}
+
+void LuaEconomy::__unpersist(lua_State* L) {
+	Widelands::PlayerNumber player_number;
+	size_t economy_number;
+	UNPERS_UINT32("player", player_number);
+	UNPERS_UINT32("economy", economy_number);
+	const Widelands::Player& player = get_egbase(L).player(player_number);
+	set_economy_pointer(player.get_economy_by_number(economy_number));
+}
+
+/* RST
+   .. method:: ware_target_quantity(warename)
+
+      Returns the amount of the given ware that should be kept in stock for this economy.
+
+      :arg warename: the name of the ware.
+      :type warename: :class:`string`
+*/
+int LuaEconomy::ware_target_quantity(lua_State* L) {
+	const std::string warename = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(warename);
+	if (get_egbase(L).tribes().ware_exists(index)) {
+		const Widelands::Economy::TargetQuantity& quantity = get()->ware_target_quantity(index);
+		lua_pushinteger(L, quantity.permanent);
+	} else {
+		report_error(L, "There is no ware '%s'.", warename.c_str());
+	}
+	return 1;
+}
+
+/* RST
+   .. method:: worker_target_quantity(workername)
+
+      Returns the amount of the given worker that should be kept in stock for this economy.
+
+      :arg workername: the name of the worker.
+      :type workername: :class:`string`
+*/
+int LuaEconomy::worker_target_quantity(lua_State* L) {
+	const std::string workername = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(workername);
+	if (get_egbase(L).tribes().worker_exists(index)) {
+		const Widelands::Economy::TargetQuantity& quantity = get()->worker_target_quantity(index);
+		lua_pushinteger(L, quantity.permanent);
+	} else {
+		report_error(L, "There is no worker '%s'.", workername.c_str());
+	}
+	return 1;
+}
+
+/* RST
+   .. method:: set_ware_target_quantity(warename)
+
+      Sets the amount of the given ware type that should be kept in stock for this economy.
+
+      :arg warename: the name of the ware type.
+      :type warename: :class:`string`
+
+      :arg amount: the new target amount for the ware. Needs to be >= 0.
+      :type amount: :class:`integer`
+*/
+int LuaEconomy::set_ware_target_quantity(lua_State* L) {
+	const std::string warename = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().ware_index(warename);
+	if (get_egbase(L).tribes().ware_exists(index)) {
+		const int quantity = luaL_checkinteger(L, 3);
+		if (quantity < 0) {
+			report_error(L, "Target ware quantity needs to be >= 0 but was '%d'.", quantity);
+		}
+		get()->set_ware_target_quantity(index, quantity, get_egbase(L).get_gametime());
+	} else {
+		report_error(L, "There is no ware '%s'.", warename.c_str());
+	}
+	return 1;
+}
+
+/* RST
+   .. method:: set_worker_target_quantity(workername)
+
+      Sets the amount of the given worker type that should be kept in stock for this economy.
+
+      :arg workername: the name of the worker type.
+      :type workername: :class:`string`
+
+      :arg amount: the new target amount for the worker. Needs to be >= 0.
+      :type amount: :class:`integer`
+*/
+int LuaEconomy::set_worker_target_quantity(lua_State* L) {
+	const std::string workername = luaL_checkstring(L, 2);
+	const Widelands::DescriptionIndex index = get_egbase(L).tribes().worker_index(workername);
+	if (get_egbase(L).tribes().worker_exists(index)) {
+		const int quantity = luaL_checkinteger(L, 3);
+		if (quantity < 0) {
+			report_error(L, "Target worker quantity needs to be >= 0 but was '%d'.", quantity);
+		}
+		get()->set_worker_target_quantity(index, quantity, get_egbase(L).get_gametime());
+	} else {
+		report_error(L, "There is no worker '%s'.", workername.c_str());
+	}
+	return 1;
+}
+
+/* RST
 MapObject
 ---------
 
@@ -3682,7 +3810,10 @@
    METHOD(LuaFlag, set_wares), METHOD(LuaFlag, get_wares), {nullptr, nullptr},
 };
 const PropertyType<LuaFlag> LuaFlag::Properties[] = {
-   PROP_RO(LuaFlag, roads), PROP_RO(LuaFlag, building), {nullptr, nullptr, nullptr},
+   PROP_RO(LuaFlag, economy),
+   PROP_RO(LuaFlag, roads),
+   PROP_RO(LuaFlag, building),
+   {nullptr, nullptr, nullptr},
 };
 
 /*
@@ -3691,6 +3822,18 @@
  ==========================================================
  */
 /* RST
+   .. attribute:: economy
+
+      (RO) Returns the economy that this flag belongs to.
+
+      :returns: The :class:`Economy` associated with the flag.
+*/
+int LuaFlag::get_economy(lua_State* L) {
+	const Flag* f = get(L, get_egbase(L));
+	return to_lua<LuaEconomy>(L, new LuaEconomy(f->get_economy()));
+}
+
+/* RST
    .. attribute:: roads
 
       (RO) Array of roads leading to the flag. Directions
@@ -6075,6 +6218,7 @@
 
 	register_class<LuaField>(L, "map");
 	register_class<LuaPlayerSlot>(L, "map");
+	register_class<LuaEconomy>(L, "map");
 	register_class<LuaMapObject>(L, "map");
 
 	register_class<LuaBob>(L, "map", true);

=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h	2017-01-25 18:55:59 +0000
+++ src/scripting/lua_map.h	2017-03-30 10:06:26 +0000
@@ -22,6 +22,7 @@
 
 #include <set>
 
+#include "economy/economy.h"
 #include "economy/flag.h"
 #include "economy/portdock.h"
 #include "economy/road.h"
@@ -728,6 +729,54 @@
 	const Widelands::TerrainDescription* terraindescr_;
 };
 
+class LuaEconomy : public LuaMapModuleClass {
+public:
+	LUNA_CLASS_HEAD(LuaEconomy);
+
+	virtual ~LuaEconomy() {
+	}
+
+	LuaEconomy() : economy_(nullptr) {
+	}
+	LuaEconomy(Widelands::Economy* economy) : economy_(economy) {
+	}
+	LuaEconomy(lua_State* L) : economy_(nullptr) {
+		report_error(L, "Cannot instantiate a 'LuaEconomy' directly!");
+	}
+
+	void __persist(lua_State* L) override;
+	void __unpersist(lua_State* L) override;
+
+	/*
+	 * Properties
+	 */
+
+	/*
+	 * Lua methods
+	 */
+	int ware_target_quantity(lua_State*);
+	int worker_target_quantity(lua_State*);
+	int set_ware_target_quantity(lua_State*);
+	int set_worker_target_quantity(lua_State*);
+
+	/*
+	 * C methods
+	 */
+
+protected:
+	Widelands::Economy* get() const {
+		assert(economy_ != nullptr);
+		return economy_;
+	}
+	// For persistence.
+	void set_economy_pointer(Widelands::Economy* pointer) {
+		economy_ = pointer;
+	}
+
+private:
+	Widelands::Economy* economy_;
+};
+
 #define CASTED_GET(klass)                                                                          \
 	Widelands::klass* get(lua_State* L, Widelands::EditorGameBase& egbase) {                        \
 		return static_cast<Widelands::klass*>(LuaMapObject::get(L, egbase, #klass));                 \
@@ -904,6 +953,7 @@
 	/*
 	 * Properties
 	 */
+	int get_economy(lua_State* L);
 	int get_roads(lua_State* L);
 	int get_building(lua_State* L);
 	/*

=== added file 'test/maps/lua_testsuite.wmf/scripting/geconomy.lua'
--- test/maps/lua_testsuite.wmf/scripting/geconomy.lua	1970-01-01 00:00:00 +0000
+++ test/maps/lua_testsuite.wmf/scripting/geconomy.lua	2017-03-30 10:06:26 +0000
@@ -0,0 +1,52 @@
+-- ==================================================
+-- Tests for Economy that are only useful in the Game
+-- ==================================================
+
+economy_tests = lunit.TestCase("Economy test")
+function economy_tests:test_instantiation_forbidden()
+   assert_error("Cannot instantiate", function()
+      wl.map.Economy()
+   end)
+end
+
+function economy_tests:test_ware_target_quantity()
+
+   -- Get the economy off a flag
+   local sf = map:get_field(10, 10)
+   local hq = player1:place_building("barbarians_headquarters", sf, false, true)
+   local hq_flag = hq.flag
+   local eco = hq_flag.economy
+
+   -- Test illegal parameters
+   assert_error("Nonexisting ware",function() eco:ware_target_quantity("foobar") end)
+   assert_error("Quantity for nonexisting ware",function() eco:worker_target_quantity("foobar", 1) end)
+   assert_error("Negative ware quantity",function() eco:set_ware_target_quantity("log", -1) end)
+
+   -- Now set and confirm ware quantity
+   quantity = eco:ware_target_quantity("log")
+   quantity = quantity + 1
+   eco:set_ware_target_quantity("log", quantity)
+   assert_equal(quantity, eco:ware_target_quantity("log"))
+
+   hq_flag:remove()
+end
+
+function economy_tests:test_worker_target_quantity()
+   -- Get the economy off a flag
+   local sf = map:get_field(10, 10)
+   local hq = player1:place_building("barbarians_headquarters", sf, false, true)
+   local hq_flag = hq.flag
+   local eco = hq_flag.economy
+
+   -- Test illegal parameters
+   assert_error("Nonexisting worker",function() eco:worker_target_quantity("foobar") end)
+   assert_error("Quantity for nonexisting worker",function() eco:worker_target_quantity("foobar", 1) end)
+   assert_error("Negative worker quantity",function() eco:set_worker_target_quantity("barbarians_soldier", -1) end)
+
+   -- Now set and confirm worker quantity
+   quantity = eco:worker_target_quantity("barbarians_soldier")
+   quantity = quantity + 1
+   eco:set_worker_target_quantity("barbarians_soldier", quantity)
+   assert_equal(quantity, eco:worker_target_quantity("barbarians_soldier"))
+   hq_flag:remove()
+end

=== modified file 'test/maps/lua_testsuite.wmf/scripting/gplayer.lua'
--- test/maps/lua_testsuite.wmf/scripting/gplayer.lua	2017-01-17 20:07:46 +0000
+++ test/maps/lua_testsuite.wmf/scripting/gplayer.lua	2017-03-30 10:06:26 +0000
@@ -59,6 +59,30 @@
    assert_equal(true, player1:sees_field(self.f))
 end
 
+-- This test must go last, because we change the state of player1:seen_field.
+function player_vision_tests:test_hide_completely()
+   player1.see_all = true
+   assert_equal(true, player1:sees_field(self.f))
+   player1.see_all = false
+   assert_equal(false, player1:sees_field(self.f))
+
+   player1:hide_fields(self.f:region(1), false)
+   game.desired_speed = 0;
+   assert_equal(false, player1:sees_field(self.f))
+   assert_equal(true, player1:seen_field(self.f))
+
+   player1.see_all = true
+   assert_equal(true, player1:sees_field(self.f))
+   player1.see_all = false
+   assert_equal(false, player1:sees_field(self.f))
+
+   player1:hide_fields(self.f:region(1), true)
+   game.desired_speed = 0;
+   assert_equal(false, player1:sees_field(self.f))
+   assert_equal(false, player1:seen_field(self.f))
+   player1:reveal_fields(self.f:region(1))
+end
+
 
 -- =========================
 -- Forbid & Allow buildings

=== modified file 'test/maps/lua_testsuite.wmf/scripting/init.lua'
--- test/maps/lua_testsuite.wmf/scripting/init.lua	2016-04-12 07:35:33 +0000
+++ test/maps/lua_testsuite.wmf/scripting/init.lua	2017-03-30 10:06:26 +0000
@@ -40,6 +40,7 @@
 if not wl.editor then
    include "map:scripting/game.lua"
 
+   include "map:scripting/geconomy.lua"
    include "map:scripting/gplayer.lua"
    include "map:scripting/gfield.lua"
    include "map:scripting/gplr_access.lua"


Follow ups