← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/bug-1426465-scenario-timings into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/bug-1426465-scenario-timings into lp:widelands.

Commit message:
Tweaked timings in tutorials and scenarios:

- New function set_objective_done that adds a configurable sleep time
  when marking an objective as done
- Barbarian scenario 1: Shifted story messages back to reduce the barrage
  at the start of the scenario.
  Also, more felling axes to make clearing the trees easier.
- Atlantean scenario : Trigger warehouse objective earlier, so we can
  expand faster and have some horses ready when racing for the lake.
- Warfare Tutorial: Build trainingsites concurrently in order to save time.
- Economy tutorial: Sleep longer for the stock window.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1426465 in widelands: "Introduce delay between completion of an objective and the trigger of a dialog popup"
  https://bugs.launchpad.net/widelands/+bug/1426465
  Bug #1623996 in widelands: "Economy tutorial - sleep longer for the Stock"
  https://bugs.launchpad.net/widelands/+bug/1623996

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/bug-1426465-scenario-timings/+merge/311119
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/bug-1426465-scenario-timings into lp:widelands.
=== modified file 'data/campaigns/atl01.wmf/scripting/mission_thread.lua'
--- data/campaigns/atl01.wmf/scripting/mission_thread.lua	2015-11-03 18:52:00 +0000
+++ data/campaigns/atl01.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -18,38 +18,45 @@
 end
 
 function build_warehouse_and_horsefarm()
-   local fields = {
+   -- Sleeps until one of the given fields is owned by p1.
+   local function wait_for_owns_a_field(fields)
+      local fowned = nil
+      while not fowned do
+         for idx, f in ipairs(fields) do
+            if f.owner == p1 then
+               fowned = f
+               break
+            end
+         end
+         sleep(5000)
+      end
+   end
+
+   wait_for_owns_a_field({
+      map:get_field(60, 139),
+      map:get_field(98, 128),
+      map:get_field(120, 126)
+   })
+
+   msg_boxes(horsefarm_and_warehouse_story)
+   local o = add_campaign_objective(obj_horsefarm_and_warehouse)
+   while not check_for_buildings(p1, {
+      atlanteans_horsefarm = 1,
+      atlanteans_warehouse = 1,
+   }) do sleep(2384) end
+   set_objective_done(o)
+
+   -- Now check if the water should rise
+   wait_for_owns_a_field({
       map:get_field(42, 88),
       map:get_field(64, 105),
       map:get_field(93, 89),
       map:get_field(90, 66),
-   }
+   })
 
-   local fowned = nil
-   while not fowned do
-      for idx, f in ipairs(fields) do
-         if f.owner == p1 then
-            fowned = f
-            break
-         end
-      end
-      sleep(3213)
-   end
    -- Has been started from the very beginning
-   expand_objective.done = true
+   set_objective_done(expand_objective)
    let_the_water_rise = true
-
-   local pts = wait_for_roadbuilding_and_scroll(fowned)
-   msg_boxes(horsefarm_and_warehouse_story)
-   -- Go back to where we were
-   timed_scroll(array_reverse(pts))
-
-   local o = add_campaign_objective(obj_horsefarm_and_warehouse)
-   while not check_for_buildings(p1, {
-      atlanteans_horsefarm = 1,
-      atlanteans_warehouse = 1,
-   }) do sleep(2384) end
-   o.done = true
 end
 
 function build_training()
@@ -60,7 +67,7 @@
       atlanteans_dungeon = 1,
       atlanteans_labyrinth = 1
    }) do sleep(3874) end
-   o.done = true
+   set_objective_done(o)
 
    msg_boxes(training_story_end)
 end
@@ -79,7 +86,7 @@
       atlanteans_armorsmithy = 1,
       atlanteans_toolsmithy = 1,
    }) do sleep(3478) end
-   o.done = true
+   set_objective_done(o)
 
    sleep(15 * 60 * 1000) -- sleep a while
    run(build_training)
@@ -105,7 +112,7 @@
       atlanteans_fishbreeders_house = 1,
       atlanteans_smokery = 2,
    }) do sleep(2789) end
-   o.done = true
+   set_objective_done(o)
 
    msg_boxes(food_story_ended_messages)
 end
@@ -122,7 +129,7 @@
       atlanteans_gold_spinning_mill = 1,
       atlanteans_weaving_mill = 1
    }) do sleep(6273) end
-   o.done = true
+   set_objective_done(o)
 
    msg_boxes(spidercloth_story_ended_messages)
 
@@ -140,7 +147,7 @@
       atlanteans_quarry = 1,
       atlanteans_sawmill = 1,
    }) do sleep(3731) end
