diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index 0f16f91b1..8979006be 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -247,8 +247,59 @@ the bearer for one week. - The recipe of this potion is a well kept secret. Some even say it couldn't be brewed by mere mortals. One thing is certain though, the drinker receives further insight into any learned skills, which furthers their progress towards the mastery of those skills. - Die Herstellung dieses Trunkes ist ein wohlgehütetes Geheimnis. Manche behaupten gar, von Sterblichen könne er gar nicht gebraut werden. Tatsache ist, dass er dem Trinkenden tiefere Einsicht in seine erlernten Talente gewährt, was ihn in der Meisterung dieser Talente voranbringt. + + Die Herstellung dieses Trunkes ist ein wohlgehütetes Geheimnis. Manche + behaupten gar, von Sterblichen könne er gar nicht gebraut werden. + Tatsache ist, dass er dem Trinkenden tiefere Einsicht in seine erlernten + Talente gewährt, was ihn in der Meisterung dieser Talente voranbringt. + + + The recipe of this potion is a well kept secret. Some even say it + couldn't be brewed by mere mortals. One thing is certain though, the + drinker receives further insight into any learned skills, which furthers + their progress towards the mastery of those skills. + + + + + Eine Kugel aus Kristallglas von circa drei Zoll Durchmesser, welche auf + einem Sockel aus Granit ruht. + Im Inneren tanzen unzählige winzige Schneeflocken munter umher. Auf der + Unterseite des Sockels ist eine goldene Windrose mit den sechs + Himmelsrichtungen abgebildet. Eigentlich ein sehr schöner Anblick, doch + strahlt sie eine namenlose Kälte aus. + Unter Magiern und anderen der arkanen Künste kundigen ist die Funktion + und Wirkungsweise des Artefaktes heftig umstritten. Einig scheint man + sich darüber zu sein, dass in dieser kleinen Kugel so viel Kälte + gefangen ist, dass es dauerhafte Folgen für eine weiträumige Umgebung + hätte wenn man sie zerstört. Größte Brände ließen sich damit wohl + löschen, Vulkane besänftigen und Unmengen von Wasser zum gefrieren + bringen. Doch auch in weniger extremen Umgebungen würden sich bestimmt + dauerhafte Veränderungen ereignen. + Es wäre sicherlich nicht zu empfehlen das Kleinod einfach fallen zu + lassen. Man sollte es anstelle dessen so weit wie möglich von sich + schleudern und dafür sorge tragen, dass sich am Einschlagsort kein + Lebewesen aufhält. So man denn eine Benutzung tatsächlich riskieren + will. + (BENUTZE Schneekugel <HIMMELSRICHTUNG>) + + + A sphere with a diameter of three inches made of crystal glass, sitting + on a granite base. + On the inside countless tiny snowflakes dance around lively. On the + bottom of the base a golden compass rose is engraved. A beautiful sight + to behold, but it emanates a nameless cold. + Among mages and others knowledgeable in the arcane arts the function and + effect of the artefact are disputed intensely. Although there is + agreement about something: upon release the intensity of the contained + cold would have permanent repercussions for a large area. Gigantic fires + would be extinguished, volcanos quelled and large bodies of water frozen + solid. In less extreme environments permanent changes were also probable. + Therefore it isn't recommended to drop the cold treasure. It should be + thrown far off instead, while making sure there is no living being + within the impact zone, if one is willing to risk the usage. + (USE "snow globe" <DIRECTION>) + diff --git a/res/core/messages.xml b/res/core/messages.xml index c79416c25..b89019aa9 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -14,7 +14,36 @@ your faction with a $resource($item,1). - + + + + + + "$unit($unit) in $region($region): '$order($command)' - Ungültige Zielregion." + "$unit($unit) in $region($region): '$order($command)' - invalid target region." + + + + + + + + + "$unit($unit) in $region($region): '$order($command)' - keine Richtung angegeben." + "$unit($unit) in $region($region): '$order($command)' - no direction was specified." + + + + + + + + + "$unit($unit) in $region($region): '$order($command)' - In der Zielregion befinden sich noch Einheiten." + "$unit($unit) in $region($region): '$order($command)' - There are units in the target region." + + + diff --git a/scripts/eressea/xmasitems.lua b/scripts/eressea/xmasitems.lua index bce82f7e4..4f8a20767 100644 --- a/scripts/eressea/xmasitems.lua +++ b/scripts/eressea/xmasitems.lua @@ -6,7 +6,16 @@ local function get_direction(locale, token) return nil end -function use_snowglobe(u, amount, token) +local function error_message(msg, u, ord) + local msg = message.create(msg) + msg:set_unit("unit", u) + msg:set_region("region", u.region) + msg:set_order("command", ord) + msg:send_faction(u.faction) + return -1 +end + +function use_snowglobe(u, amount, token, ord) local transform = { ocean = "glacier", firewall = "volcano", @@ -17,8 +26,7 @@ function use_snowglobe(u, amount, token) if direction then local r = u.region:next(direction) if r.units() then - -- message "target region not empty" - return -1 + return error_message('target_region_not_empty', u, ord) end if r then local trans = transform[r.terrain] @@ -26,15 +34,13 @@ function use_snowglobe(u, amount, token) r.terrain = trans return 1 else - -- message "invalid terrain" + return error_message('target_region_invalid', u, ord) end else - -- message "invalid terrain" + return error_message('target_region_invalid', u, ord) end - else - -- message "need to specify direction" end - return -1 + return error_message('missing_direction', u, ord) end function use_snowman(u, amount) diff --git a/scripts/tests/xmas.lua b/scripts/tests/xmas.lua index 8c6acb895..7ce416db3 100644 --- a/scripts/tests/xmas.lua +++ b/scripts/tests/xmas.lua @@ -19,6 +19,22 @@ function test_snowglobe_fail() unit.create(f, r2, 1) -- unit in target region => fail process_orders() assert_equal('ocean', r2.terrain) + assert_equal(1, u:get_item('snowglobe')) + assert_equal(1, f:count_msg_type('target_region_not_empty')) +end + +function test_snowglobe_missing_direction() + local r1 = region.create(0, 0, "glacier") + local r2 = region.create(1, 0, "ocean") + local f = faction.create("snowglobe1@eressea.de", "human", "de") + local u = unit.create(f, r1, 1) + u:add_item("snowglobe", 1) + u:clear_orders() + u:add_order("BENUTZEN 1 Schneekugel") + process_orders() + assert_equal('ocean', r2.terrain) + assert_equal(1, u:get_item('snowglobe')) + assert_equal(1, f:count_msg_type('missing_direction')) end function test_snowglobe() @@ -27,6 +43,7 @@ function test_snowglobe() local f = faction.create("snowglobe2@eressea.de", "human", "de") local u = unit.create(f, r1, 1) local have = 6 + local fail = 0 u:add_item("snowglobe", have) local xform = { ocean = "glacier", glacier = "glacier", firewall = "volcano", volcano = "mountain", desert = "plain", plain = "plain" } u:clear_orders() @@ -35,7 +52,12 @@ function test_snowglobe() r2.terrain = k process_orders() assert_equal(v, r2.terrain) - if k~=v then have=have - 1 end + if k~=v then + have=have - 1 + else + fail = fail + 1 + assert_equal(fail, f:count_msg_type('target_region_invalid')) + end assert_equal(have, u:get_item("snowglobe")) end end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36c728d40..eb603bc0b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -139,6 +139,7 @@ set(SERVER_SRC bind_eressea.c bind_faction.c bind_dict.c + bind_order.c bindings.c bind_message.c bind_monsters.c diff --git a/src/bind_faction.c b/src/bind_faction.c index 8cfc21718..dc06c4057 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -224,6 +224,23 @@ static int tolua_faction_addnotice(lua_State * L) return 0; } +static int tolua_faction_count_msg_type(lua_State *L) { + faction *self = (faction *)tolua_tousertype(L, 1, 0); + const char *str = tolua_tostring(L, 2, 0); + int n = 0; + if (self->msgs) { + mlist * ml = self->msgs->begin; + while (ml) { + if (strcmp(str, ml->msg->type->name) == 0) { + ++n; + } + ml = ml->next; + } + } + lua_pushinteger(L, n); + return 1; +} + static int tolua_faction_get_objects(lua_State * L) { faction *self = (faction *)tolua_tousertype(L, 1, 0); @@ -528,12 +545,12 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "id", tolua_faction_get_id, tolua_faction_set_id); - tolua_variable(L, TOLUA_CAST "uid", &tolua_faction_get_uid, - &tolua_faction_set_uid); - tolua_variable(L, TOLUA_CAST "name", &tolua_faction_get_name, - &tolua_faction_set_name); - tolua_variable(L, TOLUA_CAST "info", &tolua_faction_get_info, - &tolua_faction_set_info); + tolua_variable(L, TOLUA_CAST "uid", tolua_faction_get_uid, + tolua_faction_set_uid); + tolua_variable(L, TOLUA_CAST "name", tolua_faction_get_name, + tolua_faction_set_name); + tolua_variable(L, TOLUA_CAST "info", tolua_faction_get_info, + tolua_faction_set_info); tolua_variable(L, TOLUA_CAST "units", tolua_faction_get_units, NULL); tolua_variable(L, TOLUA_CAST "heroes", tolua_faction_get_heroes, NULL); tolua_variable(L, TOLUA_CAST "maxheroes", tolua_faction_get_maxheroes, @@ -549,7 +566,7 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "alliance", tolua_faction_get_alliance, tolua_faction_set_alliance); tolua_variable(L, TOLUA_CAST "score", tolua_faction_get_score, NULL); - tolua_variable(L, TOLUA_CAST "magic", &tolua_faction_get_magic, + tolua_variable(L, TOLUA_CAST "magic", tolua_faction_get_magic, tolua_faction_set_magic); tolua_variable(L, TOLUA_CAST "age", tolua_faction_get_age, tolua_faction_set_age); @@ -559,11 +576,11 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn, tolua_faction_set_lastturn); - tolua_function(L, TOLUA_CAST "set_policy", &tolua_faction_set_policy); - tolua_function(L, TOLUA_CAST "get_policy", &tolua_faction_get_policy); - tolua_function(L, TOLUA_CAST "get_origin", &tolua_faction_get_origin); - tolua_function(L, TOLUA_CAST "set_origin", &tolua_faction_set_origin); - tolua_function(L, TOLUA_CAST "normalize", &tolua_faction_normalize); + tolua_function(L, TOLUA_CAST "set_policy", tolua_faction_set_policy); + tolua_function(L, TOLUA_CAST "get_policy", tolua_faction_get_policy); + tolua_function(L, TOLUA_CAST "get_origin", tolua_faction_get_origin); + tolua_function(L, TOLUA_CAST "set_origin", tolua_faction_set_origin); + tolua_function(L, TOLUA_CAST "normalize", tolua_faction_normalize); tolua_function(L, TOLUA_CAST "add_item", tolua_faction_add_item); tolua_variable(L, TOLUA_CAST "items", tolua_faction_get_items, NULL); @@ -572,7 +589,10 @@ void tolua_faction_open(lua_State * L) tolua_function(L, TOLUA_CAST "create", tolua_faction_create); tolua_function(L, TOLUA_CAST "get", tolua_faction_get); tolua_function(L, TOLUA_CAST "destroy", tolua_faction_destroy); - tolua_function(L, TOLUA_CAST "add_notice", &tolua_faction_addnotice); + tolua_function(L, TOLUA_CAST "add_notice", tolua_faction_addnotice); + + /* tech debt hack, siehe https://paper.dropbox.com/doc/Weihnachten-2015-5tOx5r1xsgGDBpb0gILrv#:h=Probleme-mit-Tests-(Nachtrag-0 */ + tolua_function(L, TOLUA_CAST "count_msg_type", tolua_faction_count_msg_type); tolua_variable(L, TOLUA_CAST "objects", tolua_faction_get_objects, NULL); diff --git a/src/bind_message.c b/src/bind_message.c index 34e43301a..15673f4f6 100644 --- a/src/bind_message.c +++ b/src/bind_message.c @@ -81,6 +81,23 @@ static int msg_set_resource(lua_message * msg, const char *param, const char *re return E_INVALID_MESSAGE; } +static int msg_set_order(lua_message * msg, const char *param, struct order *ord) +{ + if (msg->mtype) { + int i = mtype_get_param(msg->mtype, param); + if (i == msg->mtype->nparameters) { + return E_INVALID_PARAMETER_NAME; + } + if (strcmp(msg->mtype->types[i]->name, "order") != 0) { + return E_INVALID_PARAMETER_TYPE; + } + + msg->args[i].v = (void *)ord; + return E_OK; + } + return E_INVALID_MESSAGE; +} + static int msg_set_unit(lua_message * msg, const char *param, const unit * u) { if (msg->mtype) { @@ -223,6 +240,16 @@ static int tolua_msg_set_resource(lua_State * L) return 1; } +static int tolua_msg_set_order(lua_State * L) +{ + lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); + const char *param = tolua_tostring(L, 2, 0); + struct order *value = (struct order *)tolua_tousertype(L, 3, 0); + int result = msg_set_order(lmsg, param, value); + lua_pushinteger(L, result); + return 1; +} + static int tolua_msg_set_unit(lua_State * L) { lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); @@ -294,6 +321,13 @@ static int tolua_msg_send_faction(lua_State * L) return 0; } +static int tolua_msg_get_type(lua_State * L) +{ + lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); + lua_pushstring(L, lmsg->msg->type->name); + return 1; +} + static int tolua_msg_render(lua_State * L) { lua_message *lmsg = (lua_message *)tolua_tousertype(L, 1, 0); @@ -324,8 +358,10 @@ void tolua_message_open(lua_State * L) tolua_beginmodule(L, TOLUA_CAST "message"); { tolua_function(L, TOLUA_CAST "render", tolua_msg_render); + tolua_variable(L, TOLUA_CAST "type", tolua_msg_get_type, 0); tolua_function(L, TOLUA_CAST "set", tolua_msg_set); tolua_function(L, TOLUA_CAST "set_unit", tolua_msg_set_unit); + tolua_function(L, TOLUA_CAST "set_order", tolua_msg_set_order); tolua_function(L, TOLUA_CAST "set_region", tolua_msg_set_region); tolua_function(L, TOLUA_CAST "set_resource", tolua_msg_set_resource); tolua_function(L, TOLUA_CAST "set_int", tolua_msg_set_int); diff --git a/src/bind_order.c b/src/bind_order.c new file mode 100644 index 000000000..90fc7d3b0 --- /dev/null +++ b/src/bind_order.c @@ -0,0 +1,47 @@ +#include +#include + +/* kernel includes */ +#include +#include + +/* lua includes */ +#include + +#include + +static int tolua_order_get_token(lua_State *L) { + order *ord = (order *)tolua_tousertype(L, 1, 0); + int n = (int)tolua_tonumber(L, 2, 0); + const char * str = 0; + init_order(ord); + while (n-->0) { + str = getstrtoken(); + if (!str) { + return 0; + } + } + + tolua_pushstring(L, str); + return 1; +} + +void tolua_order_open(lua_State * L) +{ + /* register user types */ + tolua_usertype(L, TOLUA_CAST "order"); + + tolua_module(L, NULL, 0); + tolua_beginmodule(L, NULL); + { + tolua_cclass(L, TOLUA_CAST "order", TOLUA_CAST "order", TOLUA_CAST "", + NULL); + tolua_beginmodule(L, TOLUA_CAST "order"); + { + tolua_function(L, TOLUA_CAST "token", tolua_order_get_token); + } + tolua_endmodule(L); + } + tolua_endmodule(L); +} + diff --git a/src/bind_order.h b/src/bind_order.h new file mode 100644 index 000000000..efe1ef373 --- /dev/null +++ b/src/bind_order.h @@ -0,0 +1,14 @@ +#ifndef H_BIND_ORDER_H +#define H_BIND_ORDER_H +#ifdef __cplusplus +extern "C" { +#endif + + struct lua_State; + void tolua_order_open(struct lua_State *L); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/bindings.c b/src/bindings.c index 20a8192e1..cbbd38072 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -19,6 +19,7 @@ without prior permission by the authors of Eressea. #include "bind_message.h" #include "bind_building.h" #include "bind_faction.h" +#include "bind_order.h" #include "bind_ship.h" #include "bind_gmtool.h" #include "bind_region.h" @@ -1157,6 +1158,7 @@ lua_State *lua_init(void) { tolua_faction_open(L); tolua_unit_open(L); tolua_message_open(L); + tolua_order_open(L); tolua_dict_open(L); #ifdef USE_CURSES tolua_gmtool_open(L); diff --git a/src/helpers.c b/src/helpers.c index c784e9901..55cfffb80 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -511,7 +511,8 @@ struct order *ord) tolua_pushusertype(L, (void *)u, TOLUA_CAST "unit"); lua_pushinteger(L, amount); lua_pushstring(L, getstrtoken()); - if (lua_pcall(L, 3, 1, 0) != 0) { + tolua_pushusertype(L, (void *)ord, TOLUA_CAST "order"); + if (lua_pcall(L, 4, 1, 0) != 0) { const char *error = lua_tostring(L, -1); log_error("use(%s) calling '%s': %s.\n", unitname(u), fname, error); lua_pop(L, 1);