widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #05603
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
GunChleoc has proposed merging lp:~widelands-dev/widelands/editor_help into lp:widelands.
Commit message:
Exposed terrain and resource descriptions to the Lua interface and added tree and terrain help to the editor.
Requested reviews:
Widelands Developers (widelands-dev)
Related bugs:
Bug #1204482 in widelands: "Improve the help system for the editor"
https://bugs.launchpad.net/widelands/+bug/1204482
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/editor_help/+merge/283900
Added tree and terrain help to the editor.
The design is discussed in the forum:
https://wl.widelands.org/forum/topic/1870/
We are also thinking of making terrains on the map clickable to popup a smaller help window, or maybe adding it to the info tool, but that can be done in a separate branch.
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/editor_help into lp:widelands.
=== added directory 'scripting/editor'
=== added file 'scripting/editor/format_editor.lua'
--- scripting/editor/format_editor.lua 1970-01-01 00:00:00 +0000
+++ scripting/editor/format_editor.lua 2016-01-26 07:30:52 +0000
@@ -0,0 +1,27 @@
+include "scripting/formatting.lua"
+
+function picture_li(imagepath, text)
+ return "<rt image=" .. imagepath .. " image-align=left>" .. p(text) .. "</rt>"
+end
+
+function spacer()
+ return rt(p("font-size=3", ""))
+end
+
+-- RST
+-- .. function text_line(t1, t2[, imgstr = nil])
+--
+-- Creates a line of h3 formatted text followed by normal text and an image.
+--
+-- :arg t1: text in h3 format.
+-- :arg t2: text in p format.
+-- :arg imgstr: image aligned right.
+-- :returns: header followed by normal text and image.
+--
+function text_line(t1, t2, imgstr)
+ if imgstr then
+ return "<rt text-align=left image=" .. imgstr .. " image-align=right><p font-size=13 font-color=D1D1D1>" .. t1 .. "</p><p line-spacing=3 font-size=12>" .. t2 .. "<br></p><p font-size=8> <br></p></rt>"
+ else
+ return "<rt text-align=left><p font-size=13 font-color=D1D1D1>" .. t1 .. "</p><p line-spacing=3 font-size=12>" .. t2 .. "<br></p><p font-size=8> <br></p></rt>"
+ end
+end
=== added file 'scripting/editor/terrain_help.lua'
--- scripting/editor/terrain_help.lua 1970-01-01 00:00:00 +0000
+++ scripting/editor/terrain_help.lua 2016-01-26 07:30:52 +0000
@@ -0,0 +1,66 @@
+include "scripting/editor/format_editor.lua"
+
+return {
+ func = function(terrain_name)
+ set_textdomain("widelands")
+ local world = wl.World();
+ local terrain = wl.Editor():get_terrain_description(terrain_name)
+
+ local result = picture_li(terrain.representative_image, "")
+
+ -- Resources
+ local valid_resources = terrain.valid_resources_names
+ if (#valid_resources > 0) then
+ result = result .. spacer() .. rt(h2(_"Resources"))
+ if (#valid_resources > 0) then
+ -- TRANSLATORS: A header in the editor help
+ result = result .. rt(h3(ngettext("Valid Resource:", "Valid Resources:", #valid_resources)))
+ for count, resourcename in pairs(valid_resources) do
+ local valid_resource = wl.Editor():get_resource_description(resourcename)
+ result = result .. picture_li(valid_resource.representative_image, valid_resource.descname)
+ end
+ end
+
+ local default_resource_name = terrain.default_resource_name
+ if (default_resource_name ~= nil) then
+ local default_resource = wl.Editor():get_resource_description(default_resource_name)
+ -- TRANSLATORS: e.g. "5x Water"
+ result = result .. text_line(_"Default:", _"%1%x %2%":bformat(terrain.default_resource_amount, default_resource.descname), default_resource:editor_image(terrain.default_resource_amount))
+ end
+ end
+
+ -- Trees
+ local tree_list = {}
+ for i, tree_name in ipairs(world:immovable_descriptions("tree")) do
+ local probability = terrain:probability_to_grow(tree_name)
+ if (probability > 0.01) then
+ -- sort the trees by percentage
+ i = 1
+ while (tree_list[i] and (tree_list[i].probability_ > probability)) do
+ i = i + 1
+ end
+
+ for j = #tree_list, i, -1 do
+ tree_list[j+1] = tree_list[j]
+ end
+ tree_list[i] = {tree_name_ = tree_name, probability_ = probability}
+ end
+ end
+
+ local tree_string = ""
+ for k,v in ipairs(tree_list) do
+ local tree = wl.Editor():get_immovable_description(v.tree_name_)
+ tree_string = tree_string .. picture_li(tree.representative_image, tree.basename .. ("<br>%2.1f%%"):bformat(100 * v.probability_)) .. spacer()
+ end
+
+ -- TRANSLATORS: A header in the editor help
+ result = result .. spacer() .. rt(h2(_"Probability of trees growing")) .. spacer()
+
+ if (tree_string ~="") then
+ result = result .. tree_string
+ else
+ result = result .. rt(p(_"No trees will grow here."))
+ end
+ return result
+ end
+}
=== added file 'scripting/editor/tree_help.lua'
--- scripting/editor/tree_help.lua 1970-01-01 00:00:00 +0000
+++ scripting/editor/tree_help.lua 2016-01-26 07:30:52 +0000
@@ -0,0 +1,38 @@
+include "scripting/editor/format_editor.lua"
+
+return {
+ func = function(tree_name)
+ set_textdomain("widelands")
+ local world = wl.World();
+ local tree = wl.Editor():get_immovable_description(tree_name)
+ local result = picture_li(tree.representative_image, "")
+
+ -- TRANSLATORS: A header in the editor help. Terrains preferred by a type of tree.
+ result = result .. rt(p("font-size=3", "")) .. rt(h2(_"Preferred terrains")) .. spacer()
+ terrain_list = {}
+ for i, terrain_name in ipairs(world:terrain_descriptions()) do
+ local terrain = wl.Editor():get_terrain_description(terrain_name)
+ local probability = terrain:probability_to_grow(tree_name)
+ if (probability > 0.01) then
+ -- sort the terrains by percentage
+ i = 1
+ while (terrain_list[i] and (terrain_list[i].probability_ > probability)) do
+ i = i + 1
+ end
+
+ for j = #terrain_list, i, -1 do
+ terrain_list[j+1] = terrain_list[j]
+ end
+ terrain_list[i] = {terrain_name_ = terrain_name, probability_ = probability}
+ end
+ end
+
+ for k,v in ipairs(terrain_list) do
+ local terrain = wl.Editor():get_terrain_description(v.terrain_name_)
+ -- TRANSLATORS: Terrain name (Climate)
+ result = result .. picture_li(terrain.representative_image, (_"%1% (%2%)"):bformat(terrain.descname, terrain.editor_category.descname) .. "<br>" .. ("%2.1f%%"):bformat(100 * v.probability_)) .. spacer()
+ end
+
+ return result
+ end
+}
=== modified file 'src/editor/CMakeLists.txt'
--- src/editor/CMakeLists.txt 2016-01-14 22:17:50 +0000
+++ src/editor/CMakeLists.txt 2016-01-26 07:30:52 +0000
@@ -47,6 +47,8 @@
tools/editor_tool_action.h
tools/multi_select.h
ui_menus/categorized_item_selection_menu.h
+ ui_menus/editor_help.cc
+ ui_menus/editor_help.h
ui_menus/editor_main_menu.cc
ui_menus/editor_main_menu.h
ui_menus/editor_main_menu_load_map.cc
=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc 2016-01-16 15:57:31 +0000
+++ src/editor/editorinteractive.cc 2016-01-26 07:30:52 +0000
@@ -30,6 +30,7 @@
#include "base/scoped_timer.h"
#include "base/warning.h"
#include "editor/tools/editor_delete_immovable_tool.h"
+#include "editor/ui_menus/editor_help.h"
#include "editor/ui_menus/editor_main_menu.h"
#include "editor/ui_menus/editor_main_menu_load_map.h"
#include "editor/ui_menus/editor_main_menu_save_map.h"
@@ -69,7 +70,7 @@
// Ok, we're doing something. First remove the current overlays.
if (note.old_resource != Widelands::kNoResource) {
const std::string str =
- world.get_resource(note.old_resource)->get_editor_pic(note.old_amount);
+ world.get_resource(note.old_resource)->editor_image(note.old_amount);
const Image* pic = g_gr->images().get(str);
field_overlay_manager->remove_overlay(note.fc, pic);
}
@@ -78,7 +79,7 @@
const auto resource_type = note.fc.field->get_resources();
if (amount > 0 && resource_type != Widelands::kNoResource) {
const std::string str =
- world.get_resource(note.fc.field->get_resources())->get_editor_pic(amount);
+ world.get_resource(note.fc.field->get_resources())->editor_image(amount);
const Image* pic = g_gr->images().get(str);
field_overlay_manager->register_overlay(note.fc, pic, 0);
}
@@ -123,7 +124,10 @@
("editor_undo", "undo", _("Undo"))),
redo_
(INIT_BUTTON
- ("editor_redo", "redo", _("Redo")))
+ ("editor_redo", "redo", _("Redo"))),
+ toggle_help_
+ (INIT_BUTTON
+ ("menu_help", "help", _("Help")))
{
toggle_main_menu_.sigclicked.connect(boost::bind(&EditorInteractive::toggle_mainmenu, this));
toggle_tool_menu_.sigclicked.connect(boost::bind(&EditorInteractive::tool_menu_btn, this));
@@ -133,6 +137,7 @@
toggle_player_menu_.sigclicked.connect(boost::bind(&EditorInteractive::toggle_playermenu, this));
undo_.sigclicked.connect([this] {history_->undo_action(egbase().world());});
redo_.sigclicked.connect([this] {history_->redo_action(egbase().world());});
+ toggle_help_.sigclicked.connect(boost::bind(&EditorInteractive::toggle_help, this));
toolbar_.set_layout_toplevel(true);
toolbar_.add(&toggle_main_menu_, UI::Box::AlignLeft);
@@ -143,6 +148,7 @@
toolbar_.add(&toggle_player_menu_, UI::Box::AlignLeft);
toolbar_.add(&undo_, UI::Box::AlignLeft);
toolbar_.add(&redo_, UI::Box::AlignLeft);
+ toolbar_.add(&toggle_help_, UI::Box::AlignLeft);
adjust_toolbar_position();
#ifndef NDEBUG
@@ -184,7 +190,7 @@
iterate_Map_FCoords(map, extent, fc) {
if (uint8_t const amount = fc.field->get_resources_amount()) {
const std::string& immname =
- egbase().world().get_resource(fc.field->get_resources())->get_editor_pic(amount);
+ egbase().world().get_resource(fc.field->get_resources())->editor_image(amount);
if (immname.size())
mutable_field_overlay_manager()->register_overlay(fc, g_gr->images().get(immname), 4);
}
@@ -349,6 +355,14 @@
}
}
+void EditorInteractive::toggle_help() {
+ if (helpmenu_.window)
+ delete helpmenu_.window;
+ else
+ new EditorHelp(*this, helpmenu_);
+}
+
+
bool EditorInteractive::handle_key(bool const down, SDL_Keysym const code) {
bool handled = InteractiveBase::handle_key(down, code);
@@ -476,6 +490,12 @@
history_->redo_action(egbase().world());
handled = true;
break;
+
+ case SDLK_F1:
+ toggle_help();
+ handled = true;
+ break;
+
default:
break;
}
=== modified file 'src/editor/editorinteractive.h'
--- src/editor/editorinteractive.h 2016-01-16 15:57:31 +0000
+++ src/editor/editorinteractive.h 2016-01-26 07:30:52 +0000
@@ -150,6 +150,7 @@
void toolsize_menu_btn();
void toggle_mainmenu();
void toggle_playermenu();
+ void toggle_help();
// state variables
bool need_save_;
@@ -173,6 +174,7 @@
UI::UniqueWindow::Registry immovablemenu_;
UI::UniqueWindow::Registry bobmenu_;
UI::UniqueWindow::Registry resourcesmenu_;
+ UI::UniqueWindow::Registry helpmenu_;
UI::Button toggle_main_menu_;
UI::Button toggle_tool_menu_;
@@ -182,6 +184,7 @@
UI::Button toggle_player_menu_;
UI::Button undo_;
UI::Button redo_;
+ UI::Button toggle_help_;
};
#endif // end of include guard: WL_EDITOR_EDITORINTERACTIVE_H
=== added file 'src/editor/ui_menus/editor_help.cc'
--- src/editor/ui_menus/editor_help.cc 1970-01-01 00:00:00 +0000
+++ src/editor/ui_menus/editor_help.cc 2016-01-26 07:30:52 +0000
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2015-2016 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "editor/ui_menus/editor_help.h"
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <boost/format.hpp>
+
+#include "base/i18n.h"
+#include "editor/editorinteractive.h"
+#include "graphic/graphic.h"
+#include "graphic/texture.h"
+#include "io/filesystem/layered_filesystem.h"
+#include "logic/map_objects/world/editor_category.h"
+#include "logic/map_objects/world/terrain_description.h"
+#include "logic/map_objects/world/world.h"
+#include "scripting/lua_interface.h"
+#include "scripting/lua_table.h"
+
+#define WINDOW_WIDTH std::min(700, g_gr->get_xres() - 40)
+#define WINDOW_HEIGHT std::min(550, g_gr->get_yres() - 40)
+
+constexpr int kPadding = 5;
+constexpr int kTabHeight = 35;
+
+using namespace Widelands;
+
+inline EditorInteractive& EditorHelp::eia() const {
+ return dynamic_cast<EditorInteractive&>(*get_parent());
+}
+
+namespace {
+const std::string heading(const std::string& text) {
+ return ((boost::format("<rt><p font-size=18 font-weight=bold font-color=D1D1D1>"
+ "%s<br></p><p font-size=8> <br></p></rt>") %
+ text).str());
+}
+} // namespace
+
+EditorHelp::EditorHelp(EditorInteractive& parent, UI::UniqueWindow::Registry& registry)
+ : UI::UniqueWindow(&parent, "encyclopedia", ®istry, WINDOW_WIDTH, WINDOW_HEIGHT, _("Help")),
+ tabs_(this, 0, 0, nullptr) {
+
+ const int contents_height = WINDOW_HEIGHT - kTabHeight - 2 * kPadding;
+ const int contents_width = WINDOW_WIDTH / 2 - 1.5 * kPadding;
+
+ std::vector<std::unique_ptr<HelpTab>> tab_definitions;
+
+ tab_definitions.push_back(
+ std::unique_ptr<HelpTab>(new HelpTab("terrains",
+ "pics/editor_menu_tool_set_terrain.png",
+ _("Terrains"),
+ "scripting/editor/terrain_help.lua",
+ HelpEntry::Type::kTerrain)));
+
+ tab_definitions.push_back(
+ std::unique_ptr<HelpTab>(new HelpTab("trees",
+ "world/immovables/trees/alder/old/idle_0.png",
+ _("Trees"),
+ "scripting/editor/tree_help.lua",
+ HelpEntry::Type::kTree)));
+
+ for (const auto& tab : tab_definitions) {
+ // Make sure that all paths exist
+ if (!g_fs->file_exists(tab->script_path)) {
+ throw wexception("Script path %s for tab %s does not exist!",
+ tab->script_path.c_str(),
+ tab->key.c_str());
+ }
+ if (!g_fs->file_exists(tab->image_filename)) {
+ throw wexception("Image path %s for tab %s does not exist!",
+ tab->image_filename.c_str(),
+ tab->key.c_str());
+ }
+
+ wrapper_boxes_.insert(std::make_pair(
+ tab->key, std::unique_ptr<UI::Box>(new UI::Box(&tabs_, 0, 0, UI::Box::Horizontal))));
+
+ boxes_.insert(
+ std::make_pair(tab->key,
+ std::unique_ptr<UI::Box>(new UI::Box(
+ wrapper_boxes_.at(tab->key).get(), 0, 0, UI::Box::Horizontal))));
+
+ lists_.insert(
+ std::make_pair(tab->key,
+ std::unique_ptr<UI::Listselect<Widelands::DescriptionIndex>>(
+ new UI::Listselect<Widelands::DescriptionIndex>(
+ boxes_.at(tab->key).get(), 0, 0, contents_width, contents_height))));
+ lists_.at(tab->key)->selected.connect(
+ boost::bind(&EditorHelp::entry_selected, this, tab->key, tab->script_path, tab->type));
+
+ contents_.insert(
+ std::make_pair(tab->key,
+ std::unique_ptr<UI::MultilineTextarea>(new UI::MultilineTextarea(
+ boxes_.at(tab->key).get(), 0, 0, contents_width, contents_height))));
+
+ boxes_.at(tab->key)->add(lists_.at(tab->key).get(), UI::Align_Left);
+ boxes_.at(tab->key)->add_space(kPadding);
+ boxes_.at(tab->key)->add(contents_.at(tab->key).get(), UI::Align_Left);
+
+ wrapper_boxes_.at(tab->key)->add_space(kPadding);
+ wrapper_boxes_.at(tab->key)->add(boxes_.at(tab->key).get(), UI::Align_Left);
+
+ tabs_.add("editor_help_" + tab->key,
+ g_gr->images().get(tab->image_filename),
+ wrapper_boxes_.at(tab->key).get(),
+ tab->tooltip);
+ }
+ tabs_.set_size(WINDOW_WIDTH, WINDOW_HEIGHT);
+
+ fill_terrains();
+ fill_trees();
+
+ if (get_usedefaultpos()) {
+ center_to_parent();
+ }
+}
+
+void EditorHelp::fill_entries(const char* key, std::vector<HelpEntry>& entries) {
+ std::sort(entries.begin(), entries.end());
+ for (uint32_t i = 0; i < entries.size(); i++) {
+ HelpEntry cur = entries[i];
+ lists_.at(key)->add(cur.descname, cur.index, cur.icon);
+ }
+ lists_.at(key)->select(0);
+}
+
+void EditorHelp::fill_terrains() {
+ const World& world = eia().egbase().world();
+ std::vector<HelpEntry> entries;
+
+ for (Widelands::DescriptionIndex i = 0; i < world.terrains().size(); ++i) {
+ const TerrainDescription& terrain = world.terrain_descr(i);
+ upcast(Image const, icon, &terrain.get_texture(0));
+ /** TRANSLATORS: Terrain name + editor category, e.g. Steppe (Summer) */
+ HelpEntry entry(i, (boost::format(_("%1% (%2%)"))
+ % terrain.descname().c_str()
+ % terrain.editor_category().descname()).str(), icon);
+ entries.push_back(entry);
+ }
+ fill_entries("terrains", entries);
+}
+
+void EditorHelp::fill_trees() {
+ const World& world = eia().egbase().world();
+ std::vector<HelpEntry> entries;
+
+ for (Widelands::DescriptionIndex i = 0; i < world.get_nr_immovables(); ++i) {
+ const ImmovableDescr* immovable = world.get_immovable_descr(i);
+ uint32_t attribute_id = immovable->get_attribute_id("tree");
+ if (immovable->has_attribute(attribute_id)) {
+ const Image* icon = immovable->representative_image();
+ HelpEntry entry(i, immovable->basename(), icon);
+ entries.push_back(entry);
+ }
+ }
+ fill_entries("trees", entries);
+}
+
+void EditorHelp::entry_selected(const std::string& key,
+ const std::string& script_path,
+ const HelpEntry::Type& type) {
+ try {
+ std::unique_ptr<LuaTable> table(eia().egbase().lua().run_script(script_path));
+ std::unique_ptr<LuaCoroutine> cr(table->get_coroutine("func"));
+
+ std::string descname = "";
+
+ switch (type) {
+ case (HelpEntry::Type::kTerrain): {
+ const TerrainDescription& descr =
+ eia().egbase().world().terrain_descr(lists_.at(key)->get_selected());
+ /** TRANSLATORS: Terrain name + editor category, e.g. Steppe (Summer) */
+ descname = (boost::format(_("%1% (%2%)"))
+ % descr.descname().c_str()
+ % descr.editor_category().descname()).str();
+ cr->push_arg(descr.name());
+ break;
+ }
+ case (HelpEntry::Type::kTree): {
+ const ImmovableDescr* descr =
+ eia().egbase().world().get_immovable_descr(lists_.at(key)->get_selected());
+ descname = descr->basename();
+ cr->push_arg(descr->name());
+ break;
+ }
+ default:
+ throw wexception("EditorHelp: No Type defined for tab.");
+ }
+
+ cr->resume();
+ const std::string help_text = cr->pop_string();
+ contents_.at(key)->set_text((boost::format("%s%s") % heading(descname) % help_text).str());
+
+ } catch (LuaError& err) {
+ contents_.at(key)->set_text(err.what());
+ }
+ contents_.at(key)->scroll_to_top();
+}
=== added file 'src/editor/ui_menus/editor_help.h'
--- src/editor/ui_menus/editor_help.h 1970-01-01 00:00:00 +0000
+++ src/editor/ui_menus/editor_help.h 2016-01-26 07:30:52 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015-2016 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WL_EDITOR_UI_MENUS_EDITOR_HELP_H
+#define WL_EDITOR_UI_MENUS_EDITOR_HELP_H
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "logic/map_objects/map_object.h"
+#include "ui_basic/box.h"
+#include "ui_basic/listselect.h"
+#include "ui_basic/multilinetextarea.h"
+#include "ui_basic/table.h"
+#include "ui_basic/tabpanel.h"
+#include "ui_basic/unique_window.h"
+#include "ui_basic/window.h"
+
+class EditorInteractive;
+
+struct EditorHelp : public UI::UniqueWindow {
+ EditorHelp(EditorInteractive&, UI::UniqueWindow::Registry&);
+
+private:
+ struct HelpEntry {
+ enum class Type {
+ kTerrain,
+ kTree
+ };
+
+ HelpEntry(const HelpEntry& other) : HelpEntry(other.index, other.descname, other.icon) {
+ }
+ HelpEntry(const Widelands::DescriptionIndex _index,
+ const std::string& _descname,
+ const Image* _icon)
+ : index(_index), descname(_descname), icon(_icon) {
+ }
+ Widelands::DescriptionIndex index;
+ std::string descname;
+ const Image* icon;
+
+ bool operator<(const HelpEntry other) const {
+ return descname < other.descname;
+ }
+ };
+
+ struct HelpTab {
+ HelpTab(const std::string& _key,
+ const std::string& _image_filename,
+ const std::string& _tooltip,
+ const std::string& _script_path,
+ const EditorHelp::HelpEntry::Type _type)
+ : key(_key),
+ image_filename(_image_filename),
+ tooltip(_tooltip),
+ script_path(_script_path),
+ type(_type) {
+ }
+ const std::string key;
+ const std::string image_filename;
+ const std::string tooltip;
+ const std::string script_path;
+ const EditorHelp::HelpEntry::Type type;
+ };
+
+ EditorInteractive& eia() const;
+
+ // Fill table of contents
+ void fill_entries(const char* key, std::vector<HelpEntry>& entries);
+ void fill_terrains();
+ void fill_trees();
+
+ // Update contents when an entry is selected
+ void entry_selected(const std::string& key,
+ const std::string& script_path,
+ const HelpEntry::Type& type);
+
+ // UI elements
+ UI::TabPanel tabs_;
+
+ // Wrapper boxes so we can add some padding
+ std::map<std::string, std::unique_ptr<UI::Box>> wrapper_boxes_;
+ // Main contents boxes for each tab
+ std::map<std::string, std::unique_ptr<UI::Box>> boxes_;
+ // A tab's table of contents
+ std::map<std::string, std::unique_ptr<UI::Listselect<Widelands::DescriptionIndex>>> lists_;
+ // The contents shown when an entry is selected in a tab
+ std::map<std::string, std::unique_ptr<UI::MultilineTextarea>> contents_;
+};
+
+#endif // end of include guard: WL_EDITOR_UI_MENUS_EDITOR_HELP_H
=== modified file 'src/editor/ui_menus/editor_tool_change_resources_options_menu.cc'
--- src/editor/ui_menus/editor_tool_change_resources_options_menu.cc 2016-01-18 19:35:25 +0000
+++ src/editor/ui_menus/editor_tool_change_resources_options_menu.cc 2016-01-26 07:30:52 +0000
@@ -139,7 +139,7 @@
// Find the maximal width and height for the resource pictures.
int resource_pic_max_width = 0, resource_pic_max_height = 0;
for (Widelands::DescriptionIndex i = 0; i < nr_resources; ++i) {
- const Image* pic = g_gr->images().get(world.get_resource(i)->get_editor_pic(100000));
+ const Image* pic = g_gr->images().get(world.get_resource(i)->representative_image());
resource_pic_max_width = std::max(resource_pic_max_width, pic->width());
resource_pic_max_height = std::max(resource_pic_max_height, pic->height());
}
@@ -170,7 +170,7 @@
m_radiogroup.add_button
(this,
pos,
- g_gr->images().get(world.get_resource(i)->get_editor_pic(100000)));
+ g_gr->images().get(world.get_resource(i)->representative_image()));
}
pos.y += resource_pic_max_height + vspacing();
=== modified file 'src/logic/field.h'
--- src/logic/field.h 2016-01-14 22:09:24 +0000
+++ src/logic/field.h 2016-01-26 07:30:52 +0000
@@ -134,7 +134,9 @@
uint16_t get_caps() const {return caps;}
Terrains get_terrains() const {return terrains;}
+ // The terrain on the downward triangle
DescriptionIndex terrain_d () const {return terrains.d;}
+ // The terrain on the triangle to the right
DescriptionIndex terrain_r () const {return terrains.r;}
void set_terrains(const Terrains & i) {terrains = i;}
void set_terrain
=== modified file 'src/logic/map_objects/immovable.cc'
--- src/logic/map_objects/immovable.cc 2016-01-17 19:54:32 +0000
+++ src/logic/map_objects/immovable.cc 2016-01-26 07:30:52 +0000
@@ -189,7 +189,8 @@
MapObjectDescr(
MapObjectType::IMMOVABLE, table.get_string("name"), init_descname, table),
m_size(BaseImmovable::NONE),
- owner_type_(input_type) {
+ owner_type_(input_type),
+ editor_category_(nullptr) {
if (!is_animation_known("idle")) {
throw GameDataError("Immovable %s has no idle animation", table.get_string("name").c_str());
}
@@ -203,8 +204,23 @@
}
if (table.has_key("attributes")) {
- add_attributes(table.get_table("attributes")->
- array_entries<std::string>(), {MapObject::Attribute::RESI});
+ std::vector<std::string> attributes = table.get_table("attributes")->array_entries<std::string>();
+ add_attributes(attributes, {MapObject::Attribute::RESI});
+
+ // Old trees get an extra basename so we can use it in help lists.
+ bool is_tree = false;
+ for (const std::string& attribute : attributes) {
+ if (attribute == "tree") {
+ is_tree = true;
+ break;
+ }
+ }
+ if (is_tree) {
+ if (!table.has_key("basename")) {
+ throw wexception("Immovable '%s' with type 'tree' must define a basename", name().c_str());
+ }
+ basename_ = table.get_string("basename");
+ }
}
std::unique_ptr<LuaTable> programs = table.get_table("programs");
@@ -247,6 +263,10 @@
}
}
+bool ImmovableDescr::has_editor_category() const {
+ return editor_category_ != nullptr;
+}
+
const EditorCategory& ImmovableDescr::editor_category() const {
return *editor_category_;
}
=== modified file 'src/logic/map_objects/immovable.h'
--- src/logic/map_objects/immovable.h 2015-11-29 09:43:15 +0000
+++ src/logic/map_objects/immovable.h 2016-01-26 07:30:52 +0000
@@ -129,10 +129,15 @@
const Buildcost & buildcost() const {return m_buildcost;}
+ // Returns whether this immovable has an editor category. E.g. Tribe immovables never have one.
+ bool has_editor_category() const;
// Returns the editor category.
const EditorCategory& editor_category() const;
+ // A basic localized name for the immovable, used by trees
+ const std::string& basename() const {return basename_;}
+
// Every immovable that can 'grow' needs to have terrain affinity defined,
// all others do not. Returns true if this one has it defined.
bool has_terrain_affinity() const;
@@ -152,6 +157,8 @@
/// \see ActConstruction
Buildcost m_buildcost;
+ std::string basename_;
+
private:
// Common constructor functions for tribes and world.
ImmovableDescr(const std::string& init_descname, const LuaTable&, MapObjectDescr::OwnerType type);
=== modified file 'src/logic/map_objects/terrain_affinity.cc'
--- src/logic/map_objects/terrain_affinity.cc 2015-11-28 22:29:26 +0000
+++ src/logic/map_objects/terrain_affinity.cc 2016-01-26 07:30:52 +0000
@@ -37,6 +37,30 @@
return a * a;
}
+// Helper function for probability_to_grow
+// Calculates the probability to grow for the given affinity and terrain values
+double calculate_probability_to_grow(const TerrainAffinity& affinity,
+ double terrain_humidity,
+ double terrain_fertility,
+ double terrain_temperature) {
+
+ constexpr double kHumidityWeight = 0.500086642549548;
+ constexpr double kFertilityWeight = 0.5292268046607387;
+ constexpr double kTemperatureWeight = 61.31300863608306;
+
+ const double sigma_humidity = (1. - affinity.pickiness());
+ const double sigma_temperature = (1. - affinity.pickiness());
+ const double sigma_fertility = (1. - affinity.pickiness());
+
+ return exp((-pow2((affinity.preferred_fertility() - terrain_fertility) /
+ (kFertilityWeight * sigma_fertility)) -
+ pow2((affinity.preferred_humidity() - terrain_humidity) /
+ (kHumidityWeight * sigma_humidity)) -
+ pow2((affinity.preferred_temperature() - terrain_temperature) /
+ (kTemperatureWeight * sigma_temperature))) /
+ 2);
+}
+
} // namespace
TerrainAffinity::TerrainAffinity(const LuaTable& table, const std::string& immovable_name)
@@ -111,21 +135,20 @@
average(ln.field->terrain_r());
}
- constexpr double kHumidityWeight = 0.500086642549548;
- constexpr double kFertilityWeight = 0.5292268046607387;
- constexpr double kTemperatureWeight = 61.31300863608306;
-
- const double sigma_humidity = (1. - affinity.pickiness());
- const double sigma_temperature = (1. - affinity.pickiness());
- const double sigma_fertility = (1. - affinity.pickiness());
-
- return exp((-pow2((affinity.preferred_fertility() - terrain_fertility) /
- (kFertilityWeight * sigma_fertility)) -
- pow2((affinity.preferred_humidity() - terrain_humidity) /
- (kHumidityWeight * sigma_humidity)) -
- pow2((affinity.preferred_temperature() - terrain_temperature) /
- (kTemperatureWeight * sigma_temperature))) /
- 2);
+ return calculate_probability_to_grow(affinity,
+ terrain_humidity,
+ terrain_fertility,
+ terrain_temperature);
+}
+
+
+double probability_to_grow(const TerrainAffinity& affinity,
+ const TerrainDescription& terrain) {
+
+ return calculate_probability_to_grow(affinity,
+ terrain.humidity(),
+ terrain.fertility(),
+ terrain.temperature());
}
} // namespace Widelands
=== modified file 'src/logic/map_objects/terrain_affinity.h'
--- src/logic/map_objects/terrain_affinity.h 2015-11-28 22:29:26 +0000
+++ src/logic/map_objects/terrain_affinity.h 2016-01-26 07:30:52 +0000
@@ -69,6 +69,10 @@
(const TerrainAffinity& immovable_affinity, const FCoords& fcoords,
const Map& map, const DescriptionMaintainer<TerrainDescription>& terrains);
+// Probability to grow for a single terrain
+double probability_to_grow
+ (const TerrainAffinity& immovable_affinity, const TerrainDescription& terrain);
+
} // namespace Widelands
#endif // end of include guard: WL_LOGIC_MAP_OBJECTS_TERRAIN_AFFINITY_H
=== modified file 'src/logic/map_objects/tribes/worker.cc'
--- src/logic/map_objects/tribes/worker.cc 2016-01-17 19:54:32 +0000
+++ src/logic/map_objects/tribes/worker.cc 2016-01-26 07:30:52 +0000
@@ -960,7 +960,7 @@
if (rdescr && rdescr->detectable() && position.field->get_resources_amount()) {
const std::string message =
(boost::format("<rt image=%s><p font-face=serif font-size=14>%s</p></rt>")
- % rdescr->get_editor_pic(rdescr->max_amount())
+ % rdescr->representative_image()
% _("A geologist found resources.")).str();
Message::Type message_type = Message::Type::kGeologists;
=== modified file 'src/logic/map_objects/world/resource_description.cc'
--- src/logic/map_objects/world/resource_description.cc 2015-11-28 22:29:26 +0000
+++ src/logic/map_objects/world/resource_description.cc 2016-01-26 07:30:52 +0000
@@ -31,7 +31,8 @@
: name_(table.get_string("name")),
descname_(table.get_string("descname")),
detectable_(table.get_bool("detectable")),
- max_amount_(table.get_int("max_amount")) {
+ max_amount_(table.get_int("max_amount")),
+ representative_image_(table.get_string("representative_image")) {
std::unique_ptr<LuaTable> st = table.get_table("editor_pictures");
const std::set<int> keys = st->keys<int>();
@@ -44,7 +45,7 @@
}
}
-const std::string & ResourceDescription::get_editor_pic
+const std::string & ResourceDescription::editor_image
(uint32_t const amount) const
{
uint32_t bestmatch = 0;
=== modified file 'src/logic/map_objects/world/resource_description.h'
--- src/logic/map_objects/world/resource_description.h 2015-11-28 22:29:26 +0000
+++ src/logic/map_objects/world/resource_description.h 2016-01-26 07:30:52 +0000
@@ -53,13 +53,17 @@
/// Returns the path to the image that should be used in the editor to
/// represent an 'amount' of this resource.
- const std::string& get_editor_pic(uint32_t amount) const;
+ const std::string& editor_image(uint32_t amount) const;
+
+ /// Returns the path to the image that should be used in menus to represent this resource
+ const std::string& representative_image() const {return representative_image_;}
private:
const std::string name_;
const std::string descname_;
const bool detectable_;
const int32_t max_amount_;
+ const std::string representative_image_;
std::vector<EditorPicture> editor_pictures_;
DISALLOW_COPY_AND_ASSIGN(ResourceDescription);
=== modified file 'src/logic/map_objects/world/terrain_description.cc'
--- src/logic/map_objects/world/terrain_description.cc 2016-01-17 09:55:27 +0000
+++ src/logic/map_objects/world/terrain_description.cc 2016-01-26 07:30:52 +0000
@@ -222,6 +222,10 @@
return valid_resources_.size();
}
+std::vector<uint8_t> TerrainDescription::valid_resources() const {
+ return valid_resources_;
+}
+
bool TerrainDescription::is_resource_valid(const int res) const {
for (const uint8_t resource_index : valid_resources_) {
if (resource_index == res) {
=== modified file 'src/logic/map_objects/world/terrain_description.h'
--- src/logic/map_objects/world/terrain_description.h 2016-01-13 07:27:55 +0000
+++ src/logic/map_objects/world/terrain_description.h 2016-01-26 07:30:52 +0000
@@ -94,6 +94,9 @@
/// Returns the number of valid resources.
int get_num_valid_resources() const;
+ /// Returns the the valid resources.
+ std::vector<uint8_t> valid_resources() const;
+
/// Returns true if this resource can be found in this terrain type.
bool is_resource_valid(int32_t res) const;
=== modified file 'src/scripting/lua_bases.cc'
--- src/scripting/lua_bases.cc 2015-11-28 22:29:26 +0000
+++ src/scripting/lua_bases.cc 2016-01-26 07:30:52 +0000
@@ -27,6 +27,7 @@
#include "logic/map_objects/tribes/tribe_descr.h"
#include "logic/map_objects/tribes/tribes.h"
#include "logic/map_objects/tribes/ware_descr.h"
+#include "logic/map_objects/world/world.h"
#include "logic/player.h"
#include "scripting/factory.h"
#include "scripting/globals.h"
@@ -78,10 +79,13 @@
const char LuaEditorGameBase::className[] = "EditorGameBase";
const MethodType<LuaEditorGameBase> LuaEditorGameBase::Methods[] = {
+ METHOD(LuaEditorGameBase, get_immovable_description),
METHOD(LuaEditorGameBase, get_building_description),
METHOD(LuaEditorGameBase, get_tribe_description),
METHOD(LuaEditorGameBase, get_ware_description),
METHOD(LuaEditorGameBase, get_worker_description),
+ METHOD(LuaEditorGameBase, get_resource_description),
+ METHOD(LuaEditorGameBase, get_terrain_description),
{nullptr, nullptr},
};
const PropertyType<LuaEditorGameBase> LuaEditorGameBase::Properties[] = {
@@ -150,6 +154,38 @@
*/
/* RST
+ .. function:: get_immovable_description(immovable_name)
+
+ :arg immovable_name: the name of the immovable
+
+ Registers an immovable description so Lua can reference it from the editor.
+
+ (RO) The :class:`~wl.Game.Immovable_description`.
+*/
+int LuaEditorGameBase::get_immovable_description(lua_State* L) {
+ if (lua_gettop(L) != 2) {
+ report_error(L, "Wrong number of arguments");
+ }
+ const std::string immovable_name = luaL_checkstring(L, 2);
+ const World& world = get_egbase(L).world();
+ DescriptionIndex idx = world.get_immovable_index(immovable_name);
+ if (idx != INVALID_INDEX) {
+ const ImmovableDescr* descr = world.get_immovable_descr(idx);
+ return to_lua<LuaMaps::LuaImmovableDescription>(L, new LuaMaps::LuaImmovableDescription(descr));
+ } else {
+ const Tribes& tribes = get_egbase(L).tribes();
+ idx = tribes.immovable_index(immovable_name);
+ if (!tribes.immovable_exists(idx)) {
+ report_error(L, "Immovable %s does not exist", immovable_name.c_str());
+ }
+ const ImmovableDescr* descr = tribes.get_immovable_descr(idx);
+ return to_lua<LuaMaps::LuaImmovableDescription>(L, new LuaMaps::LuaImmovableDescription(descr));
+ }
+ return 0;
+}
+
+
+/* RST
.. function:: get_building_description(building_description.name)
:arg building_name: the name of the building
@@ -244,6 +280,53 @@
return LuaMaps::upcasted_map_object_descr_to_lua(L, worker_description);
}
+/* RST
+ .. function:: get_resource_description(resource_name)
+
+ :arg resource_name: the name of the resource
+
+ Registers a resource description so Lua can reference it from the editor.
+
+ (RO) The :class:`~wl.Game.Resource_description`.
+*/
+int LuaEditorGameBase::get_resource_description(lua_State* L) {
+ if (lua_gettop(L) != 2) {
+ report_error(L, "Wrong number of arguments");
+ }
+ const std::string resource_name = luaL_checkstring(L, 2);
+ const World& world = get_egbase(L).world();
+ DescriptionIndex idx = world.get_resource(resource_name.c_str());
+
+ if (idx == INVALID_INDEX) {
+ report_error(L, "Resource %s does not exist", resource_name.c_str());
+ }
+
+ const ResourceDescription* descr = world.get_resource(idx);
+ return to_lua<LuaMaps::LuaResourceDescription>(L, new LuaMaps::LuaResourceDescription(descr));
+}
+
+/* RST
+ .. function:: get_terrain_description(terrain_name)
+
+ :arg terrain_name: the name of the terrain
+
+ Registers a terrain description so Lua can reference it from the editor.
+
+ (RO) The :class:`~wl.Game.Terrain_description`.
+*/
+int LuaEditorGameBase::get_terrain_description(lua_State* L) {
+ if (lua_gettop(L) != 2) {
+ report_error(L, "Wrong number of arguments");
+ }
+ const std::string terrain_name = luaL_checkstring(L, 2);
+ const TerrainDescription* descr = get_egbase(L).world().get_ter(terrain_name.c_str());
+ if (!descr) {
+ report_error(L, "Terrain %s does not exist", terrain_name.c_str());
+ }
+ return to_lua<LuaMaps::LuaTerrainDescription>(L, new LuaMaps::LuaTerrainDescription(descr));
+}
+
+
/*
==========================================================
C METHODS
=== modified file 'src/scripting/lua_bases.h'
--- src/scripting/lua_bases.h 2015-04-11 08:58:15 +0000
+++ src/scripting/lua_bases.h 2016-01-26 07:30:52 +0000
@@ -58,10 +58,13 @@
/*
* Lua methods
*/
+ int get_immovable_description(lua_State * L);
int get_building_description(lua_State * L);
int get_tribe_description(lua_State * L);
int get_ware_description(lua_State * L);
int get_worker_description(lua_State * L);
+ int get_resource_description(lua_State * L);
+ int get_terrain_description(lua_State * L);
/*
* C methods
=== modified file 'src/scripting/lua_map.cc'
--- src/scripting/lua_map.cc 2016-01-24 17:01:59 +0000
+++ src/scripting/lua_map.cc 2016-01-26 07:30:52 +0000
@@ -31,11 +31,13 @@
#include "logic/findimmovable.h"
#include "logic/map_objects/checkstep.h"
#include "logic/map_objects/immovable.h"
+#include "logic/map_objects/terrain_affinity.h"
#include "logic/map_objects/tribes/carrier.h"
#include "logic/map_objects/tribes/ship.h"
#include "logic/map_objects/tribes/soldier.h"
#include "logic/map_objects/tribes/tribes.h"
#include "logic/map_objects/tribes/warelist.h"
+#include "logic/map_objects/world/editor_category.h"
#include "logic/map_objects/world/resource_description.h"
#include "logic/map_objects/world/terrain_description.h"
#include "logic/map_objects/world/world.h"
@@ -605,6 +607,8 @@
return CAST_TO_LUA(WorkerDescr, LuaWorkerDescription);
case MapObjectType::SOLDIER:
return CAST_TO_LUA(WorkerDescr, LuaWorkerDescription);
+ case MapObjectType::IMMOVABLE:
+ return CAST_TO_LUA(ImmovableDescr, LuaImmovableDescription);
default:
return CAST_TO_LUA(MapObjectDescr, LuaMapObjectDescription);
}
@@ -1406,6 +1410,168 @@
return 1;
}
+
+/* RST
+BuildingDescription
+-------------------
+
+.. class:: LuaImmovableDescription
+
+ A static description of a base immovable, so it can be used in help files
+ without having to access an actual immovalbe on the map.
+ See also class MapObjectDescription for more properties.
+*/
+const char LuaImmovableDescription::className[] = "ImmovableDescription";
+const MethodType<LuaImmovableDescription> LuaImmovableDescription::Methods[] = {
+ {nullptr, nullptr},
+};
+const PropertyType<LuaImmovableDescription> LuaImmovableDescription::Properties[] = {
+ PROP_RO(LuaImmovableDescription, basename),
+ PROP_RO(LuaImmovableDescription, build_cost),
+ PROP_RO(LuaImmovableDescription, editor_category),
+ PROP_RO(LuaImmovableDescription, has_terrain_affinity),
+ PROP_RO(LuaImmovableDescription, pickiness),
+ PROP_RO(LuaImmovableDescription, preferred_fertility),
+ PROP_RO(LuaImmovableDescription, preferred_humidity),
+ PROP_RO(LuaImmovableDescription, preferred_temperature),
+ PROP_RO(LuaImmovableDescription, owner_type),
+ PROP_RO(LuaImmovableDescription, size),
+ {nullptr, nullptr, nullptr},
+};
+
+
+void LuaImmovableDescription::__persist(lua_State* L) {
+ const ImmovableDescr* descr = get();
+ PERS_STRING("name", descr->name());
+}
+
+void LuaImmovableDescription::__unpersist(lua_State* L) {
+ std::string name;
+ UNPERS_STRING("name", name);
+ const World& world = get_egbase(L).world();
+ DescriptionIndex idx = world.get_immovable_index(name);
+ if (idx == INVALID_INDEX) {
+ throw LuaError((boost::format("Immovable '%s' doesn't exist.") % name).str());
+ }
+ set_description_pointer(world.get_immovable_descr(idx));
+}
+
+
+/* RST
+ .. attribute:: the basename of a tree for editor lists
+
+ (RO) the basename of the immovable, or an empty string if it has none.
+*/
+int LuaImmovableDescription::get_basename(lua_State * L) {
+ lua_pushstring(L, get()->basename());
+ return 1;
+}
+
+
+/* RST
+ .. attribute:: build_cost
+
+ (RO) a list of ware build cost for the immovable.
+*/
+int LuaImmovableDescription::get_build_cost(lua_State * L) {
+ return wares_or_workers_map_to_lua(L, get()->buildcost(), MapObjectType::WARE);
+}
+
+/* RST
+ .. attribute:: the name and descname of the editor category of this immovable
+
+ (RO) a table with "name" and "descname" entries for the editor category, or nil if it has none.
+*/
+int LuaImmovableDescription::get_editor_category(lua_State * L) {
+ if (get()->has_editor_category()) {
+ const EditorCategory& editor_category = get()->editor_category();
+ lua_newtable(L);
+ lua_pushstring(L, "name");
+ lua_pushstring(L, editor_category.name());
+ lua_settable(L, -3);
+ lua_pushstring(L, "descname");
+ lua_pushstring(L, editor_category.descname());
+ lua_settable(L, -3);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* RST
+ .. attribute:: whether this immovable has terrain affinity
+
+ (RO) true if this immovable has terrain affinity
+*/
+int LuaImmovableDescription::get_has_terrain_affinity(lua_State * L) {
+ lua_pushboolean(L, get()->has_terrain_affinity());
+ return 1;
+}
+
+/* RST
+ .. attribute:: the terrain affinity's pickiness
+
+ (RO) the immovable's pickiness terrain affinity value. 0 if it has no terrain affinity.
+*/
+int LuaImmovableDescription::get_pickiness(lua_State * L) {
+ lua_pushnumber(L, get()->has_terrain_affinity() ? get()->terrain_affinity().pickiness() : 0);
+ return 1;
+}
+
+/* RST
+ .. attribute:: the terrain affinity's preferred_fertility
+
+ (RO) the immovable's preferred_fertility terrain affinity value. 0 if it has no terrain affinity.
+*/
+int LuaImmovableDescription::get_preferred_fertility(lua_State * L) {
+ lua_pushnumber(L, get()->has_terrain_affinity() ? get()->terrain_affinity().preferred_fertility() : 0);
+ return 1;
+}
+
+/* RST
+ .. attribute:: the terrain affinity's preferred_humidity
+
+ (RO) the immovable's preferred_humidity terrain affinity value. 0 if it has no terrain affinity.
+*/
+int LuaImmovableDescription::get_preferred_humidity(lua_State * L) {
+ lua_pushnumber(L, get()->has_terrain_affinity() ? get()->terrain_affinity().preferred_humidity() : 0);
+ return 1;
+}
+
+
+/* RST
+ .. attribute:: the terrain affinity's preferred_temperature
+
+ (RO) the immovable's preferred_temperature terrain affinity value. 0 if it has no terrain affinity.
+*/
+int LuaImmovableDescription::get_preferred_temperature(lua_State * L) {
+ lua_pushnumber(L, get()->has_terrain_affinity() ? get()->terrain_affinity().preferred_temperature() : 0);
+ return 1;
+}
+
+
+/* RST
+ .. attribute:: the owner type of this immovable
+
+ (RO) "world" for world immovables and "tribe" for tribe immovables.
+*/
+int LuaImmovableDescription::get_owner_type(lua_State * L) {
+ lua_pushstring(L, get()->owner_type() == MapObjectDescr::OwnerType::kWorld ? "world" : "tribe");
+ return 1;
+}
+
+
+/* RST
+ .. attribute:: size
+
+ (RO) the size of the immovable as an int.
+*/
+int LuaImmovableDescription::get_size(lua_State * L) {
+ lua_pushinteger(L, get()->get_size());
+ return 1;
+}
+
+
/* RST
BuildingDescription
-------------------
@@ -2311,7 +2477,7 @@
/* RST
- .. attribute:: is_construction_material
+ .. .. method:: is_construction_material
:arg tribename: the name of the tribe that this ware gets checked for
:type tribename: :class:`string`
@@ -2477,6 +2643,340 @@
==========================================================
*/
+/* RST
+ResourceDescription
+--------------------
+.. class:: ResourceDescription
+
+ A static description of a resource.
+*/
+const char LuaResourceDescription::className[] = "ResourceDescription";
+const MethodType<LuaResourceDescription> LuaResourceDescription::Methods[] = {
+ METHOD(LuaResourceDescription, editor_image),
+ {nullptr, nullptr},
+};
+const PropertyType<LuaResourceDescription> LuaResourceDescription::Properties[] = {
+ PROP_RO(LuaResourceDescription, name),
+ PROP_RO(LuaResourceDescription, descname),
+ PROP_RO(LuaResourceDescription, is_detectable),
+ PROP_RO(LuaResourceDescription, max_amount),
+ PROP_RO(LuaResourceDescription, representative_image),
+ {nullptr, nullptr, nullptr},
+};
+
+void LuaResourceDescription::__persist(lua_State* L) {
+ const Widelands::ResourceDescription* descr = get();
+ PERS_STRING("name", descr->name());
+}
+
+void LuaResourceDescription::__unpersist(lua_State* L) {
+ std::string name;
+ UNPERS_STRING("name", name);
+ const World& world = get_egbase(L).world();
+ const ResourceDescription* descr = world.get_resource(world.safe_resource_index(name.c_str()));
+ set_description_pointer(descr);
+}
+
+/*
+ ==========================================================
+ PROPERTIES
+ ==========================================================
+ */
+
+/* RST
+ .. attribute:: name
+
+ (RO) the :class:`string` internal name of this resource
+*/
+
+int LuaResourceDescription::get_name(lua_State * L) {
+ lua_pushstring(L, get()->name());
+ return 1;
+}
+
+/* RST
+ .. attribute:: descname
+
+ (RO) the :class:`string` display name of this resource
+*/
+
+int LuaResourceDescription::get_descname(lua_State * L) {
+ lua_pushstring(L, get()->descname());
+ return 1;
+}
+
+/* RST
+ .. attribute:: is_detectable
+
+ (RO) true if geologists can find this resource
+*/
+
+int LuaResourceDescription::get_is_detectable(lua_State * L) {
+ lua_pushboolean(L, get()->detectable());
+ return 1;
+}
+
+/* RST
+ .. attribute:: max_amount
+
+ (RO) the maximum amount of this resource that a terrain can have
+*/
+
+int LuaResourceDescription::get_max_amount(lua_State * L) {
+ lua_pushinteger(L, get()->max_amount());
+ return 1;
+}
+
+/* RST
+ .. attribute:: representative_image
+
+ (RO) the :class:`string` path to the image representing this resource in the GUI
+*/
+int LuaResourceDescription::get_representative_image(lua_State * L) {
+ lua_pushstring(L, get()->representative_image());
+ return 1;
+}
+
+
+/*
+ ==========================================================
+ METHODS
+ ==========================================================
+ */
+
+/* RST
+ .. method:: representative_image(amount)
+
+ :arg amount: The amount of the resource what we want an overlay image for
+
+ (RO) the :class:`string` path to the image representing the specified amount of this resource
+*/
+int LuaResourceDescription::editor_image(lua_State * L) {
+ if (lua_gettop(L) != 2) {
+ report_error(L, "Takes only one argument.");
+ }
+ const uint32_t amount = luaL_checkuint32(L, 2);
+ lua_pushstring(L, get()->editor_image(amount));
+ return 1;
+}
+
+/* RST
+TerrainDescription
+--------------------
+.. class:: TerrainDescription
+
+ A static description of a terrain.
+*/
+const char LuaTerrainDescription::className[] = "TerrainDescription";
+const MethodType<LuaTerrainDescription> LuaTerrainDescription::Methods[] = {
+ METHOD(LuaTerrainDescription, probability_to_grow),
+ {nullptr, nullptr},
+};
+const PropertyType<LuaTerrainDescription> LuaTerrainDescription::Properties[] = {
+ PROP_RO(LuaTerrainDescription, name),
+ PROP_RO(LuaTerrainDescription, descname),
+ PROP_RO(LuaTerrainDescription, default_resource_name),
+ PROP_RO(LuaTerrainDescription, default_resource_amount),
+ PROP_RO(LuaTerrainDescription, editor_category),
+ PROP_RO(LuaTerrainDescription, fertility),
+ PROP_RO(LuaTerrainDescription, humidity),
+ PROP_RO(LuaTerrainDescription, representative_image),
+ PROP_RO(LuaTerrainDescription, temperature),
+ PROP_RO(LuaTerrainDescription, valid_resources_names),
+ {nullptr, nullptr, nullptr},
+};
+
+void LuaTerrainDescription::__persist(lua_State* L) {
+ const Widelands::TerrainDescription* descr = get();
+ PERS_STRING("name", descr->name());
+}
+
+void LuaTerrainDescription::__unpersist(lua_State* L) {
+ std::string name;
+ UNPERS_STRING("name", name);
+ set_description_pointer(get_egbase(L).world().get_ter(name.c_str()));
+}
+
+/*
+ ==========================================================
+ PROPERTIES
+ ==========================================================
+ */
+
+/* RST
+ .. attribute:: name
+
+ (RO) the :class:`string` internal name of this terrain
+*/
+
+int LuaTerrainDescription::get_name(lua_State * L) {
+ lua_pushstring(L, get()->name());
+ return 1;
+}
+
+/* RST
+ .. attribute:: descname
+
+ (RO) the :class:`string` display name of this terrain
+*/
+
+int LuaTerrainDescription::get_descname(lua_State * L) {
+ lua_pushstring(L, get()->descname());
+ return 1;
+}
+
+/* RST
+ .. attribute:: get_default_resource_descname
+
+ (RO) the :class:`string` description name of the default resource provided by this terrain, or
+ nil if the terrain has no default resource.
+*/
+
+int LuaTerrainDescription::get_default_resource_name(lua_State * L) {
+ int res_index = get()->get_default_resource();
+ const World& world = get_egbase(L).world();
+ if (res_index != Widelands::kNoResource && res_index < world.get_nr_resources()) {
+ lua_pushstring(L, world.get_resource(res_index)->name());
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* RST
+ .. attribute:: default_resource_amount
+
+ (RO) the int amount of the default resource provided by this terrain.
+*/
+
+int LuaTerrainDescription::get_default_resource_amount(lua_State * L) {
+ lua_pushinteger(L, get()->get_default_resource_amount());
+ return 1;
+}
+
+
+/* RST
+ .. attribute:: the name and descname of the editor category of this terrain
+
+ (RO) a table with "name" and "descname" entries for the editor category, or nil if it has none.
+*/
+int LuaTerrainDescription::get_editor_category(lua_State * L) {
+ const EditorCategory& editor_category = get()->editor_category();
+ if (&editor_category) {
+ lua_newtable(L);
+ lua_pushstring(L, "name");
+ lua_pushstring(L, editor_category.name());
+ lua_settable(L, -3);
+ lua_pushstring(L, "descname");
+ lua_pushstring(L, editor_category.descname());
+ lua_settable(L, -3);
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+/* RST
+ .. attribute:: fertility
+
+ (RO) the :class:`double` fertility value for this terrain
+*/
+
+int LuaTerrainDescription::get_fertility(lua_State * L) {
+ lua_pushnumber(L, get()->fertility());
+ return 1;
+}
+
+/* RST
+ .. attribute:: humidity
+
+ (RO) the :class:`double` humidity value for this terrain
+*/
+
+int LuaTerrainDescription::get_humidity(lua_State * L) {
+ lua_pushnumber(L, get()->humidity());
+ return 1;
+}
+
+/* RST
+ .. attribute:: representative_image
+
+ (RO) the :class:`string` file path to a representative image
+*/
+
+int LuaTerrainDescription::get_representative_image(lua_State * L) {
+ lua_pushstring(L, *get()->texture_paths().begin());
+ return 1;
+}
+
+/* RST
+ .. attribute:: temperature
+
+ (RO) the :class:`double` temperature value for this terrain
+*/
+
+int LuaTerrainDescription::get_temperature(lua_State * L) {
+ lua_pushnumber(L, get()->temperature());
+ return 1;
+}
+
+
+/* RST
+ .. attribute:: valid_resources_names
+
+ (RO) a list of the names for all valid resources for this terrain.
+*/
+
+int LuaTerrainDescription::get_valid_resources_names(lua_State * L) {
+ const World& world = get_egbase(L).world();
+ lua_newtable(L);
+ int index = 1;
+ for (uint8_t res_index : get()->valid_resources()) {
+ if (res_index != Widelands::kNoResource && res_index < world.get_nr_resources()) {
+ lua_pushint32(L, index++);
+ lua_pushstring(L, world.get_resource(res_index)->name());
+ lua_settable(L, -3);
+ }
+ }
+ return 1;
+}
+
+
+/*
+ ==========================================================
+ METHODS
+ ==========================================================
+ */
+
+/* RST
+ .. method:: probability_to_grow
+
+ :arg treename: The tree that we are checking the probability for.
+ :type treename: :class:`string`
+
+ (RO) A double describing the probability that the given tree will grow on this terrain.
+*/
+int LuaTerrainDescription::probability_to_grow(lua_State * L) {
+ if (lua_gettop(L) != 2) {
+ report_error(L, "Takes only one argument.");
+ }
+ const std::string tree_name = luaL_checkstring(L, 2);
+ const World& world = get_egbase(L).world();
+ const DescriptionIndex index = world.get_immovable_index(tree_name);
+ if (index != INVALID_INDEX) {
+ const ImmovableDescr* tree = world.get_immovable_descr(index);
+ if (tree->has_terrain_affinity()) {
+ lua_pushnumber(L, Widelands::probability_to_grow(tree->terrain_affinity(), *get()));
+ } else {
+ lua_pushnil(L);
+ }
+ } else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+
/* RST
@@ -4943,6 +5443,10 @@
register_class<LuaTribeDescription>(L, "map");
register_class<LuaMapObjectDescription>(L, "map");
+ register_class<LuaImmovableDescription>(L, "map", true);
+ add_parent<LuaImmovableDescription, LuaMapObjectDescription>(L);
+ lua_pop(L, 1); // Pop the meta table
+
register_class<LuaBuildingDescription>(L, "map", true);
add_parent<LuaBuildingDescription, LuaMapObjectDescription>(L);
lua_pop(L, 1); // Pop the meta table
@@ -4986,6 +5490,9 @@
add_parent<LuaWorkerDescription, LuaMapObjectDescription>(L);
lua_pop(L, 1); // Pop the meta table
+ register_class<LuaResourceDescription>(L, "map");
+ register_class<LuaTerrainDescription>(L, "map");
+
register_class<LuaField>(L, "map");
register_class<LuaPlayerSlot>(L, "map");
register_class<LuaMapObject>(L, "map");
=== modified file 'src/scripting/lua_map.h'
--- src/scripting/lua_map.h 2016-01-22 19:53:32 +0000
+++ src/scripting/lua_map.h 2016-01-26 07:30:52 +0000
@@ -35,6 +35,7 @@
#include "logic/map_objects/tribes/trainingsite.h"
#include "logic/map_objects/tribes/warehouse.h"
#include "logic/map_objects/tribes/worker.h"
+#include "logic/map_objects/world/terrain_description.h"
#include "scripting/lua.h"
#include "scripting/luna.h"
@@ -43,8 +44,10 @@
class SoldierDescr;
class BuildingDescr;
class Bob;
+ class ResourceDescription;
class WareDescr;
class WorkerDescr;
+ class TerrainDescription;
class TribeDescr;
}
@@ -203,6 +206,49 @@
return static_cast<const Widelands::klass*>(LuaMapObjectDescription::get()); \
}
+class LuaImmovableDescription : public LuaMapObjectDescription {
+public:
+ LUNA_CLASS_HEAD(LuaImmovableDescription);
+
+ virtual ~LuaImmovableDescription() {}
+
+ LuaImmovableDescription() {}
+ LuaImmovableDescription(const Widelands::ImmovableDescr* const immovabledescr)
+ : LuaMapObjectDescription(immovabledescr) {
+ }
+ LuaImmovableDescription(lua_State* L) : LuaMapObjectDescription(L) {
+ }
+
+ void __persist(lua_State * L) override;
+ void __unpersist(lua_State * L) override;
+
+ /*
+ * Properties
+ */
+ int get_basename(lua_State *);
+ int get_build_cost(lua_State *);
+ int get_editor_category(lua_State *);
+ int get_has_terrain_affinity(lua_State *);
+ int get_pickiness(lua_State *);
+ int get_preferred_fertility(lua_State *);
+ int get_preferred_humidity(lua_State *);
+ int get_preferred_temperature(lua_State *);
+ int get_owner_type(lua_State *);
+ int get_size(lua_State *);
+
+ /*
+ * Lua methods
+ */
+
+ /*
+ * C methods
+ */
+
+private:
+ CASTED_GET_DESCRIPTION(ImmovableDescr)
+};
+
+
class LuaBuildingDescription : public LuaMapObjectDescription {
public:
LUNA_CLASS_HEAD(LuaBuildingDescription);
@@ -515,6 +561,110 @@
#undef CASTED_GET_DESCRIPTION
+
+class LuaResourceDescription : public LuaMapModuleClass {
+public:
+ LUNA_CLASS_HEAD(LuaResourceDescription);
+
+ virtual ~LuaResourceDescription() {}
+
+ LuaResourceDescription() : resourcedescr_(nullptr) {}
+ LuaResourceDescription(const Widelands::ResourceDescription* const resourcedescr)
+ : resourcedescr_(resourcedescr) {}
+ LuaResourceDescription(lua_State* L) : resourcedescr_(nullptr) {
+ report_error(L, "Cannot instantiate a 'LuaResourceDescription' directly!");
+ }
+
+ void __persist(lua_State * L) override;
+ void __unpersist(lua_State * L) override;
+
+ /*
+ * Properties
+ */
+ int get_name(lua_State *);
+ int get_descname(lua_State *);
+ int get_is_detectable(lua_State *);
+ int get_max_amount(lua_State *);
+ int get_representative_image(lua_State *);
+
+ /*
+ * Lua methods
+ */
+
+ int editor_image(lua_State *);
+
+ /*
+ * C methods
+ */
+protected:
+ const Widelands::ResourceDescription* get() const {
+ assert(resourcedescr_ != nullptr);
+ return resourcedescr_;
+ }
+ // For persistence.
+ void set_description_pointer(const Widelands::ResourceDescription* pointer) {
+ resourcedescr_ = pointer;
+ }
+
+private:
+ const Widelands::ResourceDescription* resourcedescr_;
+};
+
+
+
+class LuaTerrainDescription : public LuaMapModuleClass {
+public:
+ LUNA_CLASS_HEAD(LuaTerrainDescription);
+
+ virtual ~LuaTerrainDescription() {}
+
+ LuaTerrainDescription() : terraindescr_(nullptr) {}
+ LuaTerrainDescription(const Widelands::TerrainDescription* const terraindescr)
+ : terraindescr_(terraindescr) {}
+ LuaTerrainDescription(lua_State* L) : terraindescr_(nullptr) {
+ report_error(L, "Cannot instantiate a 'LuaTerrainDescription' directly!");
+ }
+
+ void __persist(lua_State * L) override;
+ void __unpersist(lua_State * L) override;
+
+ /*
+ * Properties
+ */
+ int get_name(lua_State *);
+ int get_descname(lua_State *);
+ int get_default_resource_name(lua_State *);
+ int get_default_resource_amount(lua_State *);
+ int get_editor_category(lua_State *);
+ int get_fertility(lua_State *);
+ int get_humidity(lua_State *);
+ int get_representative_image(lua_State *);
+ int get_temperature(lua_State *);
+ int get_valid_resources_names(lua_State *);
+
+ /*
+ * Lua methods
+ */
+ int probability_to_grow(lua_State *);
+
+ /*
+ * C methods
+ */
+protected:
+ const Widelands::TerrainDescription* get() const {
+ assert(terraindescr_ != nullptr);
+ return terraindescr_;
+ }
+ // For persistence.
+ void set_description_pointer(const Widelands::TerrainDescription* pointer) {
+ terraindescr_ = pointer;
+ }
+
+private:
+ const Widelands::TerrainDescription* terraindescr_;
+};
+
+
#define CASTED_GET(klass) \
Widelands:: klass * get(lua_State * L, Widelands::EditorGameBase & egbase) { \
return static_cast<Widelands:: klass *> \
=== modified file 'src/scripting/lua_root.cc'
--- src/scripting/lua_root.cc 2015-11-28 22:29:26 +0000
+++ src/scripting/lua_root.cc 2016-01-26 07:30:52 +0000
@@ -309,6 +309,8 @@
const char LuaWorld::className[] = "World";
const MethodType<LuaWorld> LuaWorld::Methods[] = {
+ METHOD(LuaWorld, immovable_descriptions),
+ METHOD(LuaWorld, terrain_descriptions),
METHOD(LuaWorld, new_critter_type),
METHOD(LuaWorld, new_editor_immovable_category),
METHOD(LuaWorld, new_editor_terrain_category),
@@ -345,6 +347,55 @@
*/
/* RST
+ .. method:: immovable_descriptions(attribute_name)
+
+ Returns a list of names with the immovables that have the attribute with the given attribute_name.
+
+ (RO) a list of immovable names, e.g. {"alder_summer_old", "cirrus_wasteland_old", ...}
+*/
+int LuaWorld::immovable_descriptions(lua_State* L) {
+ if (lua_gettop(L) != 2) {
+ report_error(L, "Takes only one argument.");
+ }
+ const World& world = get_egbase(L).world();
+ const std::string attribute_name = luaL_checkstring(L, 2);
+ lua_newtable(L);
+ int index = 1;
+ for (DescriptionIndex i = 0; i < world.get_nr_immovables(); ++i) {
+ const ImmovableDescr* immovable = world.get_immovable_descr(i);
+ uint32_t attribute_id = immovable->get_attribute_id(attribute_name);
+ if (immovable->has_attribute(attribute_id)) {
+ lua_pushint32(L, index++);
+ lua_pushstring(L, immovable->name());
+ lua_settable(L, -3);
+ }
+ }
+ return 1;
+}
+
+
+/* RST
+ .. method:: terrain_descriptions()
+
+ Returns a list of names with the terrains that are available in the worls.
+
+ (RO) a list of terrain names, e.g. {"wiese1", "wiese2", ...}
+*/
+int LuaWorld::terrain_descriptions(lua_State* L) {
+ const World& world = get_egbase(L).world();
+ lua_newtable(L);
+ int index = 1;
+ for (DescriptionIndex i = 0; i < world.terrains().size(); ++i) {
+ const TerrainDescription& terrain = world.terrain_descr(i);
+ lua_pushint32(L, index++);
+ lua_pushstring(L, terrain.name());
+ lua_settable(L, -3);
+ }
+ return 1;
+}
+
+
+/* RST
.. method:: new_resource_type(table)
Adds a new resource type that can be in the different maps. Takes a
=== modified file 'src/scripting/lua_root.h'
--- src/scripting/lua_root.h 2015-09-04 11:11:50 +0000
+++ src/scripting/lua_root.h 2016-01-26 07:30:52 +0000
@@ -111,6 +111,8 @@
/*
* Lua methods
*/
+ int immovable_descriptions(lua_State* L);
+ int terrain_descriptions(lua_State* L);
int new_critter_type(lua_State* L);
int new_editor_immovable_category(lua_State* L);
int new_editor_terrain_category(lua_State* L);
=== modified file 'test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua'
--- test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua 2015-10-31 12:11:44 +0000
+++ test/maps/lua_testsuite.wmf/scripting/immovables_descriptions.lua 2016-01-26 07:30:52 +0000
@@ -13,6 +13,95 @@
end)
end
+
+-- =======================================================
+-- ***************** ImmovableDescription *****************
+-- =======================================================
+
+function test_descr:test_immovable_descr()
+ assert_error("Wrong immovable", function() egbase:get_immovable_description("XXX") end)
+ assert_error("Wrong number of parameters: 2", function() egbase:get_immovable_description("XXX", "YYY") end)
+ assert_error("Wrong number of parameters: 3", function() egbase:get_immovable_description("XXX","YYY","ZZZ") end)
+end
+
+function test_descr:test_immovable_basename()
+ assert_equal("", egbase:get_immovable_description("bush1").basename)
+ assert_equal("", egbase:get_immovable_description("cornfield_ripe").basename)
+ assert_equal("", egbase:get_immovable_description("alder_summer_sapling").basename)
+ assert_equal(_"Alder", egbase:get_immovable_description("alder_summer_old").basename)
+end
+
+function test_descr:test_immovable_build_cost()
+ local build_cost = egbase:get_immovable_description("atlanteans_shipconstruction").build_cost
+ assert_equal(10, build_cost["planks"])
+ assert_equal(2, build_cost["log"])
+ assert_equal(4, build_cost["spidercloth"])
+ assert_equal(nil, build_cost["wine"])
+end
+
+function test_descr:test_immovable_editor_category()
+ assert_equal("plants", egbase:get_immovable_description("bush1").editor_category.name)
+ assert_equal(_"Plants", egbase:get_immovable_description("bush1").editor_category.descname)
+ assert_equal(nil, egbase:get_immovable_description("cornfield_ripe").editor_category)
+ assert_equal("trees_deciduous", egbase:get_immovable_description("alder_summer_sapling").editor_category.name)
+ assert_equal(_"Deciduous Trees", egbase:get_immovable_description("alder_summer_sapling").editor_category.descname)
+ assert_equal("trees_deciduous", egbase:get_immovable_description("alder_summer_old").editor_category.name)
+end
+
+function test_descr:test_immovable_has_terrain_affinity()
+ assert_equal(false, egbase:get_immovable_description("bush1").has_terrain_affinity)
+ assert_equal(false, egbase:get_immovable_description("cornfield_ripe").has_terrain_affinity)
+ assert_equal(true, egbase:get_immovable_description("alder_summer_sapling").has_terrain_affinity)
+ assert_equal(true, egbase:get_immovable_description("alder_summer_old").has_terrain_affinity)
+end
+
+function test_descr:test_immovable_pickiness()
+ assert_equal(0, egbase:get_immovable_description("bush1").pickiness)
+ assert_equal(0, egbase:get_immovable_description("cornfield_ripe").pickiness)
+ assert_equal(0.6, egbase:get_immovable_description("alder_summer_sapling").pickiness)
+ assert_equal(0.6, egbase:get_immovable_description("alder_summer_old").pickiness)
+ assert_equal(0.6, egbase:get_immovable_description("mushroom_red_wasteland_sapling").pickiness)
+end
+
+function test_descr:test_immovable_preferred_fertility()
+ assert_equal(0, egbase:get_immovable_description("bush1").preferred_fertility)
+ assert_equal(0, egbase:get_immovable_description("cornfield_ripe").preferred_fertility)
+ assert_equal(0.6, egbase:get_immovable_description("alder_summer_sapling").preferred_fertility)
+ assert_equal(0.6, egbase:get_immovable_description("alder_summer_old").preferred_fertility)
+ assert_equal(0.85, egbase:get_immovable_description("mushroom_red_wasteland_sapling").preferred_fertility)
+end
+
+function test_descr:test_immovable_preferred_humidity()
+ assert_equal(0, egbase:get_immovable_description("bush1").preferred_humidity)
+ assert_equal(0, egbase:get_immovable_description("cornfield_ripe").preferred_humidity)
+ assert_equal(0.65, egbase:get_immovable_description("alder_summer_sapling").preferred_humidity)
+ assert_equal(0.65, egbase:get_immovable_description("alder_summer_old").preferred_humidity)
+ assert_equal(0.35, egbase:get_immovable_description("mushroom_red_wasteland_sapling").preferred_humidity)
+end
+
+function test_descr:test_immovable_preferred_temperature()
+ assert_equal(0, egbase:get_immovable_description("bush1").preferred_temperature)
+ assert_equal(0, egbase:get_immovable_description("cornfield_ripe").preferred_temperature)
+ assert_equal(125, egbase:get_immovable_description("alder_summer_sapling").preferred_temperature)
+ assert_equal(125, egbase:get_immovable_description("alder_summer_old").preferred_temperature)
+ assert_equal(80, egbase:get_immovable_description("mushroom_red_wasteland_sapling").preferred_temperature)
+end
+
+function test_descr:test_immovable_owner_type()
+ assert_equal("world", egbase:get_immovable_description("bush1").owner_type)
+ assert_equal("tribe", egbase:get_immovable_description("cornfield_ripe").owner_type)
+ assert_equal("world", egbase:get_immovable_description("alder_summer_sapling").owner_type)
+ assert_equal("world", egbase:get_immovable_description("alder_summer_old").owner_type)
+end
+
+function test_descr:test_immovable_size()
+ assert_equal(0, egbase:get_immovable_description("bush1").size)
+ assert_equal(1, egbase:get_immovable_description("cornfield_ripe").size)
+ assert_equal(1, egbase:get_immovable_description("alder_summer_sapling").size)
+ assert_equal(1, egbase:get_immovable_description("alder_summer_old").size)
+end
+
+
-- =======================================================
-- ***************** BuildingDescription *****************
-- =======================================================
=== modified file 'test/maps/lua_testsuite.wmf/scripting/init.lua'
--- test/maps/lua_testsuite.wmf/scripting/init.lua 2015-10-31 12:11:44 +0000
+++ test/maps/lua_testsuite.wmf/scripting/init.lua 2016-01-26 07:30:52 +0000
@@ -33,6 +33,7 @@
include "map:scripting/immovables.lua"
include "map:scripting/immovables_descriptions.lua"
+include "map:scripting/terrains_resources_descriptions.lua"
include "map:scripting/tribes_descriptions.lua"
if not wl.editor then
=== added file 'test/maps/lua_testsuite.wmf/scripting/terrains_resources_descriptions.lua'
--- test/maps/lua_testsuite.wmf/scripting/terrains_resources_descriptions.lua 1970-01-01 00:00:00 +0000
+++ test/maps/lua_testsuite.wmf/scripting/terrains_resources_descriptions.lua 2016-01-26 07:30:52 +0000
@@ -0,0 +1,154 @@
+set_textdomain("tribes")
+
+test_terrains_resource_descr = lunit.TestCase("Terrains and resources descriptions test")
+
+-- =======================================================
+-- ***************** ResourceDescription *****************
+-- =======================================================
+
+function test_terrains_resource_descr:test_resource_descr()
+ assert_error("Wrong terrain", function() egbase:get_resource_description("XXX") end)
+ assert_error("Wrong number of parameters: 2", function() egbase:get_resource_description("XXX", "YYY") end)
+ assert_error("Wrong number of parameters: 3", function() egbase:get_resource_description("XXX","YYY","ZZZ") end)
+end
+
+function test_terrains_resource_descr:test_resource_descname()
+ assert_equal(_"Coal", egbase:get_resource_description("coal").descname)
+ assert_equal(_"Stones", egbase:get_resource_description("stones").descname)
+ assert_equal(_"Water", egbase:get_resource_description("water").descname)
+ assert_equal(_"Fish", egbase:get_resource_description("fish").descname)
+end
+
+function test_terrains_resource_descr:test_resource_name()
+ assert_equal("coal", egbase:get_resource_description("coal").name)
+ assert_equal("stones", egbase:get_resource_description("stones").name)
+ assert_equal("water", egbase:get_resource_description("water").name)
+ assert_equal("fish", egbase:get_resource_description("fish").name)
+end
+
+function test_terrains_resource_descr:test_resource_is_detectable()
+ assert_equal(true, egbase:get_resource_description("coal").is_detectable)
+ assert_equal(true, egbase:get_resource_description("stones").is_detectable)
+ assert_equal(true, egbase:get_resource_description("water").is_detectable)
+ assert_equal(false, egbase:get_resource_description("fish").is_detectable)
+end
+
+function test_terrains_resource_descr:test_resource_max_amount()
+ assert_equal(20, egbase:get_resource_description("coal").max_amount)
+ assert_equal(20, egbase:get_resource_description("stones").max_amount)
+ assert_equal(50, egbase:get_resource_description("water").max_amount)
+ assert_equal(20, egbase:get_resource_description("fish").max_amount)
+end
+
+function test_terrains_resource_descr:test_resource_representative_image()
+ assert_equal("world/resources/pics/coal4.png", egbase:get_resource_description("coal").representative_image)
+ assert_equal("world/resources/pics/stones4.png", egbase:get_resource_description("stones").representative_image)
+ assert_equal("world/resources/pics/water4.png", egbase:get_resource_description("water").representative_image)
+ assert_equal("world/resources/pics/fish.png", egbase:get_resource_description("fish").representative_image)
+end
+
+function test_terrains_resource_descr:test_resource_editor_image()
+ assert_equal("world/resources/pics/coal1.png", egbase:get_resource_description("coal"):editor_image(0))
+ assert_equal("world/resources/pics/coal1.png", egbase:get_resource_description("coal"):editor_image(5))
+ assert_equal("world/resources/pics/coal2.png", egbase:get_resource_description("coal"):editor_image(6))
+ assert_equal("world/resources/pics/coal2.png", egbase:get_resource_description("coal"):editor_image(10))
+ assert_equal("world/resources/pics/coal3.png", egbase:get_resource_description("coal"):editor_image(15))
+ assert_equal("world/resources/pics/coal4.png", egbase:get_resource_description("coal"):editor_image(16))
+ assert_equal("world/resources/pics/coal4.png", egbase:get_resource_description("coal"):editor_image(1000))
+end
+
+-- =======================================================
+-- ***************** TerrainDescription ******************
+-- =======================================================
+
+function test_terrains_resource_descr:test_terrain_descr()
+ assert_error("Wrong terrain", function() egbase:get_terrain_description("XXX") end)
+ assert_error("Wrong number of parameters: 2", function() egbase:get_terrain_description("XXX", "YYY") end)
+ assert_error("Wrong number of parameters: 3", function() egbase:get_terrain_description("XXX","YYY","ZZZ") end)
+end
+
+function test_terrains_resource_descr:test_terrain_descname()
+ assert_equal(_"Meadow", egbase:get_terrain_description("wiese1").descname)
+ assert_equal(_"Beach", egbase:get_terrain_description("wasteland_beach").descname)
+ assert_equal(_"Forested Mountain", egbase:get_terrain_description("desert_forested_mountain2").descname)
+ assert_equal(_"Water", egbase:get_terrain_description("winter_water").descname)
+end
+
+function test_terrains_resource_descr:test_terrain_name()
+ assert_equal("wiese1", egbase:get_terrain_description("wiese1").name)
+ assert_equal("wasteland_beach", egbase:get_terrain_description("wasteland_beach").name)
+ assert_equal("desert_forested_mountain2", egbase:get_terrain_description("desert_forested_mountain2").name)
+ assert_equal("winter_water", egbase:get_terrain_description("winter_water").name)
+end
+
+function test_terrains_resource_descr:test_terrain_default_resource_name()
+ assert_equal("water", egbase:get_terrain_description("wiese1").default_resource_name)
+ assert_equal(nil, egbase:get_terrain_description("wasteland_beach").default_resource_name)
+ assert_equal(nil, egbase:get_terrain_description("desert_forested_mountain2").default_resource_name)
+ assert_equal("fish", egbase:get_terrain_description("winter_water").default_resource_name)
+end
+
+function test_terrains_resource_descr:test_terrain_default_resource_amount()
+ assert_equal(10, egbase:get_terrain_description("wiese1").default_resource_amount)
+ assert_equal(0, egbase:get_terrain_description("wasteland_beach").default_resource_amount)
+ assert_equal(0, egbase:get_terrain_description("desert_forested_mountain2").default_resource_amount)
+ assert_equal(4, egbase:get_terrain_description("winter_water").default_resource_amount)
+end
+
+function test_terrains_resource_descr:test_terrain_editor_category()
+ assert_equal("green", egbase:get_terrain_description("wiese1").editor_category.name)
+ assert_equal(_"Summer", egbase:get_terrain_description("wiese1").editor_category.descname)
+ assert_equal("wasteland", egbase:get_terrain_description("wasteland_beach").editor_category.name)
+ assert_equal(_"Wasteland", egbase:get_terrain_description("wasteland_beach").editor_category.descname)
+ assert_equal("desert", egbase:get_terrain_description("desert_forested_mountain2").editor_category.name)
+ assert_equal(_"Desert", egbase:get_terrain_description("desert_forested_mountain2").editor_category.descname)
+ assert_equal("winter", egbase:get_terrain_description("winter_water").editor_category.name)
+ assert_equal(_"Winter", egbase:get_terrain_description("winter_water").editor_category.descname)
+end
+
+function test_terrains_resource_descr:test_terrain_fertility()
+ assert_equal(0.7, egbase:get_terrain_description("wiese1").fertility)
+ assert_equal(0.2, egbase:get_terrain_description("wasteland_beach").fertility)
+ assert_equal(0.5, egbase:get_terrain_description("desert_forested_mountain2").fertility)
+ assert_equal(0.001, egbase:get_terrain_description("winter_water").fertility)
+end
+
+function test_terrains_resource_descr:test_terrain_humidity()
+ assert_equal(0.6, egbase:get_terrain_description("wiese1").humidity)
+ assert_equal(0.4, egbase:get_terrain_description("wasteland_beach").humidity)
+ assert_equal(0.5, egbase:get_terrain_description("desert_forested_mountain2").humidity)
+ assert_equal(0.999, egbase:get_terrain_description("winter_water").humidity)
+end
+
+function test_terrains_resource_descr:test_terrain_temperature()
+ assert_equal(100, egbase:get_terrain_description("wiese1").temperature)
+ assert_equal(60, egbase:get_terrain_description("wasteland_beach").temperature)
+ assert_equal(120, egbase:get_terrain_description("desert_forested_mountain2").temperature)
+ assert_equal(50, egbase:get_terrain_description("winter_water").temperature)
+end
+
+function test_terrains_resource_descr:test_terrain_representative_image()
+ assert_equal("world/terrains/pics/green/wiese1_00.png", egbase:get_terrain_description("wiese1").representative_image)
+ assert_equal("world/terrains/pics/wasteland/strand_00.png", egbase:get_terrain_description("wasteland_beach").representative_image)
+ assert_equal("world/terrains/pics/desert/forested_mountain2_00.png", egbase:get_terrain_description("desert_forested_mountain2").representative_image)
+ assert_equal("world/terrains/pics/winter/water_00.png", egbase:get_terrain_description("winter_water").representative_image)
+end
+
+function test_terrains_resource_descr:test_valid_resources_names()
+ assert_equal("water", egbase:get_terrain_description("wiese1").valid_resources_names[1])
+ assert_equal(0, #egbase:get_terrain_description("wasteland_beach").valid_resources_names)
+ assert_equal(4, #egbase:get_terrain_description("desert_forested_mountain2").valid_resources_names)
+ assert_equal("fish", egbase:get_terrain_description("winter_water").valid_resources_names[1])
+end
+
+function test_terrains_resource_descr:test_terrain_probability_to_grow()
+ -- Using comparisons in order to not run into trouble with floating point numbers
+ assert_true(egbase:get_terrain_description("wiese1"):probability_to_grow("alder_summer_sapling") < 0.6)
+ assert_true(egbase:get_terrain_description("wiese1"):probability_to_grow("alder_summer_sapling") > 0.4)
+ assert_true(egbase:get_terrain_description("wasteland_beach"):probability_to_grow("alder_summer_sapling") < 0.003)
+ assert_true(egbase:get_terrain_description("wasteland_beach"):probability_to_grow("alder_summer_sapling") > 0.002)
+ assert_true(egbase:get_terrain_description("desert_forested_mountain2"):probability_to_grow("alder_summer_sapling") < 0.662)
+ assert_true(egbase:get_terrain_description("desert_forested_mountain2"):probability_to_grow("alder_summer_sapling") > 0.660)
+ assert_true(egbase:get_terrain_description("winter_water"):probability_to_grow("alder_summer_sapling") < 0.000038)
+ assert_true(egbase:get_terrain_description("winter_water"):probability_to_grow("alder_summer_sapling") > 0.000037)
+end
=== modified file 'tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua'
--- tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua 2016-01-02 21:39:43 +0000
+++ tribes/buildings/trainingsites/atlanteans/labyrinth/init.lua 2016-01-26 07:30:52 +0000
@@ -34,8 +34,8 @@
},
aihints = {
- prohibited_till=900,
- forced_after=1500,
+ prohibited_till = 900,
+ forced_after = 1500,
trainingsite_type = "basic",
very_weak_ai_limit = 1,
weak_ai_limit = 2
=== modified file 'world/immovables/trees/alder/init.lua'
--- world/immovables/trees/alder/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/alder/init.lua 2016-01-26 07:30:52 +0000
@@ -87,6 +87,7 @@
world:new_immovable_type{
name = "alder_summer_old",
descname = _ "Alder (Old)",
+ basename = _ "Alder",
editor_category = "trees_deciduous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/aspen/init.lua'
--- world/immovables/trees/aspen/init.lua 2015-11-20 18:21:27 +0000
+++ world/immovables/trees/aspen/init.lua 2016-01-26 07:30:52 +0000
@@ -82,6 +82,7 @@
world:new_immovable_type{
name = "aspen_summer_old",
descname = _ "Aspen (Old)",
+ basename = _ "Aspen",
editor_category = "trees_deciduous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/beech/init.lua'
--- world/immovables/trees/beech/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/beech/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "beech_summer_old",
descname = _ "Beech (Old)",
+ basename = _ "Beech",
editor_category = "trees_deciduous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/birch/init.lua'
--- world/immovables/trees/birch/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/birch/init.lua 2016-01-26 07:30:52 +0000
@@ -82,6 +82,7 @@
world:new_immovable_type{
name = "birch_summer_old",
descname = _ "Birch (Old)",
+ basename = _ "Birch",
editor_category = "trees_deciduous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/cirrus/init.lua'
--- world/immovables/trees/cirrus/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/cirrus/init.lua 2016-01-26 07:30:52 +0000
@@ -83,6 +83,8 @@
name = "cirrus_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Cirrus Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Cirrus Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/larch/init.lua'
--- world/immovables/trees/larch/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/larch/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "larch_summer_old",
descname = _ "Larch (Old)",
+ basename = _ "Larch",
editor_category = "trees_coniferous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/liana/init.lua'
--- world/immovables/trees/liana/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/liana/init.lua 2016-01-26 07:30:52 +0000
@@ -86,6 +86,8 @@
name = "liana_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Liana Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Liana Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/maple/init.lua'
--- world/immovables/trees/maple/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/maple/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "maple_winter_old",
descname = _ "Maple (Old)",
+ basename = _ "Maple",
editor_category = "trees_deciduous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/mushroom_dark/init.lua'
--- world/immovables/trees/mushroom_dark/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/mushroom_dark/init.lua 2016-01-26 07:30:52 +0000
@@ -83,6 +83,8 @@
name = "mushroom_dark_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Dark Mushroom Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Dark Mushroom Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/mushroom_green/init.lua'
--- world/immovables/trees/mushroom_green/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/mushroom_green/init.lua 2016-01-26 07:30:52 +0000
@@ -83,6 +83,8 @@
name = "mushroom_green_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Green Mushroom Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Green Mushroom Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/mushroom_red/init.lua'
--- world/immovables/trees/mushroom_red/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/mushroom_red/init.lua 2016-01-26 07:30:52 +0000
@@ -86,6 +86,8 @@
name = "mushroom_red_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Red Mushroom Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Red Mushroom Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/oak/init.lua'
--- world/immovables/trees/oak/init.lua 2015-11-20 18:21:27 +0000
+++ world/immovables/trees/oak/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "oak_summer_old",
descname = _ "Oak (Old)",
+ basename = _ "Oak",
editor_category = "trees_deciduous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/palm_borassus/init.lua'
--- world/immovables/trees/palm_borassus/init.lua 2016-01-21 10:39:57 +0000
+++ world/immovables/trees/palm_borassus/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "palm_borassus_desert_old",
descname = _ "Borassus Palm (Old)",
+ basename = _ "Borassus Palm",
editor_category = "trees_palm",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/palm_coconut/init.lua'
--- world/immovables/trees/palm_coconut/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/palm_coconut/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "palm_coconut_desert_old",
descname = _ "Coconut Palm (Old)",
+ basename = _ "Coconut Palm",
editor_category = "trees_palm",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/palm_date/init.lua'
--- world/immovables/trees/palm_date/init.lua 2016-01-22 08:01:22 +0000
+++ world/immovables/trees/palm_date/init.lua 2016-01-26 07:30:52 +0000
@@ -82,6 +82,7 @@
world:new_immovable_type{
name = "palm_date_desert_old",
descname = _ "Date Palm (Old)",
+ basename = _ "Date Palm",
editor_category = "trees_palm",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/palm_oil/init.lua'
--- world/immovables/trees/palm_oil/init.lua 2016-01-21 10:39:57 +0000
+++ world/immovables/trees/palm_oil/init.lua 2016-01-26 07:30:52 +0000
@@ -83,6 +83,7 @@
world:new_immovable_type{
name = "palm_oil_desert_old",
descname = _ "Oil Palm (Old)",
+ basename = _ "Oil Palm",
editor_category = "trees_palm",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/palm_roystonea/init.lua'
--- world/immovables/trees/palm_roystonea/init.lua 2016-01-21 10:39:57 +0000
+++ world/immovables/trees/palm_roystonea/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "palm_roystonea_desert_old",
descname = _ "Roystonea regia Palm (Old)",
+ basename = _ "Roystonea regia Palm",
editor_category = "trees_palm",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/rowan/init.lua'
--- world/immovables/trees/rowan/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/rowan/init.lua 2016-01-26 07:30:52 +0000
@@ -82,6 +82,7 @@
world:new_immovable_type{
name = "rowan_summer_old",
descname = _ "Rowan (Old)",
+ basename = _ "Rowan",
editor_category = "trees_deciduous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/spruce/init.lua'
--- world/immovables/trees/spruce/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/spruce/init.lua 2016-01-26 07:30:52 +0000
@@ -79,6 +79,7 @@
world:new_immovable_type{
name = "spruce_summer_old",
descname = _ "Spruce (Old)",
+ basename = _ "Spruce",
editor_category = "trees_coniferous",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/twine/init.lua'
--- world/immovables/trees/twine/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/twine/init.lua 2016-01-26 07:30:52 +0000
@@ -83,6 +83,8 @@
name = "twine_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Twine Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Twine Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/umbrella_green/init.lua'
--- world/immovables/trees/umbrella_green/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/umbrella_green/init.lua 2016-01-26 07:30:52 +0000
@@ -83,6 +83,8 @@
name = "umbrella_green_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Green Umbrella Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Green Umbrella Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/immovables/trees/umbrella_red/init.lua'
--- world/immovables/trees/umbrella_red/init.lua 2015-11-03 18:18:27 +0000
+++ world/immovables/trees/umbrella_red/init.lua 2016-01-26 07:30:52 +0000
@@ -86,6 +86,8 @@
name = "umbrella_red_wasteland_old",
-- TRANSLATORS: This is a fictitious tree. Be creative if you want.
descname = _ "Red Umbrella Tree (Old)",
+ -- TRANSLATORS: This is a fictitious tree. Be creative if you want.
+ basename = _ "Red Umbrella Tree",
editor_category = "trees_wasteland",
size = "small",
attributes = { "tree" },
=== modified file 'world/resources/init.lua'
--- world/resources/init.lua 2016-01-11 22:13:36 +0000
+++ world/resources/init.lua 2016-01-26 07:30:52 +0000
@@ -9,6 +9,8 @@
max_amount = 20,
-- A geologist can find it, otherwise false (see Fish)
detectable = true,
+ -- This represents the resource in menus etc.
+ representative_image = pics_dir .. "coal4.png",
-- Picture that is used to indicate the amount of resource on the map
-- [5] means amount 0 to 5; next line means amount 6 to 10 and so on
-- The picture with highest number is additionally used in ui
@@ -25,6 +27,7 @@
descname = _ "Gold",
max_amount = 20,
detectable = true,
+ representative_image = pics_dir .. "gold4.png",
editor_pictures = {
[5] = pics_dir .. "gold1.png",
[10] = pics_dir .. "gold2.png",
@@ -38,6 +41,7 @@
descname = _ "Iron",
max_amount = 20,
detectable = true,
+ representative_image = pics_dir .. "iron4.png",
editor_pictures = {
[5] = pics_dir .. "iron1.png",
[10] = pics_dir .. "iron2.png",
@@ -51,6 +55,7 @@
descname = _ "Stones",
max_amount = 20,
detectable = true,
+ representative_image = pics_dir .. "stones4.png",
editor_pictures = {
[5] = pics_dir .. "stones1.png",
[10] = pics_dir .. "stones2.png",
@@ -64,6 +69,7 @@
descname = _ "Water",
max_amount = 50,
detectable = true,
+ representative_image = pics_dir .. "water4.png",
editor_pictures = {
[10] = pics_dir .."water1.png",
[20] = pics_dir .."water2.png",
@@ -77,14 +83,11 @@
descname = _ "Fish",
max_amount = 20,
detectable = false,
+ representative_image = pics_dir .. "fish.png",
editor_pictures = {
[5] = pics_dir .. "fish1.png",
[10] = pics_dir .. "fish2.png",
[15] = pics_dir .. "fish3.png",
[1000] = pics_dir .. "fish4.png",
- -- Clutch: The editor chooses the image with the highest number for the
- -- UI. So we keep a nice picture for this purpose at the top of this
- -- list.
- [1001] = pics_dir .. "fish.png",
}
}
Follow ups
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: GunChleoc, 2016-02-12
-
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: GunChleoc, 2016-02-10
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: GunChleoc, 2016-02-10
-
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: bunnybot, 2016-02-08
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: SirVer, 2016-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: GunChleoc, 2016-02-07
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: SirVer, 2016-02-07
-
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: bunnybot, 2016-02-02
-
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: bunnybot, 2016-02-01
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: kaputtnik, 2016-01-29
-
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: bunnybot, 2016-01-29
-
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: bunnybot, 2016-01-27
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: GunChleoc, 2016-01-26
-
Re: [Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: kaputtnik, 2016-01-26
-
[Merge] lp:~widelands-dev/widelands/editor_help into lp:widelands
From: bunnybot, 2016-01-26