-   o.done = true
+   set_objective_done(o)
 
    run(make_spidercloth_production)
 

=== modified file 'data/campaigns/bar01.wmf/scripting/mission_thread.lua'
--- data/campaigns/bar01.wmf/scripting/mission_thread.lua	2016-01-28 05:24:34 +0000
+++ data/campaigns/bar01.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -24,26 +24,31 @@
    plr:reveal_fields(al_thunran:region(8))
    message_box_objective(plr, briefing_msg_02) -- Al'thunran
    plr:reveal_fields(grave:region(4))
-   message_box_objective(plr, briefing_msg_03) -- grave
-   message_box_objective(plr, briefing_msg_04)
-
-   message_box_objective(plr, briefing_msg_05)
-   message_box_objective(plr, briefing_msg_06)
-   message_box_objective(plr, briefing_msg_07)
-
+   message_box_objective(plr, briefing_msg_03) -- grave, Boldreth
+   message_box_objective(plr, briefing_msg_04) -- wait
    -- introduction of Khantrukh
    message_box_objective(plr, briefing_msg_08)
 
    message_box_objective(plr, order_msg_ranger)
    local obj = add_campaign_objective(obj_build_rangers)
 
+   -- Try not to interrupt the player actions with a message, so we wait generously
+   sleep(50000)
+   message_box_objective(plr, briefing_msg_05) -- war goes on
+   message_box_objective(plr, briefing_msg_06) -- brothers brought men
+   sleep(50000)
+   message_box_objective(plr, briefing_msg_07) -- still living in huts and barracks
+   sleep(50000)
+   message_box_objective(plr, msg_story_2) -- winter is upon us
+   sleep(10000)
+
    while not check_for_buildings(plr, {barbarians_rangers_hut = 2}) do sleep(500) end
-   obj.done = true
+   set_objective_done(obj)
 
    plr:allow_buildings{"barbarians_sentry", "barbarians_barrier"}
 
-   message_box_objective(plr, order_msg_1)
-   message_box_objective(plr, order_msg_2)
+   message_box_objective(plr, order_msg_1) -- Boldreth, swords rusty
+   message_box_objective(plr, order_msg_2) -- Kantrukh, rocks
 
    -- Reveal the rocks
    local rocks = wl.Game().map:get_field(27, 48)
@@ -57,12 +62,15 @@
    -- Move back
    timed_scroll(array_reverse(way), 10)
 
+   sleep(50000)
+   message_box_objective(plr, msg_story_1)
+
    -- Now, wait till the quarry comes up
    local f = wl.Game().map:get_field(27,48):region(6)
    while not check_for_buildings(plr, { barbarians_quarry = 1 }, f) do
       sleep(5000)
    end
-   obj.done = true
+   set_objective_done(obj)
 
    message_box_objective(plr, order_msg_5_quarry)
 
@@ -98,7 +106,7 @@
    while not check_for_buildings(plr, {barbarians_coalmine = 1, barbarians_ironmine = 1}) do
       sleep(5000)
    end
-   o.done = true
+   set_objective_done(o)
    message_box_objective(plr, order_msg_7_mines_up)
    message_box_objective(plr, order_msg_8_mines_up)
    message_box_objective(plr, order_msg_9_hunter)
@@ -127,8 +135,7 @@
                   and #rv.barbarians_tavern >= 1 then break end
          sleep(5331)
       end
-      obj_bf.done = true
-      sleep(5000)
+      set_objective_done(obj_bf)
       message_box_objective(plr, story_msg4)
    end)
 
@@ -146,7 +153,7 @@
          sleep(4234)
       end
       message_box_objective(plr, order_msg_12_farming_began)
-      obj_farming.done = true
+      set_objective_done(obj_farming)
    end)
 
    -- Enable food production
@@ -171,7 +178,7 @@
    while #plr:get_buildings("barbarians_smelting_works") < 1 do
       sleep(6223)
    end
-   o.done = true
+   set_objective_done(o)
 
    -- Information about making mines deeper
    -- Wait until the player has an experienced worker.
@@ -218,7 +225,7 @@
          end
          sleep(5421)
       end
-      obj.done = true
+      set_objective_done(obj)
       enhance_buildings_done = true
    end)
 
@@ -238,6 +245,7 @@
       end
       sleep(5421)
    end
+   sleep(5000)
 
    message_box_objective(plr, order_msg_16_blackwood)
    plr:allow_buildings{"barbarians_wood_hardener"}
