widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #10946
[Merge] lp:~widelands-dev/widelands/dynamic_tribe_loading into lp:widelands
GunChleoc has proposed merging lp:~widelands-dev/widelands/dynamic_tribe_loading into lp:widelands.
Commit message:
Dynamic loading of the tribes' map objects and of custom scenario tribe objects:
- Simplified tribes/init.lua: The tribe directory is now walked automatically, without the need of manually getting the load order right. Missing prerequisite map objects are parsed during postload.
- If scripting/tribes/init.lua exists in a map, run it to load custom tribe objects when starting a new scenario. So far, only buildings are supported via a new function Tribes::add_custom_building{table} in lua_root.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #1705950 in widelands: "empire mission 4"
https://bugs.launchpad.net/widelands/+bug/1705950
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/dynamic_tribe_loading/+merge/329198
Reworked the tribe loading to make it more moddable. I'd like this branch to have priority, because it affects hessenfarmer's work on the Empire 4 scenario.
An adjusted version of the new scenario for testing is available in https://code.launchpad.net/~widelands-dev/widelands/dynamic_tribe_loading_datadir
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/dynamic_tribe_loading into lp:widelands.
=== modified file 'data/tribes/init.lua'
--- data/tribes/init.lua 2017-02-12 09:10:57 +0000
+++ data/tribes/init.lua 2017-08-17 11:49:32 +0000
@@ -11,12 +11,33 @@
--
-- Basic load order (first wares, then immovables etc.) is important,
-- because checks will be made in C++.
--- Also, enhanced/upgraded units need to come before their basic units.
--
tribes = wl.Tribes()
include "scripting/mapobjects.lua"
+-- Load all init.lua files in the given table of directory names
+function load_directories(directories)
+ -- Helper function to check for file name endings
+ function string.ends(haystack, needle)
+ return needle == '' or string.sub(haystack, -string.len(needle)) == needle
+ end
+
+ while #directories > 0 do
+ local filepath = directories[1]
+ table.remove(directories, 1)
+ if path.is_directory(filepath) then
+ for idx, listed_path in ipairs(path.list_directory(filepath)) do
+ if path.is_directory(listed_path) then
+ table.insert(directories, listed_path)
+ elseif string.ends(listed_path , "init.lua") then
+ include(listed_path)
+ end
+ end
+ end
+ end
+end
+
print("┏━ Running Lua for tribes:")
print_loading_message("┗━ took", function()
@@ -25,9 +46,7 @@
-- ===================================
print_loading_message("┃ Ships", function()
- include "tribes/ships/atlanteans/init.lua"
- include "tribes/ships/barbarians/init.lua"
- include "tribes/ships/empire/init.lua"
+ load_directories({"tribes/ships"})
end)
-- ===================================
@@ -35,91 +54,7 @@
-- ===================================
print_loading_message("┃ Wares", function()
- include "tribes/wares/armor/init.lua"
- include "tribes/wares/armor_chain/init.lua"
- include "tribes/wares/armor_gilded/init.lua"
- include "tribes/wares/armor_helmet/init.lua"
- include "tribes/wares/ax/init.lua"
- include "tribes/wares/ax_battle/init.lua"
- include "tribes/wares/ax_broad/init.lua"
- include "tribes/wares/ax_bronze/init.lua"
- include "tribes/wares/ax_sharp/init.lua"
- include "tribes/wares/ax_warriors/init.lua"
- include "tribes/wares/basket/init.lua"
- include "tribes/wares/beer/init.lua"
- include "tribes/wares/beer_strong/init.lua"
- include "tribes/wares/blackroot/init.lua"
- include "tribes/wares/blackroot_flour/init.lua"
- include "tribes/wares/blackwood/init.lua"
- include "tribes/wares/bread_atlanteans/init.lua"
- include "tribes/wares/bread_barbarians/init.lua"
- include "tribes/wares/bread_empire/init.lua"
- include "tribes/wares/bread_paddle/init.lua"
- include "tribes/wares/buckets/init.lua"
- include "tribes/wares/cloth/init.lua"
- include "tribes/wares/coal/init.lua"
- include "tribes/wares/corn/init.lua"
- include "tribes/wares/cornmeal/init.lua"
- include "tribes/wares/diamond/init.lua"
- include "tribes/wares/felling_ax/init.lua"
- include "tribes/wares/fire_tongs/init.lua"
- include "tribes/wares/fish/init.lua"
- include "tribes/wares/fishing_net/init.lua"
- include "tribes/wares/fishing_rod/init.lua"
- include "tribes/wares/flour/init.lua"
- include "tribes/wares/gold/init.lua"
- include "tribes/wares/gold_ore/init.lua"
- include "tribes/wares/gold_thread/init.lua"
- include "tribes/wares/granite/init.lua"
- include "tribes/wares/grape/init.lua"
- include "tribes/wares/grout/init.lua"
- include "tribes/wares/hammer/init.lua"
- include "tribes/wares/helmet/init.lua"
- include "tribes/wares/helmet_mask/init.lua"
- include "tribes/wares/helmet_warhelm/init.lua"
- include "tribes/wares/hook_pole/init.lua"
- include "tribes/wares/hunting_bow/init.lua"
- include "tribes/wares/hunting_spear/init.lua"
- include "tribes/wares/iron/init.lua"
- include "tribes/wares/iron_ore/init.lua"
- include "tribes/wares/kitchen_tools/init.lua"
- include "tribes/wares/log/init.lua"
- include "tribes/wares/marble/init.lua"
- include "tribes/wares/marble_column/init.lua"
- include "tribes/wares/meal/init.lua"
- include "tribes/wares/meat/init.lua"
- include "tribes/wares/milking_tongs/init.lua"
- include "tribes/wares/pick/init.lua"
- include "tribes/wares/planks/init.lua"
- include "tribes/wares/quartz/init.lua"
- include "tribes/wares/ration/init.lua"
- include "tribes/wares/saw/init.lua"
- include "tribes/wares/scythe/init.lua"
- include "tribes/wares/shield_advanced/init.lua"
- include "tribes/wares/shield_steel/init.lua"
- include "tribes/wares/shovel/init.lua"
- include "tribes/wares/smoked_fish/init.lua"
- include "tribes/wares/smoked_meat/init.lua"
- include "tribes/wares/snack/init.lua"
- include "tribes/wares/spear/init.lua"
- include "tribes/wares/spear_advanced/init.lua"
- include "tribes/wares/spear_heavy/init.lua"
- include "tribes/wares/spear_war/init.lua"
- include "tribes/wares/spear_wooden/init.lua"
- include "tribes/wares/spidercloth/init.lua"
- include "tribes/wares/spider_silk/init.lua"
- include "tribes/wares/tabard/init.lua"
- include "tribes/wares/tabard_golden/init.lua"
- include "tribes/wares/thatch_reed/init.lua"
- include "tribes/wares/trident_double/init.lua"
- include "tribes/wares/trident_heavy_double/init.lua"
- include "tribes/wares/trident_light/init.lua"
- include "tribes/wares/trident_long/init.lua"
- include "tribes/wares/trident_steel/init.lua"
- include "tribes/wares/water/init.lua"
- include "tribes/wares/wheat/init.lua"
- include "tribes/wares/wine/init.lua"
- include "tribes/wares/wool/init.lua"
+ load_directories({"tribes/wares"})
end)
-- ===================================
@@ -127,44 +62,7 @@
-- ===================================
print_loading_message("┃ Immovables", function()
- include "tribes/immovables/ashes/init.lua"
- include "tribes/immovables/blackrootfield_harvested/init.lua"
- include "tribes/immovables/blackrootfield_medium/init.lua"
- include "tribes/immovables/blackrootfield_ripe/init.lua"
- include "tribes/immovables/blackrootfield_small/init.lua"
- include "tribes/immovables/blackrootfield_tiny/init.lua"
- include "tribes/immovables/cornfield_harvested/init.lua"
- include "tribes/immovables/cornfield_medium/init.lua"
- include "tribes/immovables/cornfield_ripe/init.lua"
- include "tribes/immovables/cornfield_small/init.lua"
- include "tribes/immovables/cornfield_tiny/init.lua"
- include "tribes/immovables/destroyed_building/init.lua"
- include "tribes/immovables/field_harvested/init.lua"
- include "tribes/immovables/field_medium/init.lua"
- include "tribes/immovables/field_ripe/init.lua"
- include "tribes/immovables/field_small/init.lua"
- include "tribes/immovables/field_tiny/init.lua"
- include "tribes/immovables/grapevine_medium/init.lua"
- include "tribes/immovables/grapevine_ripe/init.lua"
- include "tribes/immovables/grapevine_small/init.lua"
- include "tribes/immovables/grapevine_tiny/init.lua"
- include "tribes/immovables/reed_medium/init.lua"
- include "tribes/immovables/reed_ripe/init.lua"
- include "tribes/immovables/reed_small/init.lua"
- include "tribes/immovables/reed_tiny/init.lua"
- include "tribes/immovables/resi_coal1/init.lua"
- include "tribes/immovables/resi_coal2/init.lua"
- include "tribes/immovables/resi_gold1/init.lua"
- include "tribes/immovables/resi_gold2/init.lua"
- include "tribes/immovables/resi_iron1/init.lua"
- include "tribes/immovables/resi_iron2/init.lua"
- include "tribes/immovables/resi_none/init.lua"
- include "tribes/immovables/resi_stones1/init.lua"
- include "tribes/immovables/resi_stones2/init.lua"
- include "tribes/immovables/resi_water1/init.lua"
- include "tribes/immovables/shipconstruction_atlanteans/init.lua"
- include "tribes/immovables/shipconstruction_barbarians/init.lua"
- include "tribes/immovables/shipconstruction_empire/init.lua"
+ load_directories({"tribes/immovables"})
end)
-- ===================================
@@ -172,103 +70,7 @@
-- ===================================
print_loading_message("┃ Workers", function()
- include "tribes/workers/atlanteans/carrier/init.lua"
- include "tribes/workers/atlanteans/armorsmith/init.lua"
- include "tribes/workers/atlanteans/baker/init.lua"
- include "tribes/workers/atlanteans/blackroot_farmer/init.lua"
- include "tribes/workers/atlanteans/builder/init.lua"
- include "tribes/workers/atlanteans/charcoal_burner/init.lua"
- include "tribes/workers/atlanteans/farmer/init.lua"
- include "tribes/workers/atlanteans/fishbreeder/init.lua"
- include "tribes/workers/atlanteans/fisher/init.lua"
- include "tribes/workers/atlanteans/forester/init.lua"
- include "tribes/workers/atlanteans/geologist/init.lua"
- include "tribes/workers/atlanteans/horse/init.lua"
- include "tribes/workers/atlanteans/horsebreeder/init.lua"
- include "tribes/workers/atlanteans/hunter/init.lua"
- include "tribes/workers/atlanteans/miller/init.lua"
- include "tribes/workers/atlanteans/miner/init.lua"
- include "tribes/workers/atlanteans/recruit/init.lua"
- include "tribes/workers/atlanteans/sawyer/init.lua"
- include "tribes/workers/atlanteans/scout/init.lua"
- include "tribes/workers/atlanteans/shipwright/init.lua"
- include "tribes/workers/atlanteans/smelter/init.lua"
- include "tribes/workers/atlanteans/smoker/init.lua"
- include "tribes/workers/atlanteans/soldier/init.lua"
- include "tribes/workers/atlanteans/spiderbreeder/init.lua"
- include "tribes/workers/atlanteans/stonecutter/init.lua"
- include "tribes/workers/atlanteans/toolsmith/init.lua"
- include "tribes/workers/atlanteans/trainer/init.lua"
- include "tribes/workers/atlanteans/weaponsmith/init.lua"
- include "tribes/workers/atlanteans/weaver/init.lua"
- include "tribes/workers/atlanteans/woodcutter/init.lua"
-
- include "tribes/workers/barbarians/carrier/init.lua"
- include "tribes/workers/barbarians/baker/init.lua"
- include "tribes/workers/barbarians/blacksmith_master/init.lua"
- include "tribes/workers/barbarians/blacksmith/init.lua"
- include "tribes/workers/barbarians/brewer_master/init.lua"
- include "tribes/workers/barbarians/brewer/init.lua"
- include "tribes/workers/barbarians/builder/init.lua"
- include "tribes/workers/barbarians/cattlebreeder/init.lua"
- include "tribes/workers/barbarians/charcoal_burner/init.lua"
- include "tribes/workers/barbarians/farmer/init.lua"
- include "tribes/workers/barbarians/fisher/init.lua"
- include "tribes/workers/barbarians/gamekeeper/init.lua"
- include "tribes/workers/barbarians/gardener/init.lua"
- include "tribes/workers/barbarians/geologist/init.lua"
- include "tribes/workers/barbarians/helmsmith/init.lua"
- include "tribes/workers/barbarians/hunter/init.lua"
- include "tribes/workers/barbarians/innkeeper/init.lua"
- include "tribes/workers/barbarians/lime_burner/init.lua"
- include "tribes/workers/barbarians/lumberjack/init.lua"
- include "tribes/workers/barbarians/miner_master/init.lua"
- include "tribes/workers/barbarians/miner_chief/init.lua"
- include "tribes/workers/barbarians/miner/init.lua"
- include "tribes/workers/barbarians/ox/init.lua"
- include "tribes/workers/barbarians/ranger/init.lua"
- include "tribes/workers/barbarians/recruit/init.lua"
- include "tribes/workers/barbarians/scout/init.lua"
- include "tribes/workers/barbarians/shipwright/init.lua"
- include "tribes/workers/barbarians/smelter/init.lua"
- include "tribes/workers/barbarians/soldier/init.lua"
- include "tribes/workers/barbarians/stonemason/init.lua"
- include "tribes/workers/barbarians/trainer/init.lua"
- include "tribes/workers/barbarians/weaver/init.lua"
-
- include "tribes/workers/empire/carrier/init.lua"
- include "tribes/workers/empire/armorsmith/init.lua"
- include "tribes/workers/empire/baker/init.lua"
- include "tribes/workers/empire/brewer/init.lua"
- include "tribes/workers/empire/builder/init.lua"
- include "tribes/workers/empire/carpenter/init.lua"
- include "tribes/workers/empire/charcoal_burner/init.lua"
- include "tribes/workers/empire/donkey/init.lua"
- include "tribes/workers/empire/donkeybreeder/init.lua"
- include "tribes/workers/empire/farmer/init.lua"
- include "tribes/workers/empire/fisher/init.lua"
- include "tribes/workers/empire/forester/init.lua"
- include "tribes/workers/empire/geologist/init.lua"
- include "tribes/workers/empire/hunter/init.lua"
- include "tribes/workers/empire/innkeeper/init.lua"
- include "tribes/workers/empire/lumberjack/init.lua"
- include "tribes/workers/empire/miller/init.lua"
- include "tribes/workers/empire/miner_master/init.lua"
- include "tribes/workers/empire/miner/init.lua"
- include "tribes/workers/empire/pigbreeder/init.lua"
- include "tribes/workers/empire/recruit/init.lua"
- include "tribes/workers/empire/scout/init.lua"
- include "tribes/workers/empire/shepherd/init.lua"
- include "tribes/workers/empire/shipwright/init.lua"
- include "tribes/workers/empire/smelter/init.lua"
- include "tribes/workers/empire/soldier/init.lua"
- include "tribes/workers/empire/stonemason/init.lua"
- include "tribes/workers/empire/toolsmith/init.lua"
- include "tribes/workers/empire/trainer/init.lua"
- include "tribes/workers/empire/vinefarmer/init.lua"
- include "tribes/workers/empire/vintner/init.lua"
- include "tribes/workers/empire/weaponsmith/init.lua"
- include "tribes/workers/empire/weaver/init.lua"
+ load_directories({"tribes/workers"})
end)
-- ===================================
@@ -276,17 +78,7 @@
-- ===================================
print_loading_message("┃ Warehouses", function()
- include "tribes/buildings/warehouses/atlanteans/headquarters/init.lua"
- include "tribes/buildings/warehouses/atlanteans/port/init.lua"
- include "tribes/buildings/warehouses/atlanteans/warehouse/init.lua"
- include "tribes/buildings/warehouses/barbarians/headquarters/init.lua"
- include "tribes/buildings/warehouses/barbarians/headquarters_interim/init.lua"
- include "tribes/buildings/warehouses/barbarians/port/init.lua"
- include "tribes/buildings/warehouses/barbarians/warehouse/init.lua"
- include "tribes/buildings/warehouses/empire/headquarters/init.lua"
- include "tribes/buildings/warehouses/empire/headquarters_shipwreck/init.lua"
- include "tribes/buildings/warehouses/empire/port/init.lua"
- include "tribes/buildings/warehouses/empire/warehouse/init.lua"
+ load_directories({"tribes/buildings/warehouses"})
end)
-- ===================================
@@ -294,125 +86,7 @@
-- ===================================
print_loading_message("┃ Productionsites", function()
- -- Atlanteans small
- include "tribes/buildings/productionsites/atlanteans/quarry/init.lua"
- include "tribes/buildings/productionsites/atlanteans/woodcutters_house/init.lua"
- include "tribes/buildings/productionsites/atlanteans/foresters_house/init.lua"
- include "tribes/buildings/productionsites/atlanteans/fishers_house/init.lua"
- include "tribes/buildings/productionsites/atlanteans/fishbreeders_house/init.lua"
- include "tribes/buildings/productionsites/atlanteans/hunters_house/init.lua"
- include "tribes/buildings/productionsites/atlanteans/well/init.lua"
- include "tribes/buildings/productionsites/atlanteans/gold_spinning_mill/init.lua"
- include "tribes/buildings/productionsites/atlanteans/scouts_house/init.lua"
- -- Atlanteans medium
- include "tribes/buildings/productionsites/atlanteans/sawmill/init.lua"
- include "tribes/buildings/productionsites/atlanteans/smokery/init.lua"
- include "tribes/buildings/productionsites/atlanteans/mill/init.lua"
- include "tribes/buildings/productionsites/atlanteans/bakery/init.lua"
- include "tribes/buildings/productionsites/atlanteans/charcoal_kiln/init.lua"
- include "tribes/buildings/productionsites/atlanteans/smelting_works/init.lua"
- include "tribes/buildings/productionsites/atlanteans/shipyard/init.lua"
- include "tribes/buildings/productionsites/atlanteans/toolsmithy/init.lua"
- include "tribes/buildings/productionsites/atlanteans/weaponsmithy/init.lua"
- include "tribes/buildings/productionsites/atlanteans/armorsmithy/init.lua"
- include "tribes/buildings/productionsites/atlanteans/barracks/init.lua"
-
- -- Atlanteans big
- include "tribes/buildings/productionsites/atlanteans/horsefarm/init.lua"
- include "tribes/buildings/productionsites/atlanteans/farm/init.lua"
- include "tribes/buildings/productionsites/atlanteans/blackroot_farm/init.lua"
- include "tribes/buildings/productionsites/atlanteans/spiderfarm/init.lua"
- include "tribes/buildings/productionsites/atlanteans/weaving_mill/init.lua"
-
- -- Atlanteans mines
- include "tribes/buildings/productionsites/atlanteans/crystalmine/init.lua"
- include "tribes/buildings/productionsites/atlanteans/coalmine/init.lua"
- include "tribes/buildings/productionsites/atlanteans/ironmine/init.lua"
- include "tribes/buildings/productionsites/atlanteans/goldmine/init.lua"
- -- Barbarians small
- include "tribes/buildings/productionsites/barbarians/quarry/init.lua"
- include "tribes/buildings/productionsites/barbarians/lumberjacks_hut/init.lua"
- include "tribes/buildings/productionsites/barbarians/rangers_hut/init.lua"
- include "tribes/buildings/productionsites/barbarians/fishers_hut/init.lua"
- include "tribes/buildings/productionsites/barbarians/hunters_hut/init.lua"
- include "tribes/buildings/productionsites/barbarians/gamekeepers_hut/init.lua"
- include "tribes/buildings/productionsites/barbarians/well/init.lua"
- include "tribes/buildings/productionsites/barbarians/scouts_hut/init.lua"
- -- Barbarians medium
- include "tribes/buildings/productionsites/barbarians/wood_hardener/init.lua"
- include "tribes/buildings/productionsites/barbarians/lime_kiln/init.lua"
- include "tribes/buildings/productionsites/barbarians/reed_yard/init.lua"
- include "tribes/buildings/productionsites/barbarians/bakery/init.lua"
- include "tribes/buildings/productionsites/barbarians/brewery/init.lua"
- include "tribes/buildings/productionsites/barbarians/micro_brewery/init.lua"
- include "tribes/buildings/productionsites/barbarians/big_inn/init.lua"
- include "tribes/buildings/productionsites/barbarians/inn/init.lua"
- include "tribes/buildings/productionsites/barbarians/tavern/init.lua"
- include "tribes/buildings/productionsites/barbarians/charcoal_kiln/init.lua"
- include "tribes/buildings/productionsites/barbarians/smelting_works/init.lua"
- include "tribes/buildings/productionsites/barbarians/shipyard/init.lua"
- include "tribes/buildings/productionsites/barbarians/warmill/init.lua"
- include "tribes/buildings/productionsites/barbarians/ax_workshop/init.lua"
- include "tribes/buildings/productionsites/barbarians/metal_workshop/init.lua"
- include "tribes/buildings/productionsites/barbarians/barracks/init.lua"
-
- -- Barbarians big
- include "tribes/buildings/productionsites/barbarians/cattlefarm/init.lua"
- include "tribes/buildings/productionsites/barbarians/farm/init.lua"
- include "tribes/buildings/productionsites/barbarians/weaving_mill/init.lua"
- include "tribes/buildings/productionsites/barbarians/helmsmithy/init.lua"
- -- Barbarians mines
- include "tribes/buildings/productionsites/barbarians/granitemine/init.lua"
- include "tribes/buildings/productionsites/barbarians/coalmine_deeper/init.lua"
- include "tribes/buildings/productionsites/barbarians/coalmine_deep/init.lua"
- include "tribes/buildings/productionsites/barbarians/coalmine/init.lua"
- include "tribes/buildings/productionsites/barbarians/ironmine_deeper/init.lua"
- include "tribes/buildings/productionsites/barbarians/ironmine_deep/init.lua"
- include "tribes/buildings/productionsites/barbarians/ironmine/init.lua"
- include "tribes/buildings/productionsites/barbarians/goldmine_deeper/init.lua"
- include "tribes/buildings/productionsites/barbarians/goldmine_deep/init.lua"
- include "tribes/buildings/productionsites/barbarians/goldmine/init.lua"
- -- Empire small
- include "tribes/buildings/productionsites/empire/quarry/init.lua"
- include "tribes/buildings/productionsites/empire/lumberjacks_house/init.lua"
- include "tribes/buildings/productionsites/empire/foresters_house/init.lua"
- include "tribes/buildings/productionsites/empire/fishers_house/init.lua"
- include "tribes/buildings/productionsites/empire/hunters_house/init.lua"
- include "tribes/buildings/productionsites/empire/well/init.lua"
- include "tribes/buildings/productionsites/empire/scouts_house/init.lua"
- -- Empire medium
- include "tribes/buildings/productionsites/empire/stonemasons_house/init.lua"
- include "tribes/buildings/productionsites/empire/sawmill/init.lua"
- include "tribes/buildings/productionsites/empire/mill/init.lua"
- include "tribes/buildings/productionsites/empire/bakery/init.lua"
- include "tribes/buildings/productionsites/empire/brewery/init.lua"
- include "tribes/buildings/productionsites/empire/vineyard/init.lua"
- include "tribes/buildings/productionsites/empire/winery/init.lua"
- include "tribes/buildings/productionsites/empire/inn/init.lua"
- include "tribes/buildings/productionsites/empire/tavern/init.lua"
- include "tribes/buildings/productionsites/empire/charcoal_kiln/init.lua"
- include "tribes/buildings/productionsites/empire/smelting_works/init.lua"
- include "tribes/buildings/productionsites/empire/shipyard/init.lua"
- include "tribes/buildings/productionsites/empire/toolsmithy/init.lua"
- include "tribes/buildings/productionsites/empire/armorsmithy/init.lua"
- -- Empire big
- include "tribes/buildings/productionsites/empire/donkeyfarm/init.lua"
- include "tribes/buildings/productionsites/empire/farm/init.lua"
- include "tribes/buildings/productionsites/empire/piggery/init.lua"
- include "tribes/buildings/productionsites/empire/sheepfarm/init.lua"
- include "tribes/buildings/productionsites/empire/weaving_mill/init.lua"
- include "tribes/buildings/productionsites/empire/weaponsmithy/init.lua"
- include "tribes/buildings/productionsites/empire/barracks/init.lua"
-
- -- Empire mines
- include "tribes/buildings/productionsites/empire/coalmine_deep/init.lua"
- include "tribes/buildings/productionsites/empire/coalmine/init.lua"
- include "tribes/buildings/productionsites/empire/ironmine_deep/init.lua"
- include "tribes/buildings/productionsites/empire/ironmine/init.lua"
- include "tribes/buildings/productionsites/empire/marblemine_deep/init.lua"
- include "tribes/buildings/productionsites/empire/marblemine/init.lua"
- include "tribes/buildings/productionsites/empire/goldmine_deep/init.lua"
- include "tribes/buildings/productionsites/empire/goldmine/init.lua"
+ load_directories({"tribes/buildings/productionsites"})
end)
-- ===================================
@@ -420,13 +94,7 @@
-- ===================================
print_loading_message("┃ Trainingsites", function()
- include "tribes/buildings/trainingsites/atlanteans/dungeon/init.lua"
- include "tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua"
- include "tribes/buildings/trainingsites/barbarians/battlearena/init.lua"
- include "tribes/buildings/trainingsites/barbarians/trainingcamp/init.lua"
- include "tribes/buildings/trainingsites/empire/colosseum/init.lua"
- include "tribes/buildings/trainingsites/empire/arena/init.lua"
- include "tribes/buildings/trainingsites/empire/trainingcamp/init.lua"
+ load_directories({"tribes/buildings/trainingsites"})
end)
-- ===================================
@@ -434,26 +102,7 @@
-- ===================================
print_loading_message("┃ Militarysites", function()
- include "tribes/buildings/militarysites/atlanteans/guardhouse/init.lua"
- include "tribes/buildings/militarysites/atlanteans/guardhall/init.lua"
- include "tribes/buildings/militarysites/atlanteans/tower_small/init.lua"
- include "tribes/buildings/militarysites/atlanteans/tower_high/init.lua"
- include "tribes/buildings/militarysites/atlanteans/tower/init.lua"
- include "tribes/buildings/militarysites/atlanteans/castle/init.lua"
-
- include "tribes/buildings/militarysites/barbarians/sentry/init.lua"
- include "tribes/buildings/militarysites/barbarians/barrier/init.lua"
- include "tribes/buildings/militarysites/barbarians/tower/init.lua"
- include "tribes/buildings/militarysites/barbarians/citadel/init.lua"
- include "tribes/buildings/militarysites/barbarians/fortress/init.lua"
-
- include "tribes/buildings/militarysites/empire/sentry/init.lua"
- include "tribes/buildings/militarysites/empire/blockhouse/init.lua"
- include "tribes/buildings/militarysites/empire/barrier/init.lua"
- include "tribes/buildings/militarysites/empire/outpost/init.lua"
- include "tribes/buildings/militarysites/empire/tower/init.lua"
- include "tribes/buildings/militarysites/empire/castle/init.lua"
- include "tribes/buildings/militarysites/empire/fortress/init.lua"
+ load_directories({"tribes/buildings/militarysites"})
end)
-- ===================================
@@ -461,8 +110,7 @@
-- ===================================
print_loading_message("┃ Partially finished buildings", function()
- include "tribes/buildings/partially_finished/constructionsite/init.lua"
- include "tribes/buildings/partially_finished/dismantlesite/init.lua"
+ load_directories({"tribes/buildings/partially_finished"})
end)
-- ===================================
=== modified file 'src/game_io/game_loader.cc'
--- src/game_io/game_loader.cc 2017-07-02 21:00:58 +0000
+++ src/game_io/game_loader.cc 2017-08-17 11:49:32 +0000
@@ -84,6 +84,15 @@
M.read(fs_, game_);
log("Game: Reading Map Data took %ums\n", timer.ms_since_last_query());
+ // This has to be loaded after the map packet so that the map's filesystem will exist.
+ // The custom tribe scripts are saved when the map scripting packet is saved, but we need
+ // to load them as early as possible here.
+ if (fs_.file_exists("map/scripting/tribes/init.lua")) {
+ log("Game: Reading Scenario Tribes ... ");
+ game_.lua().run_script("map:scripting/tribes/init.lua");
+ log("Game: Reading Scenario Tribes took %ums\n", timer.ms_since_last_query());
+ }
+
log("Game: Reading Player Info ... ");
{
GamePlayerInfoPacket p;
=== modified file 'src/io/filewrite.cc'
--- src/io/filewrite.cc 2017-01-25 18:55:59 +0000
+++ src/io/filewrite.cc 2017-08-17 11:49:32 +0000
@@ -36,12 +36,12 @@
filepos_ = 0;
}
-void FileWrite::write(FileSystem& fs, char const* const filename) {
+void FileWrite::write(FileSystem& fs, const std::string& filename) {
fs.write(filename, data_, length_);
clear();
}
-void FileWrite::write_append(RealFSImpl& fs, char const* const filename) {
+void FileWrite::write_append(RealFSImpl& fs, const std::string& filename) {
fs.write(filename, data_, length_, true);
clear();
}
=== modified file 'src/io/filewrite.h'
--- src/io/filewrite.h 2017-01-25 18:55:59 +0000
+++ src/io/filewrite.h 2017-08-17 11:49:32 +0000
@@ -76,11 +76,11 @@
/// Write the file out to disk. If successful, this clears the buffers.
/// Otherwise, an exception is thrown but the buffer remains intact (don't
/// worry, it will be cleared by the destructor).
- void write(FileSystem& fs, char const* const filename);
+ void write(FileSystem& fs, const std::string& filename);
/// Same as above, just that the data is appended to the file
/// NOTE RealFSImpl is used by purpose - zip filesystems do not support appending
- void write_append(RealFSImpl& fs, char const* const filename);
+ void write_append(RealFSImpl& fs, const std::string& filename);
/// Get the position that will be written to in the next write operation that
/// does not specify a position.
=== modified file 'src/logic/game.cc'
--- src/logic/game.cc 2017-08-16 13:23:15 +0000
+++ src/logic/game.cc 2017-08-17 11:49:32 +0000
@@ -205,6 +205,12 @@
loader_ui.step(_("Loading tribes"));
tribes();
+ // If the scenario has custrom tribe entites, load them.
+ const std::string custom_tribe_script = mapname + "/scripting/tribes/init.lua";
+ if (g_fs->file_exists(custom_tribe_script)) {
+ lua().run_script(custom_tribe_script);
+ }
+
// We have to create the players here.
loader_ui.step(_("Creating players"));
PlayerNumber const nr_players = map().get_nrplayers();
=== modified file 'src/logic/map_objects/tribes/building.cc'
--- src/logic/map_objects/tribes/building.cc 2017-08-16 04:31:56 +0000
+++ src/logic/map_objects/tribes/building.cc 2017-08-17 11:49:32 +0000
@@ -57,9 +57,9 @@
BuildingDescr::BuildingDescr(const std::string& init_descname,
const MapObjectType init_type,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: MapObjectDescr(init_type, table.get_string("name"), init_descname, table),
- egbase_(egbase),
+ egbase_(*egbase),
buildable_(false),
size_(BaseImmovable::SMALL),
mine_(false),
@@ -112,22 +112,11 @@
if (enh == name()) {
throw wexception("enhancement to same type");
}
- DescriptionIndex const en_i = egbase_.tribes().building_index(enh);
- if (egbase_.tribes().building_exists(en_i)) {
- enhancement_ = en_i;
-
- // Merge the enhancements workarea info into this building's
- // workarea info.
- const BuildingDescr* tmp_enhancement = egbase_.tribes().get_building_descr(en_i);
- for (auto area : tmp_enhancement->workarea_info_) {
- std::set<std::string>& strs = workarea_info_[area.first];
- for (std::string str : area.second)
- strs.insert(str);
- }
+ if (egbase_.tribes().building_exists(enh)) {
+ set_enhances_to(enh);
} else {
- throw wexception(
- "\"%s\" has not been defined as a building type (wrong declaration order?)",
- enh.c_str());
+ // The advanced building wasn't loaded yet, so we'll try this again in postload.
+ egbase->mutable_tribes()->add_mapobject_enhancement({MapObjectType::BUILDING, name(), enh});
}
}
@@ -164,6 +153,18 @@
}
}
+void BuildingDescr::set_enhances_to(const std::string& name) {
+ enhancement_ = egbase_.tribes().safe_building_index(name);
+
+ // Merge the enhancements workarea info into this building's
+ // workarea info.
+ for (auto area : egbase_.tribes().get_building_descr(enhancement_)->workarea_info_) {
+ std::set<std::string>& strs = workarea_info_[area.first];
+ for (std::string str : area.second)
+ strs.insert(str);
+ }
+}
+
Building& BuildingDescr::create(EditorGameBase& egbase,
Player& owner,
Coords const pos,
=== modified file 'src/logic/map_objects/tribes/building.h'
--- src/logic/map_objects/tribes/building.h 2017-08-09 17:55:34 +0000
+++ src/logic/map_objects/tribes/building.h 2017-08-17 11:49:32 +0000
@@ -66,7 +66,7 @@
BuildingDescr(const std::string& init_descname,
MapObjectType type,
const LuaTable& t,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
~BuildingDescr() override {
}
@@ -80,6 +80,9 @@
return enhanced_building_;
}
+ /// Define a building that this building can be enhanced to. 'name' is the descr().name() of the other building.
+ void set_enhances_to(const std::string& name);
+
/**
* The build cost for direct construction
*/
=== modified file 'src/logic/map_objects/tribes/carrier.cc'
--- src/logic/map_objects/tribes/carrier.cc 2017-04-22 06:45:52 +0000
+++ src/logic/map_objects/tribes/carrier.cc 2017-08-17 11:49:32 +0000
@@ -568,7 +568,7 @@
CarrierDescr::CarrierDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: WorkerDescr(init_descname, MapObjectType::CARRIER, table, egbase),
ware_hotspot_(Vector2i(0, 15)) {
if (table.has_key("ware_hotspot")) {
=== modified file 'src/logic/map_objects/tribes/carrier.h'
--- src/logic/map_objects/tribes/carrier.h 2017-06-25 19:12:30 +0000
+++ src/logic/map_objects/tribes/carrier.h 2017-08-17 11:49:32 +0000
@@ -29,7 +29,7 @@
public:
CarrierDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
~CarrierDescr() override {
}
=== modified file 'src/logic/map_objects/tribes/constructionsite.cc'
--- src/logic/map_objects/tribes/constructionsite.cc 2017-06-23 16:16:28 +0000
+++ src/logic/map_objects/tribes/constructionsite.cc 2017-08-17 11:49:32 +0000
@@ -45,7 +45,7 @@
*/
ConstructionSiteDescr::ConstructionSiteDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: BuildingDescr(init_descname, MapObjectType::CONSTRUCTIONSITE, table, egbase) {
add_attribute(MapObject::CONSTRUCTIONSITE);
}
=== modified file 'src/logic/map_objects/tribes/constructionsite.h'
--- src/logic/map_objects/tribes/constructionsite.h 2017-06-24 08:47:46 +0000
+++ src/logic/map_objects/tribes/constructionsite.h 2017-08-17 11:49:32 +0000
@@ -65,7 +65,7 @@
public:
ConstructionSiteDescr(const std::string& init_descname,
const LuaTable& t,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
~ConstructionSiteDescr() override {
}
=== modified file 'src/logic/map_objects/tribes/dismantlesite.cc'
--- src/logic/map_objects/tribes/dismantlesite.cc 2017-04-23 12:11:19 +0000
+++ src/logic/map_objects/tribes/dismantlesite.cc 2017-08-17 11:49:32 +0000
@@ -45,7 +45,7 @@
DismantleSiteDescr::DismantleSiteDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: BuildingDescr(init_descname, MapObjectType::DISMANTLESITE, table, egbase) {
add_attribute(MapObject::Attribute::CONSTRUCTIONSITE); // Yep, this is correct.
}
=== modified file 'src/logic/map_objects/tribes/dismantlesite.h'
--- src/logic/map_objects/tribes/dismantlesite.h 2017-06-25 19:12:30 +0000
+++ src/logic/map_objects/tribes/dismantlesite.h 2017-08-17 11:49:32 +0000
@@ -47,7 +47,7 @@
public:
DismantleSiteDescr(const std::string& init_descname,
const LuaTable& t,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
~DismantleSiteDescr() override {
}
=== modified file 'src/logic/map_objects/tribes/militarysite.cc'
--- src/logic/map_objects/tribes/militarysite.cc 2017-08-16 13:23:15 +0000
+++ src/logic/map_objects/tribes/militarysite.cc 2017-08-17 11:49:32 +0000
@@ -296,7 +296,7 @@
*/
MilitarySiteDescr::MilitarySiteDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: BuildingDescr(init_descname, MapObjectType::MILITARYSITE, table, egbase),
conquer_radius_(0),
num_soldiers_(0),
=== modified file 'src/logic/map_objects/tribes/militarysite.h'
--- src/logic/map_objects/tribes/militarysite.h 2017-08-16 13:23:15 +0000
+++ src/logic/map_objects/tribes/militarysite.h 2017-08-17 11:49:32 +0000
@@ -45,7 +45,7 @@
public:
MilitarySiteDescr(const std::string& init_descname,
const LuaTable& t,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
~MilitarySiteDescr() override {
}
=== modified file 'src/logic/map_objects/tribes/productionsite.cc'
--- src/logic/map_objects/tribes/productionsite.cc 2017-08-16 04:31:56 +0000
+++ src/logic/map_objects/tribes/productionsite.cc 2017-08-17 11:49:32 +0000
@@ -63,7 +63,7 @@
const std::string& msgctxt,
MapObjectType init_type,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: BuildingDescr(init_descname, init_type, table, egbase),
out_of_resource_productivity_threshold_(100) {
i18n::Textdomain td("tribes");
@@ -86,15 +86,15 @@
if (table.has_key("outputs")) {
for (const std::string& output : table.get_table("outputs")->array_entries<std::string>()) {
try {
- DescriptionIndex idx = egbase.tribes().ware_index(output);
- if (egbase.tribes().ware_exists(idx)) {
+ DescriptionIndex idx = egbase->tribes().ware_index(output);
+ if (egbase->tribes().ware_exists(idx)) {
if (output_ware_types_.count(idx)) {
throw wexception("this ware type has already been declared as an output");
}
output_ware_types_.insert(idx);
} else {
- idx = egbase.tribes().worker_index(output);
- if (egbase.tribes().worker_exists(idx)) {
+ idx = egbase->tribes().worker_index(output);
+ if (egbase->tribes().worker_exists(idx)) {
if (output_worker_types_.count(idx)) {
throw wexception("this worker type has already been declared as an output");
}
@@ -119,8 +119,8 @@
if (amount < 1 || 255 < amount) {
throw wexception("amount is out of range 1 .. 255");
}
- DescriptionIndex idx = egbase.tribes().ware_index(ware_name);
- if (egbase.tribes().ware_exists(idx)) {
+ DescriptionIndex idx = egbase->tribes().ware_index(ware_name);
+ if (egbase->tribes().ware_exists(idx)) {
for (const auto& temp_inputs : input_wares()) {
if (temp_inputs.first == idx) {
throw wexception("duplicated");
@@ -128,8 +128,8 @@
}
input_wares_.push_back(WareAmount(idx, amount));
} else {
- idx = egbase.tribes().worker_index(ware_name);
- if (egbase.tribes().worker_exists(idx)) {
+ idx = egbase->tribes().worker_index(ware_name);
+ if (egbase->tribes().worker_exists(idx)) {
for (const auto& temp_inputs : input_workers()) {
if (temp_inputs.first == idx) {
throw wexception("duplicated");
@@ -153,8 +153,8 @@
if (amount < 1 || 255 < amount) {
throw wexception("count is out of range 1 .. 255");
}
- DescriptionIndex const woi = egbase.tribes().worker_index(worker_name);
- if (egbase.tribes().worker_exists(woi)) {
+ DescriptionIndex const woi = egbase->tribes().worker_index(worker_name);
+ if (egbase->tribes().worker_exists(woi)) {
for (const auto& wp : working_positions()) {
if (wp.first == woi) {
throw wexception("duplicated");
@@ -187,7 +187,7 @@
program_descname = pgettext_expr(msgctxt.c_str(), program_descname_unlocalized.c_str());
}
programs_[program_name] = std::unique_ptr<ProductionProgram>(new ProductionProgram(
- program_name, program_descname, program_table->get_table("actions"), egbase, this));
+ program_name, program_descname, program_table->get_table("actions"), *egbase, this));
} catch (const std::exception& e) {
throw wexception("program %s: %s", program_name.c_str(), e.what());
}
@@ -197,7 +197,7 @@
ProductionSiteDescr::ProductionSiteDescr(const std::string& init_descname,
const std::string& msgctxt,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: ProductionSiteDescr(init_descname, msgctxt, MapObjectType::PRODUCTIONSITE, table, egbase) {
}
=== modified file 'src/logic/map_objects/tribes/productionsite.h'
--- src/logic/map_objects/tribes/productionsite.h 2017-06-24 08:47:46 +0000
+++ src/logic/map_objects/tribes/productionsite.h 2017-08-17 11:49:32 +0000
@@ -63,11 +63,11 @@
const std::string& msgctxt,
MapObjectType type,
const LuaTable& t,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
ProductionSiteDescr(const std::string& init_descname,
const std::string& msgctxt,
const LuaTable& t,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
Building& create_object() const override;
=== modified file 'src/logic/map_objects/tribes/soldier.cc'
--- src/logic/map_objects/tribes/soldier.cc 2017-07-05 19:21:57 +0000
+++ src/logic/map_objects/tribes/soldier.cc 2017-08-17 11:49:32 +0000
@@ -63,7 +63,7 @@
SoldierDescr::SoldierDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: WorkerDescr(init_descname, MapObjectType::SOLDIER, table, egbase),
health_(table.get_table("health")),
attack_(table.get_table("attack")),
=== modified file 'src/logic/map_objects/tribes/soldier.h'
--- src/logic/map_objects/tribes/soldier.h 2017-06-24 08:47:46 +0000
+++ src/logic/map_objects/tribes/soldier.h 2017-08-17 11:49:32 +0000
@@ -41,7 +41,7 @@
public:
friend class Economy;
- SoldierDescr(const std::string& init_descname, const LuaTable& t, const EditorGameBase& egbase);
+ SoldierDescr(const std::string& init_descname, const LuaTable& t, EditorGameBase* egbase);
~SoldierDescr() override {
}
=== modified file 'src/logic/map_objects/tribes/trainingsite.cc'
--- src/logic/map_objects/tribes/trainingsite.cc 2017-06-24 20:22:19 +0000
+++ src/logic/map_objects/tribes/trainingsite.cc 2017-08-17 11:49:32 +0000
@@ -47,7 +47,7 @@
*/
TrainingSiteDescr::TrainingSiteDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: ProductionSiteDescr(init_descname, "", MapObjectType::TRAININGSITE, table, egbase),
num_soldiers_(table.get_int("soldier_capacity")),
max_stall_(table.get_int("trainer_patience")),
=== modified file 'src/logic/map_objects/tribes/trainingsite.h'
--- src/logic/map_objects/tribes/trainingsite.h 2017-06-25 19:12:30 +0000
+++ src/logic/map_objects/tribes/trainingsite.h 2017-08-17 11:49:32 +0000
@@ -35,7 +35,7 @@
public:
TrainingSiteDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
~TrainingSiteDescr() override {
}
=== modified file 'src/logic/map_objects/tribes/tribe_descr.cc'
--- src/logic/map_objects/tribes/tribe_descr.cc 2017-07-19 20:40:32 +0000
+++ src/logic/map_objects/tribes/tribe_descr.cc 2017-08-17 11:49:32 +0000
@@ -165,67 +165,10 @@
for (const std::string& buildingname :
table.get_table("buildings")->array_entries<std::string>()) {
- try {
- DescriptionIndex index = tribes_.safe_building_index(buildingname);
- if (has_building(index)) {
- throw GameDataError("Duplicate definition of building '%s'", buildingname.c_str());
- }
- buildings_.push_back(index);
-
- // Register trainigsites
- if (get_building_descr(index)->type() == MapObjectType::TRAININGSITE) {
- trainingsites_.push_back(index);
- }
-
- // Register construction materials
- for (const auto& build_cost : get_building_descr(index)->buildcost()) {
- if (!is_construction_material(build_cost.first)) {
- construction_materials_.insert(build_cost.first);
- }
- }
- for (const auto& enhancement_cost : get_building_descr(index)->enhancement_cost()) {
- if (!is_construction_material(enhancement_cost.first)) {
- construction_materials_.insert(enhancement_cost.first);
- }
- }
- } catch (const WException& e) {
- throw GameDataError("Failed adding building '%s': %s", buildingname.c_str(), e.what());
- }
- }
-
- // Set default trainingsites proportions for AI. Make sure that we get a sum of ca. 100
- float trainingsites_without_percent = 0.f;
- int used_percent = 0;
- for (const DescriptionIndex& index : trainingsites_) {
- const BuildingDescr& descr = *tribes_.get_building_descr(index);
- if (descr.hints().trainingsites_max_percent() == 0) {
- ++trainingsites_without_percent;
- } else {
- used_percent += descr.hints().trainingsites_max_percent();
- }
- }
- if (trainingsites_without_percent > 0.f && used_percent > 100) {
- throw GameDataError(
- "Predefined training sites proportions add up to > 100%%: %d", used_percent);
- } else if (trainingsites_without_percent > 0) {
- const int percent_to_use = std::ceil((100 - used_percent) / trainingsites_without_percent);
- if (percent_to_use < 1) {
- throw GameDataError("Training sites without predefined proportions add up to < 1%% and "
- "will never be built: %d",
- used_percent);
- }
- for (const DescriptionIndex& index : trainingsites_) {
- BuildingDescr* descr = tribes_.get_mutable_building_descr(index);
- if (descr->hints().trainingsites_max_percent() == 0) {
- descr->set_hints_trainingsites_max_percent(percent_to_use);
- used_percent += percent_to_use;
- }
- }
- }
- if (used_percent < 100) {
- throw GameDataError(
- "Final training sites proportions add up to < 100%%: %d", used_percent);
- }
+ add_building(buildingname);
+ }
+
+ update_trainingsites_proportions();
// Special types
builder_ = add_special_worker(table.get_string("builder"));
@@ -503,6 +446,99 @@
}
}
+void TribeDescr::add_building(const std::string& buildingname) {
+ try {
+ DescriptionIndex index = tribes_.safe_building_index(buildingname);
+ if (has_building(index)) {
+ throw GameDataError("Duplicate definition of building '%s'", buildingname.c_str());
+ }
+ buildings_.push_back(index);
+
+ // Register trainigsites
+ if (get_building_descr(index)->type() == MapObjectType::TRAININGSITE) {
+ trainingsites_.push_back(index);
+ }
+
+ // Register construction materials
+ for (const auto& build_cost : get_building_descr(index)->buildcost()) {
+ if (!is_construction_material(build_cost.first)) {
+ construction_materials_.insert(build_cost.first);
+ }
+ }
+ for (const auto& enhancement_cost : get_building_descr(index)->enhancement_cost()) {
+ if (!is_construction_material(enhancement_cost.first)) {
+ construction_materials_.insert(enhancement_cost.first);
+ }
+ }
+ } catch (const WException& e) {
+ throw GameDataError("Failed adding building '%s': %s", buildingname.c_str(), e.what());
+ }
+}
+
+void TribeDescr::update_trainingsites_proportions(const std::string& new_site) {
+ // Set default trainingsites proportions for AI. Make sure that we get a sum of ca. 100
+ float trainingsites_without_percent = 0.f;
+ int used_percent = 0;
+ if (new_site.empty()) {
+ for (const DescriptionIndex& index : trainingsites_) {
+ const BuildingDescr& descr = *tribes_.get_building_descr(index);
+ if (descr.hints().trainingsites_max_percent() == 0) {
+ ++trainingsites_without_percent;
+ } else {
+ used_percent += descr.hints().trainingsites_max_percent();
+ }
+ }
+ if (trainingsites_without_percent > 0.f && used_percent > 100) {
+ throw GameDataError(
+ "Predefined training sites proportions add up to > 100%%: %d", used_percent);
+ } else if (trainingsites_without_percent > 0) {
+ const int percent_to_use = std::ceil((100 - used_percent) / trainingsites_without_percent);
+ if (percent_to_use < 1) {
+ throw GameDataError("Training sites without predefined proportions add up to < 1%% and "
+ "will never be built: %d",
+ used_percent);
+ }
+ for (const DescriptionIndex& index : trainingsites_) {
+ BuildingDescr* descr = tribes_.get_mutable_building_descr(index);
+ if (descr->hints().trainingsites_max_percent() == 0) {
+ descr->set_hints_trainingsites_max_percent(percent_to_use);
+ used_percent += percent_to_use;
+ }
+ }
+ }
+ } else {
+ // Adjust percentages to include a custom scenario training site.
+ assert(!trainingsites().empty());
+
+ // Make sure that the new site gets a fair share.
+ BuildingDescr* newsite_descr = tribes_.get_mutable_building_descr(tribes_.safe_building_index(new_site));
+ if (newsite_descr->hints().trainingsites_max_percent() == 0) {
+ newsite_descr->set_hints_trainingsites_max_percent(100 / trainingsites().size());
+ }
+
+ // See what we have.
+ int total_percent = 0;
+ for (const DescriptionIndex& index : trainingsites_) {
+ const BuildingDescr* descr = tribes_.get_building_descr(index);
+ total_percent += descr->hints().trainingsites_max_percent();
+ }
+
+ // Subtract the surplus.
+ const int percent_to_subtract = std::ceil((total_percent - 100) / trainingsites().size());
+ for (const DescriptionIndex& index : trainingsites_) {
+ BuildingDescr* descr = tribes_.get_mutable_building_descr(index);
+ if (descr->name() != newsite_descr->name()) {
+ descr->set_hints_trainingsites_max_percent(descr->hints().trainingsites_max_percent() - percent_to_subtract);
+ }
+ used_percent += descr->hints().trainingsites_max_percent();
+ }
+ }
+ if (used_percent < 100) {
+ throw GameDataError(
+ "Final training sites proportions add up to < 100%%: %d", used_percent);
+ }
+}
+
/**
* Helper functions
*/
=== modified file 'src/logic/map_objects/tribes/tribe_descr.h'
--- src/logic/map_objects/tribes/tribe_descr.h 2017-07-19 20:40:32 +0000
+++ src/logic/map_objects/tribes/tribe_descr.h 2017-08-17 11:49:32 +0000
@@ -157,6 +157,9 @@
return ship_names_;
}
+ void add_building(const std::string& buildingname);
+ void update_trainingsites_proportions(const std::string& new_site = "");
+
private:
// Helper function for adding a special worker type (carriers etc.)
DescriptionIndex add_special_worker(const std::string& workername);
=== modified file 'src/logic/map_objects/tribes/tribes.cc'
--- src/logic/map_objects/tribes/tribes.cc 2017-03-23 07:36:36 +0000
+++ src/logic/map_objects/tribes/tribes.cc 2017-08-17 11:49:32 +0000
@@ -78,28 +78,28 @@
tribes_(new DescriptionMaintainer<TribeDescr>()) {
}
-void Tribes::add_constructionsite_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_constructionsite_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
buildings_->add(new ConstructionSiteDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
table, egbase));
}
-void Tribes::add_dismantlesite_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_dismantlesite_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
buildings_->add(new DismantleSiteDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
table, egbase));
}
-void Tribes::add_militarysite_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_militarysite_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
buildings_->add(new MilitarySiteDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
table, egbase));
}
-void Tribes::add_productionsite_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_productionsite_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
const std::string msgctxt = table.get_string("msgctxt");
buildings_->add(
@@ -107,14 +107,14 @@
msgctxt, table, egbase));
}
-void Tribes::add_trainingsite_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_trainingsite_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
buildings_->add(new TrainingSiteDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
table, egbase));
}
-void Tribes::add_warehouse_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_warehouse_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
buildings_->add(new WarehouseDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
@@ -140,21 +140,21 @@
table));
}
-void Tribes::add_carrier_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_carrier_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
workers_->add(new CarrierDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
table, egbase));
}
-void Tribes::add_soldier_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_soldier_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
workers_->add(new SoldierDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
table, egbase));
}
-void Tribes::add_worker_type(const LuaTable& table, const EditorGameBase& egbase) {
+void Tribes::add_worker_type(const LuaTable& table, EditorGameBase* egbase) {
i18n::Textdomain td("tribes");
workers_->add(new WorkerDescr(
pgettext_expr(table.get_string("msgctxt").c_str(), table.get_string("descname").c_str()),
@@ -170,6 +170,20 @@
}
}
+void Tribes::add_custom_building(const LuaTable& table) {
+ const std::string tribename = table.get_string("tribename");
+ if (Widelands::tribe_exists(tribename)) {
+ TribeDescr* descr = tribes_->get_mutable(tribe_index(tribename));
+ const std::string buildingname = table.get_string("buildingname");
+ descr->add_building(buildingname);
+ if (descr->get_building_descr(descr->building_index(buildingname))->type() == MapObjectType::TRAININGSITE) {
+ descr->update_trainingsites_proportions(buildingname);
+ }
+ } else {
+ throw GameDataError("The tribe '%s'' has no preload file.", tribename.c_str());
+ }
+}
+
size_t Tribes::nrbuildings() const {
return buildings_->size();
}
@@ -189,6 +203,9 @@
bool Tribes::ware_exists(const DescriptionIndex& index) const {
return wares_->get_mutable(index) != nullptr;
}
+bool Tribes::worker_exists(const std::string& workername) const {
+ return workers_->exists(workername) != nullptr;
+}
bool Tribes::worker_exists(const DescriptionIndex& index) const {
return workers_->get_mutable(index) != nullptr;
}
@@ -329,7 +346,61 @@
}
}
+void Tribes::add_worker_buildcost(const WorkerBuildcost& buildcost) {
+ postload_workers_buildcost_.push_back(buildcost);
+}
+
+void Tribes::add_mapobject_enhancement(const MapObjectEnhancement& becomes) {
+ postload_mapobject_enhancements_.push_back(becomes);
+}
+
void Tribes::postload() {
+ // Some workers have other workers as build cost, so we postload those in order to perform the necessary checks.
+ for (const WorkerBuildcost& buildcost : postload_workers_buildcost_) {
+ if (!worker_exists(buildcost.worker)) {
+ throw GameDataError(
+ "Trying to add a worker buildcost to non-existing worker '%s'", buildcost.worker.c_str());
+ }
+ if (!worker_exists(buildcost.needed_worker)) {
+ throw GameDataError(
+ "The worker '%s' to be added as builcost to the worker '%s' does not exist", buildcost.needed_worker.c_str(), buildcost.worker.c_str());
+ }
+ workers_->get_mutable(safe_worker_index(buildcost.worker))->add_worker_to_buildcost(buildcost.needed_worker, buildcost.quantity);
+ }
+ postload_workers_buildcost_.clear();
+
+ // Likewise, more experienced workers and advanced buildings might not have been available yet when a lower-level worker or building was loaded.
+ for (const MapObjectEnhancement& enhancement : postload_mapobject_enhancements_) {
+ switch (enhancement.type) {
+ case MapObjectType::BUILDING:
+ if (!building_exists(enhancement.name)) {
+ throw GameDataError(
+ "Trying to add a building enhancement to non-existing building '%s'", enhancement.name.c_str());
+ }
+ if (!building_exists(enhancement.enhanced_name)) {
+ throw GameDataError(
+ "The building '%s' to be added as enhancement to the building '%s' does not exist", enhancement.enhanced_name.c_str(), enhancement.name.c_str());
+ }
+ buildings_->get_mutable(safe_building_index(enhancement.name))->set_enhances_to(enhancement.enhanced_name);
+ break;
+ case MapObjectType::WORKER:
+ if (!worker_exists(enhancement.name)) {
+ throw GameDataError(
+ "Trying to add a worker enhancement to non-existing worker '%s'", enhancement.name.c_str());
+ }
+ if (!worker_exists(enhancement.enhanced_name)) {
+ throw GameDataError(
+ "The worker '%s' to be added as enhancement to the worker '%s' does not exist", enhancement.enhanced_name.c_str(), enhancement.name.c_str());
+ }
+ workers_->get_mutable(safe_worker_index(enhancement.name))->set_becomes(enhancement.enhanced_name);
+ break;
+ default:
+ NEVER_HERE();
+ }
+ }
+ postload_mapobject_enhancements_.clear();
+
+ // Add building info to wares here, since wares were loaded first.
for (DescriptionIndex i = 0; i < buildings_->size(); ++i) {
BuildingDescr& building_descr = *buildings_->get_mutable(i);
=== modified file 'src/logic/map_objects/tribes/tribes.h'
--- src/logic/map_objects/tribes/tribes.h 2017-03-23 07:36:36 +0000
+++ src/logic/map_objects/tribes/tribes.h 2017-08-17 11:49:32 +0000
@@ -65,22 +65,22 @@
}
/// Adds this building type to the tribe description.
- void add_constructionsite_type(const LuaTable& table, const EditorGameBase& egbase);
-
- /// Adds this building type to the tribe description.
- void add_dismantlesite_type(const LuaTable& table, const EditorGameBase& egbase);
-
- /// Adds this building type to the tribe description.
- void add_militarysite_type(const LuaTable& table, const EditorGameBase& egbase);
-
- /// Adds this building type to the tribe description.
- void add_productionsite_type(const LuaTable& table, const EditorGameBase& egbase);
-
- /// Adds this building type to the tribe description.
- void add_trainingsite_type(const LuaTable& table, const EditorGameBase& egbase);
-
- /// Adds this building type to the tribe description.
- void add_warehouse_type(const LuaTable& table, const EditorGameBase& egbase);
+ void add_constructionsite_type(const LuaTable& table, EditorGameBase* egbase);
+
+ /// Adds this building type to the tribe description.
+ void add_dismantlesite_type(const LuaTable& table, EditorGameBase* egbase);
+
+ /// Adds this building type to the tribe description.
+ void add_militarysite_type(const LuaTable& table, EditorGameBase* egbase);
+
+ /// Adds this building type to the tribe description.
+ void add_productionsite_type(const LuaTable& table, EditorGameBase* egbase);
+
+ /// Adds this building type to the tribe description.
+ void add_trainingsite_type(const LuaTable& table, EditorGameBase* egbase);
+
+ /// Adds this building type to the tribe description.
+ void add_warehouse_type(const LuaTable& table, EditorGameBase* egbase);
/// Adds this immovable type to the tribe description.
void add_immovable_type(const LuaTable& table);
@@ -92,23 +92,26 @@
void add_ware_type(const LuaTable& table);
/// Adds this worker type to the tribe description.
- void add_carrier_type(const LuaTable& table, const EditorGameBase& egbase);
-
- /// Adds this worker type to the tribe description.
- void add_soldier_type(const LuaTable& table, const EditorGameBase& egbase);
-
- /// Adds this worker type to the tribe description.
- void add_worker_type(const LuaTable& table, const EditorGameBase& egbase);
+ void add_carrier_type(const LuaTable& table, EditorGameBase* egbase);
+
+ /// Adds this worker type to the tribe description.
+ void add_soldier_type(const LuaTable& table, EditorGameBase* egbase);
+
+ /// Adds this worker type to the tribe description.
+ void add_worker_type(const LuaTable& table, EditorGameBase* egbase);
/// Adds a specific tribe's configuration.
void add_tribe(const LuaTable& table, const EditorGameBase& egbase);
+ void add_custom_building(const LuaTable& table);
+
size_t nrbuildings() const;
size_t nrtribes() const;
size_t nrwares() const;
size_t nrworkers() const;
bool ware_exists(const DescriptionIndex& index) const;
+ bool worker_exists(const std::string& workername) const;
bool worker_exists(const DescriptionIndex& index) const;
bool building_exists(const std::string& buildingname) const;
bool building_exists(const DescriptionIndex& index) const;
@@ -148,6 +151,22 @@
/// Complete the Description objects' information with data from other Description objects.
void postload();
+ /// Some workers have other workers as part of their buildcost. If the other worker hasn't been loaded yet, it will need to be added during postload.
+ struct WorkerBuildcost {
+ const std::string worker;
+ const std::string needed_worker;
+ const Quantity quantity;
+ };
+ void add_worker_buildcost(const WorkerBuildcost& buildcost);
+
+ /// Enhanced buildings/workers might not have been loaded yet when a more basic type is being loaded, so we will need to add some of them during postload.
+ struct MapObjectEnhancement {
+ const MapObjectType type; // Worker or building
+ const std::string name;
+ const std::string enhanced_name;
+ };
+ void add_mapobject_enhancement(const MapObjectEnhancement& becomes);
+
private:
std::unique_ptr<DescriptionMaintainer<BuildingDescr>> buildings_;
std::unique_ptr<DescriptionMaintainer<ImmovableDescr>> immovables_;
@@ -156,6 +175,11 @@
std::unique_ptr<DescriptionMaintainer<WorkerDescr>> workers_;
std::unique_ptr<DescriptionMaintainer<TribeDescr>> tribes_;
+ /// Worker buildcost records to be added in postload. This container will be empty after postload.
+ std::vector<WorkerBuildcost> postload_workers_buildcost_;
+ /// Worker/Building enhancement records to be added in postload. This container will be empty after postload.
+ std::vector<MapObjectEnhancement> postload_mapobject_enhancements_;
+
DISALLOW_COPY_AND_ASSIGN(Tribes);
};
=== modified file 'src/logic/map_objects/tribes/warehouse.cc'
--- src/logic/map_objects/tribes/warehouse.cc 2017-07-01 15:36:36 +0000
+++ src/logic/map_objects/tribes/warehouse.cc 2017-08-17 11:49:32 +0000
@@ -293,7 +293,7 @@
*/
WarehouseDescr::WarehouseDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: BuildingDescr(init_descname, MapObjectType::WAREHOUSE, table, egbase),
conquers_(0),
heal_per_second_(0) {
=== modified file 'src/logic/map_objects/tribes/warehouse.h'
--- src/logic/map_objects/tribes/warehouse.h 2017-06-25 19:12:30 +0000
+++ src/logic/map_objects/tribes/warehouse.h 2017-08-17 11:49:32 +0000
@@ -50,7 +50,7 @@
public:
WarehouseDescr(const std::string& init_descname,
const LuaTable& t,
- const EditorGameBase& egbase);
+ EditorGameBase* egbase);
~WarehouseDescr() override {
}
=== modified file 'src/logic/map_objects/tribes/worker_descr.cc'
--- src/logic/map_objects/tribes/worker_descr.cc 2017-04-21 17:03:26 +0000
+++ src/logic/map_objects/tribes/worker_descr.cc 2017-08-17 11:49:32 +0000
@@ -38,12 +38,12 @@
WorkerDescr::WorkerDescr(const std::string& init_descname,
MapObjectType init_type,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: BobDescr(init_descname, init_type, MapObjectDescr::OwnerType::kTribe, table),
buildable_(false),
needed_experience_(INVALID_INDEX),
becomes_(INVALID_INDEX),
- egbase_(egbase) {
+ egbase_(*egbase) {
if (icon_filename().empty()) {
throw GameDataError("Worker %s has no menu icon", table.get_string("name").c_str());
}
@@ -60,17 +60,18 @@
throw GameDataError(
"a buildcost item of this ware type has already been defined: %s", key.c_str());
}
- if (!tribes.ware_exists(tribes.ware_index(key)) &&
- !tribes.worker_exists(tribes.worker_index(key))) {
- throw GameDataError("\"%s\" has not been defined as a ware/worker type (wrong "
- "declaration order?)",
- key.c_str());
- }
- int32_t value = items_table->get_int(key);
- uint8_t const count = value;
- if (count != value)
+ int32_t temp_quantity = items_table->get_int(key);
+ const uint8_t quantity = temp_quantity;
+ if (quantity != temp_quantity) {
throw GameDataError("count is out of range 1 .. 255");
- buildcost_.insert(std::pair<std::string, uint8_t>(key, count));
+ }
+ if (tribes.ware_exists(tribes.ware_index(key)) ||
+ tribes.worker_exists(tribes.worker_index(key))) {
+ buildcost_.insert(std::make_pair(key, quantity));
+ } else {
+ // The buildcost's worker wasn't loaded yet, so we'll try this again in postload.
+ egbase->mutable_tribes()->add_worker_buildcost({name(), key, quantity});
+ }
} catch (const WException& e) {
throw GameDataError("[buildcost] \"%s\": %s", key.c_str(), e.what());
}
@@ -91,8 +92,14 @@
// Read what the worker can become and the needed experience
if (table.has_key("becomes")) {
- becomes_ = egbase_.tribes().safe_worker_index(table.get_string("becomes"));
needed_experience_ = table.get_int("experience");
+ const std::string becomes = table.get_string("becomes");
+ if (egbase_.tribes().worker_exists(becomes)) {
+ set_becomes(becomes);
+ } else {
+ // The expert worker wasn't loaded yet, so we'll try this again in postload.
+ egbase->mutable_tribes()->add_mapobject_enhancement({MapObjectType::WORKER, name(), becomes});
+ }
}
// Read programs
@@ -122,13 +129,22 @@
WorkerDescr::WorkerDescr(const std::string& init_descname,
const LuaTable& table,
- const EditorGameBase& egbase)
+ EditorGameBase* egbase)
: WorkerDescr(init_descname, MapObjectType::WORKER, table, egbase) {
}
WorkerDescr::~WorkerDescr() {
}
+void WorkerDescr::add_worker_to_buildcost(const std::string& name, uint8_t quantity) {
+ buildcost_.insert(std::make_pair(name, quantity));
+}
+
+void WorkerDescr::set_becomes(const std::string& name) {
+ assert(needed_experience_ > 0 && needed_experience_ != INVALID_INDEX);
+ becomes_ = egbase_.tribes().safe_worker_index(name);
+}
+
/**
* Get a program from the workers description.
*/
=== modified file 'src/logic/map_objects/tribes/worker_descr.h'
--- src/logic/map_objects/tribes/worker_descr.h 2017-02-20 14:15:07 +0000
+++ src/logic/map_objects/tribes/worker_descr.h 2017-08-17 11:49:32 +0000
@@ -43,13 +43,13 @@
friend struct WorkerProgram;
public:
- using Buildcost = std::map<std::string, Quantity>;
+ using Buildcost = std::map<std::string, uint8_t>;
WorkerDescr(const std::string& init_descname,
MapObjectType type,
const LuaTable& table,
- const EditorGameBase& egbase);
- WorkerDescr(const std::string& init_descname, const LuaTable& t, const EditorGameBase& egbase);
+ EditorGameBase* egbase);
+ WorkerDescr(const std::string& init_descname, const LuaTable& t, EditorGameBase* egbase);
~WorkerDescr() override;
Bob& create_object() const override;
@@ -62,6 +62,14 @@
return buildcost_;
}
+ /// Some workers need to be added to the buildcost in postload, because the other worker might not have been loaded into the engine yet.
+ /// 'name' is the descr().name() of the other worker, 'quantity' is the amount of that woker type needed.
+ void add_worker_to_buildcost(const std::string& name, uint8_t quantity);
+
+ /// Sets the descr().name() of the worker that this worker will enhance to, given enough experience.
+ /// 'needed_experience_' needs to be set first.
+ void set_becomes(const std::string& name);
+
/// How much of the worker type that an economy should store in warehouses.
/// The special value std::numeric_limits<uint32_t>::max() means that the
/// the target quantity of this ware type will never be checked and should
=== modified file 'src/map_io/map_scripting_packet.cc'
--- src/map_io/map_scripting_packet.cc 2017-01-25 18:55:59 +0000
+++ src/map_io/map_scripting_packet.cc 2017-08-17 11:49:32 +0000
@@ -67,18 +67,29 @@
}
void MapScriptingPacket::write(FileSystem& fs, EditorGameBase& egbase, MapObjectSaver& mos) {
- fs.ensure_directory_exists("scripting");
-
+
+ // Write all .lua files that exist in the given 'path' in 'map_fs' to the 'target_fs'.
+ auto write_dir = [] (FileSystem& target_fs, FileSystem* map_fs, const std::string& path) {
+ if (map_fs) {
+ target_fs.ensure_directory_exists(path);
+ for (const std::string& script :
+ filter(map_fs->list_directory(path),
+ [](const std::string& fn) { return boost::ends_with(fn, ".lua"); })) {
+ size_t length;
+ void* input_data = map_fs->load(script, length);
+ target_fs.write(script, input_data, length);
+ free(input_data);
+ }
+ }
+ };
+
+ // Write any scenario scripting files in the map's basic scripting dir
FileSystem* map_fs = egbase.map().filesystem();
- if (map_fs) {
- for (const std::string& script :
- filter(map_fs->list_directory("scripting"),
- [](const std::string& fn) { return boost::ends_with(fn, ".lua"); })) {
- size_t length;
- void* input_data = map_fs->load(script, length);
- fs.write(script, input_data, length);
- free(input_data);
- }
+ write_dir(fs, map_fs, "scripting");
+
+ // Write any custom scenario tribe entities
+ if (map_fs->file_exists("scripting/tribes/init.lua")) {
+ write_dir(fs, map_fs, "scripting/tribes");
}
// Dump the global environment if this is a game and not in the editor
=== modified file 'src/scripting/lua_path.cc'
--- src/scripting/lua_path.cc 2017-06-24 08:47:46 +0000
+++ src/scripting/lua_path.cc 2017-08-17 11:49:32 +0000
@@ -143,7 +143,7 @@
:returns: An :class:`array` of file paths in lexicographical order.
*/
static int L_list_files(lua_State* L) {
- std::string filename_template = luaL_checkstring(L, 1);
+ const std::string filename_template = luaL_checkstring(L, 1);
NumberGlob glob(filename_template);
std::string filename;
@@ -161,9 +161,48 @@
return 1;
}
+/* RST
+.. function:: list_directory(filename)
+
+ Returns all file names contained in the given directory.
+
+ :type filename: class:`string`
+ :arg filename: The directory to read.
+
+ :returns: An :class:`array` of file names.
+*/
+static int L_list_directory(lua_State* L) {
+ lua_newtable(L);
+ int idx = 1;
+ for (const std::string& filename : g_fs->list_directory(luaL_checkstring(L, 1))) {
+ lua_pushint32(L, idx++);
+ lua_pushstring(L, filename);
+ lua_settable(L, -3);
+ }
+ return 1;
+}
+
+
+/* RST
+.. function:: is_directory(filename)
+
+ Checks whether the given filename points to a directory.
+
+ :type filename: class:`string`
+ :arg filename: The filename to check.
+
+ :returns: ``true`` if the given path is a directory.
+*/
+static int L_is_directory(lua_State* L) {
+ lua_pushboolean(L, g_fs->is_directory(luaL_checkstring(L, -1)));
+ return 1;
+}
+
const static struct luaL_Reg path[] = {{"basename", &L_basename},
{"dirname", &L_dirname},
{"list_files", &L_list_files},
+ {"list_directory", &L_list_directory},
+ {"is_directory", &L_is_directory},
{nullptr, nullptr}};
void luaopen_path(lua_State* L) {
=== modified file 'src/scripting/lua_root.cc'
--- src/scripting/lua_root.cc 2017-01-25 18:55:59 +0000
+++ src/scripting/lua_root.cc 2017-08-17 11:49:32 +0000
@@ -560,6 +560,7 @@
METHOD(LuaTribes, new_soldier_type),
METHOD(LuaTribes, new_worker_type),
METHOD(LuaTribes, new_tribe),
+ METHOD(LuaTribes, add_custom_building),
{0, 0},
};
const PropertyType<LuaTribes> LuaTribes::Properties[] = {
@@ -606,8 +607,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_constructionsite_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_constructionsite_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -630,8 +631,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_dismantlesite_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_dismantlesite_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -654,8 +655,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_militarysite_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_militarysite_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -678,8 +679,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_productionsite_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_productionsite_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -702,8 +703,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_trainingsite_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_trainingsite_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -726,8 +727,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_warehouse_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_warehouse_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -818,8 +819,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_carrier_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_carrier_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -841,8 +842,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_soldier_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_soldier_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -864,8 +865,8 @@
try {
LuaTable table(L); // Will pop the table eventually.
- EditorGameBase& egbase = get_egbase(L);
- egbase.mutable_tribes()->add_worker_type(table, egbase);
+ EditorGameBase* egbase = &get_egbase(L);
+ egbase->mutable_tribes()->add_worker_type(table, egbase);
} catch (std::exception& e) {
report_error(L, "%s", e.what());
}
@@ -896,6 +897,38 @@
return 0;
}
+
+/* RST
+ .. method:: add_custom_building{table}
+
+ Adds a custom building to a tribe, e.g. for use in a scenario.
+ The building must already be known to the tribes.
+ The table has the following entries:
+
+ **tribename**
+ *Mandatory*. The name of the tribe that this building will be added to.
+
+ **buildingname**
+ *Mandatory*. The name of the building to be added to the tribe.
+
+ :returns: :const:`0`
+*/
+int LuaTribes::add_custom_building(lua_State* L) {
+ if (lua_gettop(L) != 2) {
+ report_error(L, "Takes only one argument.");
+ }
+
+ try {
+ LuaTable table(L); // Will pop the table eventually.
+ EditorGameBase& egbase = get_egbase(L);
+ egbase.mutable_tribes()->add_custom_building(table);
+ } catch (std::exception& e) {
+ report_error(L, "%s", e.what());
+ }
+ return 0;
+}
+
+
/*
==========================================================
C METHODS
=== modified file 'src/scripting/lua_root.h'
--- src/scripting/lua_root.h 2017-06-24 08:47:46 +0000
+++ src/scripting/lua_root.h 2017-08-17 11:49:32 +0000
@@ -172,6 +172,7 @@
int new_soldier_type(lua_State* L);
int new_worker_type(lua_State* L);
int new_tribe(lua_State* L);
+ int add_custom_building(lua_State* L);
/*
* C methods
References