@@ -245,10 +253,10 @@
    -- So that player has really little, but still enough to expand a bit
    local o = add_campaign_objective(obj_better_material_1)
 
-   sleep(30*1000)
+   sleep(50000)
    message_box_objective(plr, story_msg1)
    while #plr:get_buildings("barbarians_wood_hardener") < 1 do sleep(5421) end
-   o.done = true
+   set_objective_done(o)
 
    message_box_objective(plr, order_msg_17_grout)
    plr:allow_buildings{"barbarians_lime_kiln", "barbarians_well", "barbarians_charcoal_kiln"}
@@ -267,7 +275,7 @@
       end
       sleep(5421)
    end
-   o.done = true
+   set_objective_done(o)
 
    message_box_objective(plr, order_msg_18_reed)
    plr:allow_buildings{"barbarians_reed_yard"}
@@ -275,7 +283,7 @@
    while #plr:get_buildings("barbarians_reed_yard") < 1 do sleep(5421) end
 
    message_box_objective(plr, order_msg_19_all_material)
-   o.done = true
+   set_objective_done(o)
 
    build_materials_done = true
 end
@@ -299,23 +307,12 @@
    while not check_for_buildings(plr, { barbarians_cattlefarm = 1 }) do
       sleep(2323)
    end
-   o.done = true
+   set_objective_done(o)
 
    cattle_farm_done = true
 end
 
 
--- ======================
--- Throns story messages
--- ======================
-function story_messages_thread()
-   wake_me(180 * 1000)
-   message_box_objective(plr, msg_story_2)
-
-   wake_me(600 * 1000)
-   message_box_objective(plr, msg_story_1)
-end
-
 -- =================
 -- Mission complete
 -- =================
@@ -333,7 +330,6 @@
 run(introduction_thread)
 run(mines_and_food_thread)
 run(build_materials_thread)
-run(story_messages_thread)
 
 include "map:scripting/secret_village.lua" -- starts the thread
 

=== modified file 'data/campaigns/bar01.wmf/scripting/starting_conditions.lua'
--- data/campaigns/bar01.wmf/scripting/starting_conditions.lua	2015-10-31 12:11:44 +0000
+++ data/campaigns/bar01.wmf/scripting/starting_conditions.lua	2016-11-17 09:50:24 +0000
@@ -46,7 +46,7 @@
    barbarians_gardener = 1,
    barbarians_geologist = 4,
    barbarians_lime_burner = 1,
-   barbarians_lumberjack = 3,
+   barbarians_lumberjack = 6,
    barbarians_miner = 4,
    barbarians_ranger = 2,
    barbarians_stonemason = 2

=== modified file 'data/campaigns/bar01.wmf/scripting/texts.lua'
--- data/campaigns/bar01.wmf/scripting/texts.lua	2016-01-28 05:24:34 +0000
+++ data/campaigns/bar01.wmf/scripting/texts.lua	2016-11-17 09:50:24 +0000
@@ -187,7 +187,7 @@
       -- TRANSLATORS: Thron
       _[[Boldreth, my loyal companion and friend is a source of peace and comfort to me in these dark times. He keeps my spirits high and those of my warriors awake, preventing greed or despair from destroying the bonds between us as well.]]),
    field = grave,
-   position = "topleft"
+   position = "topleft",
 }
 
 
@@ -195,7 +195,8 @@
    title = _"The Story Begins",
    body = thron(
       -- TRANSLATORS: Thron
-      _[[As father told me, there are times to fight and times to lie and wait, trying not to fall asleep or die before the right time comes. And so I do wait.]])
+      _[[As father told me, there are times to fight and times to lie and wait, trying not to fall asleep or die before the right time comes. And so I do wait.]]),
+   position = "topleft",
 }
 
 
@@ -207,7 +208,8 @@
       .. paragraphdivider() ..
       -- TRANSLATORS: Thron
       _([[The stories they tell about the deeds of our kin are sad to hear. I’ve spent nights lying awake, restless, more tired than I ever believed one could be. Yet whenever I close my eyes, I see the fortress my father built consumed by flames. The Throne Among the Trees, the symbol of unity and peace among our kin, became the wedge that drives us apart.]])),
-   field = sf -- scroll back when showing this and the next few message boxes
+   field = al_thunran,
+   position = "topleft",
 }
 
 
@@ -218,7 +220,8 @@
       _([[Today my hunters brought men, women and little children before me who had hidden out in the forests, trying to escape the war, hate and revenge that rage among the tribes fighting each other like in olden times, when we were no more but wild beasts driven and controlled by instincts. None of my brothers will ever gain and hold control over the wooden throne, none of the tribes will be strong enough to subdue the other. There will be no end to this slaughter, unless… is this it? As father told me?]])
       .. paragraphdivider() ..
       -- TRANSLATORS: Thron
-      _([[To rise against whoever threatens our very existence, even though it may be one of your own blood or mind?]]))
+      _([[To rise against whoever threatens our very existence, even though it may be one of your own blood or mind?]])),
+   field = sf,
 }
 
 
@@ -240,7 +243,8 @@
       _[[Hail, chieftain. I am Khantrukh and have seen many winters pass. Please allow me to aid you with my counsel through these darkened days.]]
       .. paragraphdivider() ..
       -- TRANSLATORS: Khantrukh
-      _[[Only the gods know for how long we have to remain hidden here. The warriors hope we may march back gloriously any day now, but I strongly doubt that will happen soon. And the days are short and cold…]])
+      _[[Only the gods know for how long we have to remain hidden here. The warriors hope we may march back gloriously any day now, but I strongly doubt that will happen soon. And the days are short and cold…]]),
+   field = sf -- scroll back when showing this and the next few message boxes
 }
 
 

=== modified file 'data/campaigns/bar02.wmf/scripting/mission_thread.lua'
--- data/campaigns/bar02.wmf/scripting/mission_thread.lua	2016-05-06 09:44:37 +0000
+++ data/campaigns/bar02.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -30,7 +30,7 @@
    local o = add_campaign_objective(obj_build_cattlefarm)
    while not check_for_buildings(p1, {barbarians_cattlefarm = 1}) do
       sleep(1223) end
-   o.done = true
+   set_objective_done(o)
 
 end
 
@@ -48,7 +48,7 @@
    while not check_for_buildings(p1, {barbarians_sentry=1}, game.map:get_field(57,36):region(6)) do
       sleep(1500)
    end
-   o.done = true
+   set_objective_done(o)
    sleep(3000)
 
    campaign_message_box(briefing_msg_1)
@@ -73,7 +73,7 @@
          barbarians_farm = 1,
          barbarians_bakery = 1,
       }) do sleep(3413) end
-   o.done = true
+   set_objective_done(o)
    campaign_message_box(story_note_1)
 
    sleep(600000)  -- 10 minutes
@@ -111,7 +111,7 @@
    p1:hide_fields(fields)
 
    while not check_for_buildings(p1, {barbarians_tower=1}) do sleep(2341) end
-   o.done = true
+   set_objective_done(o)
    campaign_message_box(order_msg_3_explore_further)
    -- "explore further" is active untill "Boldreth shout out", so the player always has one open objectve.
    exploration_objective = add_campaign_objective(obj_explore_further)
@@ -178,7 +178,7 @@
       end
       sleep(4139)
    end
-   o.done = true
+   set_objective_done(o)
    campaign_message_box(story_note_2)
 
    sleep(100000)
@@ -211,7 +211,7 @@
    while not check_for_buildings(p1, {barbarians_trainingcamp = 1, barbarians_battlearena = 1}) do
       sleep(6523)
    end
-   o.done = true
+   set_objective_done(o)
 end
 function check_weapon_productions_obj(o)
    while true do
@@ -225,15 +225,15 @@
       end
       sleep(6523)
    end
-   o.done = true
+   set_objective_done(o)
 end
 function check_warehouse_obj(o)
    while not check_for_buildings(p1, {barbarians_warehouse = 1}) do sleep(3827) end
-   o.done = true
+   set_objective_done(o)
 end
 function check_helmsmithy_obj(o)
    while not check_for_buildings(p1, {barbarians_helmsmithy = 1}) do sleep(3827) end
-   o.done = true
+   set_objective_done(o)
 end
 
 function fortress()
@@ -247,7 +247,7 @@
 
    while #p1:get_buildings("barbarians_fortress") == 0 do sleep(6523) end
 
-   o.done = true
+   set_objective_done(o)
    campaign_message_box(story_note_3)
 end
 
@@ -294,7 +294,7 @@
       )
    do sleep(7829) end
    -- "explore further" is done
-   exploration_objective.done = true
+   set_objective_done(exploration_objective)
 
    campaign_message_box(order_msg_7_destroy_kalitaths_army)
    local o = add_campaign_objective(obj_destroy_kalitaths_army)
@@ -302,7 +302,7 @@
    while not check_player_completely_defeated(p2) do
         sleep(7837)
    end
-   o.done = true
+   set_objective_done(o)
 end
 
 function renegade_fortresses()
@@ -345,7 +345,7 @@
       sleep(6733)
    end
 
-   o.done = true
+   set_objective_done(o)
 end
 
 function mission_complete()

=== modified file 'data/campaigns/emp01.wmf/scripting/mission_thread.lua'
--- data/campaigns/emp01.wmf/scripting/mission_thread.lua	2016-01-28 05:24:34 +0000
+++ data/campaigns/emp01.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -30,7 +30,7 @@
    p1:allow_buildings{"empire_blockhouse"}
    local o = add_campaign_objective(obj_build_blockhouse)
    while #p1:get_buildings("empire_blockhouse") < 1 do sleep(3249) end
-   o.done = true
+   set_objective_done(o)
 
    -- Blockhouse is completed now
    campaign_message_box(saledus_2)
@@ -38,7 +38,7 @@
    o = add_campaign_objective(obj_build_lumberjack)
    campaign_message_box(amalea_1)
    while #p1:get_buildings("empire_lumberjacks_house") < 1 do sleep(3249) end
-   o.done = true
+   set_objective_done(o)
 
    -- Lumberjack is now build
    campaign_message_box(amalea_2)
@@ -46,14 +46,14 @@
    o = add_campaign_objective(obj_build_sawmill_and_lumberjacks)
    while not check_for_buildings(p1, { empire_lumberjacks_house = 3, empire_sawmill = 1})
       do sleep(2343) end
-   o.done = true
+   set_objective_done(o)
 
    -- Now the lady demands a forester after having us cut down the whole forest.
    campaign_message_box(amalea_3)
    o = add_campaign_objective(obj_build_forester)
    p1:allow_buildings{"empire_foresters_house"}
    while not check_for_buildings(p1, { empire_foresters_house = 1 }) do sleep(2434) end
-   o.done = true
+   set_objective_done(o)
 
 
    -- Now a quarry
@@ -61,7 +61,7 @@
    o = add_campaign_objective(obj_build_quarry)
    p1:allow_buildings{"empire_quarry"}
    while not check_for_buildings(p1, { empire_quarry = 1 }) do sleep(2434) end
-   o.done = true
+   set_objective_done(o)
 
    -- All buildings done. Got home
    campaign_message_box(saledus_4)

=== modified file 'data/campaigns/emp02.wmf/scripting/mission_thread.lua'
--- data/campaigns/emp02.wmf/scripting/mission_thread.lua	2016-01-28 05:24:34 +0000
+++ data/campaigns/emp02.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -28,7 +28,7 @@
       }) do sleep(2342) end
 
       campaign_message_box(diary_page_6)
-      o_woodeconomy.done = true
+      set_objective_done(o_woodeconomy)
    end)
 
 
@@ -39,7 +39,7 @@
    -- Check for completeness of the quarry
    run(function()
       while not check_for_buildings(p1, {empire_quarry=1}) do sleep(3423) end
-      o_quarry.done = true
+      set_objective_done(o_quarry)
 
       campaign_message_box(diary_page_7)
    end)
@@ -100,7 +100,7 @@
           #rv.empire_piggery + #rv.empire_bakery) > 0 then break end
       sleep(4857)
    end
-   o.done = true
+   set_objective_done(o)
 end
 
 function mining_infrastructure()
@@ -159,7 +159,7 @@
          #rv.empire_weaponsmithy > 0 then break end
       sleep(4948)
    end
-   o.done = true
+   set_objective_done(o)
    mining_infrastructure_done = true
 end
 
@@ -182,7 +182,7 @@
 
    -- sleep while not owning 26, 21
    while wl.Game().map:get_field(26,21).owner ~= p1 do sleep(3243) end
-   o.done = true
+   set_objective_done(o)
 
    -- Marble Mountains
    local marblemountains = wl.Game().map:get_field(35,19)
@@ -195,7 +195,7 @@
    p1:allow_buildings{"empire_marblemine", "empire_marblemine_deep"}
    o = add_campaign_objective(obj_build_marblemine)
    run(function() while not check_for_buildings(p1, {empire_marblemine = 1})
-      do sleep(2133) end  o.done = true end)
+      do sleep(2133) end set_objective_done(o, 0) end)
 
    -- Go back to where we were
    timed_scroll(array_reverse(pts))
@@ -239,7 +239,7 @@
       end
       sleep(2342)
    end
-   o.done = true
+   set_objective_done(o)
 
    -- Wait till the mining infrastructure is also up
    while not mining_infrastructure_done do
@@ -254,7 +254,7 @@
       wl.Game().map:get_field(60,65):region(6))
    do sleep(2435) end
 
-   o.done = true
+   set_objective_done(o)
 
    -- Show victory message
    campaign_message_box(diary_page_10)

=== modified file 'data/campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua'
--- data/campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua	2016-05-14 16:18:25 +0000
+++ data/campaigns/tutorial01_basic_control.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -17,11 +17,9 @@
    while not wl.ui.MapView().buildhelp do
       sleep(200)
    end
-   o.done = true
+   set_objective_done(o, 500)
    wl.ui.MapView():abort_road_building()
 
-   sleep(500)
-
    build_lumberjack()
 end
 
@@ -86,9 +84,7 @@
 
       -- Wait for flag
       while not (f.immovable and f.immovable.descr.type_name == "flag") do sleep(300) end
-      o.done = true
-
-      sleep(300)
+      set_objective_done(o, 300)
 
       message_box_objective(plr, lumberjack_message_06)
    else
@@ -120,14 +116,12 @@
    end
 
    _wait_for_move()
-   o.done = true
-   sleep(3000) -- Give the player a chance to try this some more
+   set_objective_done(o)
 
    o = message_box_objective(plr, tell_about_right_drag_move)
 
    _wait_for_move()
-   o.done = true
-   sleep(3000) -- Give the player a chance to try this some more
+   set_objective_done(o)
 
    o = message_box_objective(plr, tell_about_minimap)
 
@@ -135,8 +129,7 @@
    while not wl.ui.MapView().windows.minimap do sleep(100) end
    while wl.ui.MapView().windows.minimap do sleep(100) end
 
-   o.done = true
-   sleep(500)
+   set_objective_done(o, 500)
 
    message_box_objective(plr, congratulate_and_on_to_quarry)
 
@@ -161,7 +154,7 @@
    -- Wait for the constructionsite to be placed
    while not cs do sleep(200) end
 
-   o.done = true
+   set_objective_done(o, 0)
    register_immovable_as_allowed(cs)
 
    local function _rip_road()
@@ -238,7 +231,7 @@
    census_and_statistics()
 
    while #plr:get_buildings("barbarians_quarry") < 2 do sleep(1400) end
-   o.done = true
+   set_objective_done(o, 0)
 
    messages()
 end
@@ -271,7 +264,7 @@
       if not second_quarry_field.immovable then message_box_objective(plr,quarry_illegally_destroyed) return end
    end
 
-   o.done = true
+   set_objective_done(o, 0)
    register_immovable_as_allowed(cs)
 end
 
@@ -310,15 +303,13 @@
    local o = add_campaign_objective(teaching_about_messages)
 
    while #plr.inbox > 0 do sleep(200) end
-   o.done = true
-
-   sleep(500)
+   set_objective_done(o, 500)
 
    local o = message_box_objective(plr, closing_msg_window_00)
 
    -- Wait for messages window to close
    while wl.ui.MapView().windows.messages do sleep(300) end
-   o.done = true
+   set_objective_done(o, 0)
 
    message_box_objective(plr, closing_msg_window_01)
 
@@ -351,9 +342,7 @@
    terminate_bad_boy_sentinel = true
 
    while #plr:get_buildings("barbarians_quarry") > 0 do sleep(200) end
-   o.done = true
-
-   sleep(3000)
+   set_objective_done(o)
 
    expansion()
 end
@@ -382,8 +371,7 @@
       sleep(500)
    end
 
-   o.done = true
-   sleep(4000)
+   set_objective_done(o)
    message_box_objective(plr, military_building_finished)
 
    conclusion()

=== modified file 'data/campaigns/tutorial02_warfare.wmf/scripting/mission_thread.lua'
--- data/campaigns/tutorial02_warfare.wmf/scripting/mission_thread.lua	2015-10-31 12:11:44 +0000
+++ data/campaigns/tutorial02_warfare.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -9,35 +9,39 @@
    training()
 end
 
+function training2()
+   -- Teach about trainingsites and soldiers' abilities - concurrent part 2
+   sleep(2*60*1000)
+   o = message_box_objective(plr, trainingcamp1)
+   while #plr:get_buildings("barbarians_trainingcamp") == 0 do sleep(500) end
+   set_objective_done(o)
+   message_box_objective(plr, trainingcamp2)
+end
+
 function training()
    -- Teach about trainingsites and soldiers' abilities
    sleep(5000) -- to let soldiers walk
 
    message_box_objective(plr, abilities)
    local o = message_box_objective(plr, battlearena1)
+   run(training2)
+
    while #plr:get_buildings("barbarians_battlearena") == 0 do sleep(500) end
-   o.done = true
+   set_objective_done(o, 0)
    message_box_objective(plr, battlearena2)
-
-   o = message_box_objective(plr, trainingcamp1)
-   while #plr:get_buildings("barbarians_trainingcamp") == 0 do sleep(500) end
-   o.done = true
-   message_box_objective(plr, trainingcamp2)
-
-   sleep(300)
-
-   military_buildings()
 end
 
 function military_buildings()
+   while #plr:get_buildings("barbarians_battlearena") == 0 or
+      #plr:get_buildings("barbarians_trainingcamp") == 0
+      do sleep(500)
+   end
    message_box_objective(plr, heroes_rookies)
    message_box_objective(plr, soldier_capacity)
    local o = message_box_objective(plr, dismantle)
 
    while #plr:get_buildings("barbarians_sentry") > 1 do sleep(200) end
-   o.done = true
-
-   sleep(2000)
+   set_objective_done(o)
 
    enhance_fortress()
 end
@@ -49,7 +53,7 @@
    local o = message_box_objective(plr, fortress_enhancement)
    while not (citadel_field.immovable and
       citadel_field.immovable.descr.name == "barbarians_citadel") do sleep(800) end
-   o.done = true
+   set_objective_done(o, 0)
 
    create_enemy()
 
@@ -91,14 +95,14 @@
    while #plr2:get_buildings("empire_headquarters") > 0 do
       sleep(3000)
    end
-   o.done = true
+   set_objective_done(o)
 
    conclusion()
 end
 
 function conclusion()
-   sleep(4000)
    message_box_objective(plr, conclude_tutorial)
 end
 
 run(intro)
+run (military_buildings)

=== modified file 'data/campaigns/tutorial03_seafaring.wmf/scripting/mission_thread.lua'
--- data/campaigns/tutorial03_seafaring.wmf/scripting/mission_thread.lua	2016-08-03 10:20:20 +0000
+++ data/campaigns/tutorial03_seafaring.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -21,7 +21,7 @@
    local o = message_box_objective(plr, tell_about_port_building)
 
    while #plr:get_buildings("atlanteans_port") < 2 do sleep(200) end
-   o.done = true
+   set_objective_done(o)
 
    build_ships()
 end
@@ -32,7 +32,7 @@
    plr:allow_buildings{"atlanteans_shipyard"}
 
    while #plr:get_buildings("atlanteans_shipyard") < 1 do sleep(200) end
-   o.done = true
+   set_objective_done(o)
 
    local o = message_box_objective(plr, tell_about_ships)
 
@@ -40,7 +40,7 @@
    while #plr:get_ships() < 1 do sleep(30*1000) end
    sleep(5*60*1000)
 
-   o.done = true
+   set_objective_done(o)
 
    expedition()
 end
@@ -58,12 +58,12 @@
    end
 
    while not _ship_ready_for_expedition() do sleep(1000) end
-   o.done = true
+   set_objective_done(o)
 
    o = message_box_objective(plr, expedition3)
 
    while #plr:get_buildings("atlanteans_port") < 3 do sleep(200) end
-   o.done = true
+   set_objective_done(o)
 
    -- places 5 signs with iron to show the player he really found some iron ore
    local fields = map:get_field(97,35):region(3)

=== modified file 'data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua'
--- data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua	2015-10-31 12:11:44 +0000
+++ data/campaigns/tutorial04_economy.wmf/scripting/mission_thread.lua	2016-11-17 09:50:24 +0000
@@ -13,16 +13,15 @@
 function burn_tavern_down()
    sleep(500)
    scroll_smoothly_to(tavern_field)
-   sleep(250)
+   sleep(500)
    tavern_field.immovable:destroy()
-   sleep(50)
+   sleep(500)
    message_box_objective(plr, tavern_burnt_down)
-   sleep(2000)
+   sleep(500)
    local o = message_box_objective(plr, building_stat)
    while not mv.windows.building_statistics do sleep(100) end
-   o.done = true
+   set_objective_done(o, wl.Game().real_speed)
 
-   sleep(wl.Game().real_speed) -- The building statistics window needs some time to build up
    o = message_box_objective(plr,explain_building_stat)
    -- We cannot create several objectives with the same name. Therefore, we create o2 here once and change its visibility
    local o2 = add_campaign_objective(reopen_building_stat_obj)
@@ -39,28 +38,26 @@
       sleep(200)
    end
    while mv.windows.building_statistics do sleep(100) end
-   o.done = true
+   set_objective_done(o, 0)
 
-   sleep(2000)
    o = message_box_objective(plr, inventory1)
    while not mv.windows.stock_menu do sleep(200) end
-   o.done = true
+   set_objective_done(o, wl.Game().real_speed)
 
    o = message_box_objective(plr, inventory2)
    -- We cannot create several objectives with the same name. Therefore, we create o2 here once and change its visibility
    o2 = add_campaign_objective(reopen_stock_menu_obj)
    o2.visible = false
-   while not o.done do
+   while not mv.windows.stock_menu.tabs["wares_in_warehouses"].active do
       if not mv.windows.stock_menu then
          o2.visible = true
          message_box_objective(plr, reopen_stock_menu)
          while not mv.windows.stock_menu do sleep(200) end
          o2.visible = false
       end
-      if mv.windows.stock_menu.tabs["wares_in_warehouses"].active then o.done = true end
       sleep(200)
    end
-
+   set_objective_done(o, 0)
    message_box_objective(plr, inventory3)
 
    sleep(2000)
@@ -70,57 +67,54 @@
    message_box_objective(plr, ware_encyclopedia) -- a small insert
 
    while #plr:get_buildings("empire_tavern") < 2 do sleep(500) end
-   o.done = true
+   set_objective_done(o, 0)
 
    plan_the_future()
 end
 
 function plan_the_future()
-   sleep(2000)
    message_box_objective(plr, building_priority_settings)
    sleep(30*1000) -- give the user time to try it out
 
    local o = message_box_objective(plr, ware_stats1)
    while not mv.windows.ware_statistics do sleep(200) end
-   o.done = true
+   set_objective_done(o, 0)
 
    o = message_box_objective(plr, ware_stats2)
    local o2 = add_campaign_objective(reopen_ware_stats1_obj)
    o2.visible = false
-   while not o.done do
+   while not mv.windows.ware_statistics.tabs["economy_health"].active do
       if not mv.windows.ware_statistics then
          o2.visible = true
          message_box_objective(plr, reopen_ware_stats1)
          while not mv.windows.ware_statistics do sleep(200) end
          o2.visible = false
       end
-      if mv.windows.ware_statistics.tabs["economy_health"].active then o.done = true end
       sleep(200)
    end
+   set_objective_done(o, 0)
 
    o = message_box_objective(plr, ware_stats3)
    o2 = add_campaign_objective(reopen_ware_stats2_obj)
    o2.visible = false
-   while not o.done do
+   while not mv.windows.ware_statistics.tabs["stock"].active  do
       if not mv.windows.ware_statistics then
          o2.visible = true
          message_box_objective(plr, reopen_ware_stats2)
          while not mv.windows.ware_statistics do sleep(200) end
          o2.visible = false
       end
-      if mv.windows.ware_statistics.tabs["stock"].active then o.done = true end
       sleep(200)
    end
+   set_objective_done(o, 0)
 
    o = message_box_objective(plr, ware_stats4)
    while mv.windows.ware_statistics do sleep(500) end
-   o.done = true
-
-   sleep(2000)
+   set_objective_done(o)
 
    o = message_box_objective(plr, economy_settings1)
    while not mv.windows.economy_options do sleep(200) end
-   o.done = true
+   set_objective_done(o, 0)
    message_box_objective(plr, economy_settings2)
    o = message_box_objective(plr, economy_settings3)
 
@@ -141,7 +135,7 @@
       end
       sleep(500)
    end
-   o.done = true
+   set_objective_done(o)
 
    -- if the minimum_storage_per_warehouse feature is introduced, use the gold mountain to the northeast for explanation
    conclude()

=== modified file 'data/scripting/messages.lua'
--- data/scripting/messages.lua	2016-01-28 05:24:34 +0000
+++ data/scripting/messages.lua	2016-11-17 09:50:24 +0000
@@ -69,6 +69,7 @@
    message_box(wl.Game().players[1], message.title, message.body, message)
 end
 
+
 -- RST
 -- .. function:: add_campaign_objective(objective)
 --
@@ -87,6 +88,24 @@
 end
 
 -- RST
+-- .. function:: set_objective_done(objective[, sleeptime])
+--
+--    Sets an objectve as done and sleeps for a bit.
+--
+--    :arg objective: The objective to be marked as done.
+--    :arg sleeptime: The milliseconds to sleep. Defaults to 3000.
+--
+function set_objective_done(objective, sleeptime)
+   objective.done = true
+   if not sleeptime then
+      sleep(3000)
+   else
+      sleep(sleeptime)
+   end
+end
+
+
+-- RST
 -- .. function:: message_box_objective(player, message)
 --
 --    Calls message_box(player, message.title, message.body, message). Also adds an objective defined in obj_name, obj_title and obj_body.


Follow ups