From fef57d3fcfc0aa30472fbbb27febf6089da1ff6a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 14 Sep 2019 21:51:13 +0200 Subject: [PATCH 01/11] factions that idle out gift their stuff to friends --- scripts/tests/e2/allies.lua | 15 +++ scripts/tests/e2/init.lua | 1 + src/bind_faction.c | 217 +++++++++++++++++++++--------------- src/kernel/ally.c | 23 ++++ src/kernel/ally.h | 1 + src/kernel/faction.c | 5 +- src/spells/combatspells.c | 3 +- 7 files changed, 171 insertions(+), 94 deletions(-) create mode 100644 scripts/tests/e2/allies.lua diff --git a/scripts/tests/e2/allies.lua b/scripts/tests/e2/allies.lua new file mode 100644 index 000000000..d7164c74b --- /dev/null +++ b/scripts/tests/e2/allies.lua @@ -0,0 +1,15 @@ +require "lunit" + +module("tests.e2.allies", package.seeall, lunit.testcase) + +function test_get_set_ally() + local f1 = faction.create("human") + local f2 = faction.create("human") + + assert_equal(false, f1:get_ally(f2, "guard")) + f1:set_ally(f2, "guard", true) + assert_equal(true, f1:get_ally(f2, "guard")) + assert_equal(false, f1:get_ally(f2, "give")) + f1:set_ally(f2, "give", true) + assert_equal(true, f1:get_ally(f2, "give")) +end diff --git a/scripts/tests/e2/init.lua b/scripts/tests/e2/init.lua index 28d7ebc9b..39178467b 100644 --- a/scripts/tests/e2/init.lua +++ b/scripts/tests/e2/init.lua @@ -1,4 +1,5 @@ require 'tests.e2.carts' +require 'tests.e2.allies' require 'tests.e2.quit' require 'tests.e2.movement' require 'tests.e2.astral' diff --git a/src/bind_faction.c b/src/bind_faction.c index f71e334d1..bb3de9d04 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -7,6 +7,7 @@ #include "bindings.h" #include "magic.h" +#include #include #include #include @@ -48,13 +49,13 @@ int tolua_factionlist_next(lua_State * L) static int tolua_faction_get_units(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); unit **unit_ptr = (unit **)lua_newuserdata(L, sizeof(unit *)); luaL_getmetatable(L, TOLUA_CAST "unit"); lua_setmetatable(L, -2); - *unit_ptr = self->units; + *unit_ptr = f->units; lua_pushcclosure(L, tolua_unitlist_nextf, 1); return 1; @@ -62,7 +63,7 @@ static int tolua_faction_get_units(lua_State * L) int tolua_faction_add_item(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *iname = tolua_tostring(L, 2, NULL); int number = (int)tolua_tonumber(L, 3, 0); int result = -1; @@ -70,7 +71,7 @@ int tolua_faction_add_item(lua_State * L) if (iname != NULL) { const resource_type *rtype = rt_find(iname); if (rtype && rtype->itype) { - item *i = i_change(&self->items, rtype->itype, number); + item *i = i_change(&f->items, rtype->itype, number); result = i ? i->number : 0; } /* if (itype!=NULL) */ } @@ -80,38 +81,38 @@ int tolua_faction_add_item(lua_State * L) static int tolua_faction_get_maxheroes(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushinteger(L, maxheroes(self)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushinteger(L, maxheroes(f)); return 1; } static int tolua_faction_get_heroes(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushinteger(L, countheroes(self)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushinteger(L, countheroes(f)); return 1; } static int tolua_faction_get_score(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushnumber(L, (lua_Number)self->score); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushnumber(L, (lua_Number)f->score); return 1; } static int tolua_faction_get_id(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushinteger(L, self->no); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushinteger(L, f->no); return 1; } static int tolua_faction_set_id(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); int id = (int)tolua_tonumber(L, 2, 0); if (findfaction(id) == NULL) { - renumber_faction(self, id); + renumber_faction(f, id); lua_pushboolean(L, 1); } else { @@ -122,20 +123,20 @@ static int tolua_faction_set_id(lua_State * L) static int tolua_faction_get_magic(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushstring(L, magic_school[self->magiegebiet]); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushstring(L, magic_school[f->magiegebiet]); return 1; } static int tolua_faction_set_magic(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *type = tolua_tostring(L, 2, NULL); int mtype; for (mtype = 0; mtype != MAXMAGIETYP; ++mtype) { if (strcmp(magic_school[mtype], type) == 0) { - self->magiegebiet = (magic_t)mtype; + f->magiegebiet = (magic_t)mtype; break; } } @@ -144,89 +145,89 @@ static int tolua_faction_set_magic(lua_State * L) static int tolua_faction_get_age(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushinteger(L, self->age); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushinteger(L, f->age); return 1; } static int tolua_faction_set_age(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); int age = (int)tolua_tonumber(L, 2, 0); - self->age = age; + f->age = age; return 0; } static int tolua_faction_get_flags(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushinteger(L, self->flags); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushinteger(L, f->flags); return 1; } static int tolua_faction_set_flags(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - int flags = (int)tolua_tonumber(L, 2, self->flags); - self->flags = flags; + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + int flags = (int)tolua_tonumber(L, 2, f->flags); + f->flags = flags; return 1; } static int tolua_faction_get_options(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushinteger(L, self->options); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushinteger(L, f->options); return 1; } static int tolua_faction_set_options(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - int options = (int)tolua_tonumber(L, 2, self->options); - self->options = options; + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + int options = (int)tolua_tonumber(L, 2, f->options); + f->options = options; return 1; } static int tolua_faction_get_lastturn(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushinteger(L, self->lastorders); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushinteger(L, f->lastorders); return 1; } static int tolua_faction_set_lastturn(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - if (self) { - self->lastorders = (int)tolua_tonumber(L, 2, self->lastorders); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + if (f) { + f->lastorders = (int)tolua_tonumber(L, 2, f->lastorders); } return 0; } static int tolua_faction_renumber(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); int no = (int)tolua_tonumber(L, 2, 0); - renumber_faction(self, no); + renumber_faction(f, no); return 0; } static int tolua_faction_addnotice(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *str = tolua_tostring(L, 2, NULL); - addmessage(NULL, self, str, MSG_MESSAGE, ML_IMPORTANT); + addmessage(NULL, f, str, MSG_MESSAGE, ML_IMPORTANT); return 0; } static int tolua_faction_getkey(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *name = tolua_tostring(L, 2, NULL); int flag = atoi36(name); - int value = key_get(self->attribs, flag); + int value = key_get(f->attribs, flag); if (value != 0) { lua_pushinteger(L, value); return 1; @@ -236,16 +237,16 @@ static int tolua_faction_getkey(lua_State * L) static int tolua_faction_setkey(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *name = tolua_tostring(L, 2, NULL); int value = (int)tolua_tonumber(L, 3, 1); int flag = atoi36(name); if (value) { - key_set(&self->attribs, flag, value); + key_set(&f->attribs, flag, value); } else { - key_unset(&self->attribs, flag); + key_unset(&f->attribs, flag); } return 0; } @@ -269,14 +270,14 @@ static int tolua_faction_debug_messages(lua_State * L) static int tolua_faction_get_messages(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); int i = 1; mlist *ml; - if (!self->msgs) { + if (!f->msgs) { return 0; } lua_newtable(L); - for (ml = self->msgs->begin; ml; ml = ml->next, ++i) { + for (ml = f->msgs->begin; ml; ml = ml->next, ++i) { lua_pushnumber(L, i); lua_pushstring(L, ml->msg->type->name); lua_rawset(L, -3); @@ -285,11 +286,11 @@ static int tolua_faction_get_messages(lua_State * L) } static int tolua_faction_count_msg_type(lua_State *L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *str = tolua_tostring(L, 2, NULL); int n = 0; - if (self->msgs) { - mlist * ml = self->msgs->begin; + if (f->msgs) { + mlist * ml = f->msgs->begin; while (ml) { if (strcmp(str, ml->msg->type->name) == 0) { ++n; @@ -330,9 +331,9 @@ static int tolua_faction_set_origin(lua_State * L) static int tolua_faction_get_origin(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); int x = 0, y = 0; - faction_getorigin(self, 0, &x, &y); + faction_getorigin(f, 0, &x, &y); lua_pushinteger(L, x); lua_pushinteger(L, y); @@ -380,48 +381,48 @@ static int tolua_faction_create(lua_State * L) static int tolua_faction_get_password(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - tolua_pushstring(L, faction_getpassword(self)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + tolua_pushstring(L, faction_getpassword(f)); return 1; } static int tolua_faction_set_password(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char * passw = tolua_tostring(L, 2, NULL); - faction_setpassword(self, + faction_setpassword(f, passw ? password_hash(passw, PASSWORD_DEFAULT) : NULL); return 0; } static int tolua_faction_get_email(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - tolua_pushstring(L, faction_getemail(self)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + tolua_pushstring(L, faction_getemail(f)); return 1; } static int tolua_faction_set_email(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - faction_setemail(self, tolua_tostring(L, 2, NULL)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + faction_setemail(f, tolua_tostring(L, 2, NULL)); return 0; } static int tolua_faction_get_locale(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - tolua_pushstring(L, locale_name(self->locale)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + tolua_pushstring(L, locale_name(f->locale)); return 1; } static int tolua_faction_set_locale(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *name = tolua_tostring(L, 2, NULL); const struct locale *loc = get_locale(name); if (loc) { - self->locale = loc; + f->locale = loc; } else { tolua_pushstring(L, "invalid locale"); @@ -432,18 +433,18 @@ static int tolua_faction_set_locale(lua_State * L) static int tolua_faction_get_race(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - tolua_pushstring(L, self->race->_name); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + tolua_pushstring(L, f->race->_name); return 1; } static int tolua_faction_set_race(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); const char *name = tolua_tostring(L, 2, NULL); const race *rc = rc_find(name); if (rc != NULL) { - self->race = rc; + f->race = rc; } return 0; @@ -451,15 +452,15 @@ static int tolua_faction_set_race(lua_State * L) static int tolua_faction_get_name(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - tolua_pushstring(L, faction_getname(self)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + tolua_pushstring(L, faction_getname(f)); return 1; } static int tolua_faction_set_name(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - faction_setname(self, tolua_tostring(L, 2, NULL)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + faction_setname(f, tolua_tostring(L, 2, NULL)); return 0; } @@ -479,44 +480,78 @@ static int tolua_faction_set_uid(lua_State * L) static int tolua_faction_get_info(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - tolua_pushstring(L, faction_getbanner(self)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + tolua_pushstring(L, faction_getbanner(f)); return 1; } static int tolua_faction_set_info(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - faction_setbanner(self, tolua_tostring(L, 2, NULL)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + faction_setbanner(f, tolua_tostring(L, 2, NULL)); return 0; } -static int tolua_faction_get_alliance(lua_State * L) +static int tolua_faction_set_ally(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - tolua_pushusertype(L, f_get_alliance(self), TOLUA_CAST "alliance"); + faction *f1 = (faction *)tolua_tousertype(L, 1, NULL); + faction *f2 = (faction *)tolua_tousertype(L, 2, NULL); + const char *status = tolua_tostring(L, 3, NULL); + bool value = tolua_toboolean(L, 4, 1); + if (status) { + int flag = ally_status(status); + int flags = ally_get(f1->allies, f2); + if (value) { + flags |= flag; + } + else { + flags &= ~flag; + } + ally_set(&f1->allies, f2, flags); + } + return 0; +} + +static int tolua_faction_get_ally(lua_State * L) +{ + faction *f1 = (faction *)tolua_tousertype(L, 1, NULL); + faction *f2 = (faction *)tolua_tousertype(L, 2, NULL); + const char *status = tolua_tostring(L, 3, NULL); + if (f1 && f2 && status) { + int test = ally_status(status); + int flags = ally_get(f1->allies, f2); + lua_pushboolean(L, (test & flags) == test); + return 1; + } + return 0; +} + +static int tolua_faction_get_alliances(lua_State * L) +{ + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + tolua_pushusertype(L, f_get_alliance(f), TOLUA_CAST "alliance"); return 1; } static int tolua_faction_set_alliance(lua_State * L) { - struct faction *self = (struct faction *)tolua_tousertype(L, 1, NULL); + struct faction *f = (struct faction *)tolua_tousertype(L, 1, NULL); struct alliance *alli = (struct alliance *) tolua_tousertype(L, 2, NULL); - setalliance(self, alli); + setalliance(f, alli); return 0; } static int tolua_faction_get_items(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); item **item_ptr = (item **)lua_newuserdata(L, sizeof(item *)); luaL_getmetatable(L, TOLUA_CAST "item"); lua_setmetatable(L, -2); - *item_ptr = self->items; + *item_ptr = f->items; lua_pushcclosure(L, tolua_itemlist_next, 1); @@ -525,8 +560,8 @@ static int tolua_faction_get_items(lua_State * L) static int tolua_faction_tostring(lua_State * L) { - faction *self = (faction *)tolua_tousertype(L, 1, NULL); - lua_pushstring(L, factionname(self)); + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_pushstring(L, factionname(f)); return 1; } @@ -569,8 +604,6 @@ void tolua_faction_open(lua_State * L) tolua_faction_set_locale); tolua_variable(L, TOLUA_CAST "race", tolua_faction_get_race, tolua_faction_set_race); - 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_faction_set_magic); @@ -582,6 +615,12 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "lastturn", tolua_faction_get_lastturn, tolua_faction_set_lastturn); + tolua_variable(L, TOLUA_CAST "alliance", tolua_faction_get_alliances, + tolua_faction_set_alliance); + + tolua_function(L, TOLUA_CAST "set_ally", tolua_faction_set_ally); + tolua_function(L, TOLUA_CAST "get_ally", tolua_faction_get_ally); + 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); diff --git a/src/kernel/ally.c b/src/kernel/ally.c index 4ee6b0f57..300d64e15 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -185,6 +185,29 @@ static int ally_flag(const char *s, int help_mask) return 0; } +int ally_status(const char *s) +{ + if (strcmp(s, "give") == 0) { + return HELP_GIVE; + } + else if (strcmp(s, "fight") == 0) { + return HELP_FIGHT; + } + else if (strcmp(s, "money") == 0) { + return HELP_MONEY; + } + else if (strcmp(s, "travel") == 0) { + return HELP_TRAVEL; + } + else if (strcmp(s, "guard") == 0) { + return HELP_GUARD; + } + else if (strcmp(s, "all") == 0) { + return HELP_ALL; + } + return 0; +} + /** Specifies automatic alliance modes. * If this returns a value then the bits set are immutable between alliance * partners (faction::alliance) and cannot be changed with the HELP command. diff --git a/src/kernel/ally.h b/src/kernel/ally.h index c6cb8fe51..ac7ff6238 100644 --- a/src/kernel/ally.h +++ b/src/kernel/ally.h @@ -14,6 +14,7 @@ struct allies; extern struct attrib_type at_npcfaction; +int ally_status(const char *s); int ally_get(struct allies *al, const struct faction *f); void ally_set(struct allies **p_al, struct faction *f, int status); void write_allies(struct gamedata * data, const struct allies *alist); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index b6bd02659..882c1333a 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -408,9 +408,6 @@ void destroyfaction(faction ** fp) f->next = dead_factions; dead_factions = f; - fset(f, FFL_QUIT); - f->_alive = false; - if (f->spellbook) { spellbook_clear(f->spellbook); free(f->spellbook); @@ -463,6 +460,8 @@ void destroyfaction(faction ** fp) setalliance(f, NULL); } + fset(f, FFL_QUIT); + f->_alive = false; funhash(f); /* units of other factions that were disguised as this faction diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 51059b546..f4b8b6954 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -952,8 +952,7 @@ int sp_hero(struct castorder * co) } } - m = - msg_message("cast_hero_effect", "mage spell amount", fi->unit, sp, targets); + m = msg_message("cast_hero_effect", "mage spell amount", fi->unit, sp, targets); message_all(b, m); msg_release(m); From fa3abe8c322405bd664f85f65370dadce76d6374 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 15 Sep 2019 13:08:50 +0200 Subject: [PATCH 02/11] new bindings for allies. script to fix damage from bug 2608. --- scripts/fix-death.lua | 76 +++++++++++++++++++++++++++++++++++++ scripts/tests/e2/allies.lua | 17 ++++++++- src/bind_faction.c | 35 ++++++++++++++++- 3 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 scripts/fix-death.lua diff --git a/scripts/fix-death.lua b/scripts/fix-death.lua new file mode 100644 index 000000000..992af95d3 --- /dev/null +++ b/scripts/fix-death.lua @@ -0,0 +1,76 @@ +require 'config' + +eressea.read_game('1137.dat') + +local dead = {"cwz", "rama"} + + +local function list_items(f) + local items = {} + for u in f.units do + local r = u.region + for name in u.items do + local count = u:get_item(name) + if not items[r.id] then + items[r.id] = {} + end + if not items[r.id][name] then + items[r.id][name] = count + else + items[r.id][name] = items[r.id][name] + count + end + end + end + return items +end + +gifts = {} +info = {} + +for _, no in ipairs(dead) do + f = get_faction(no) + gifts[f.id] = list_items(f) + local allies = {} + for fno, as in pairs(f.allies) do + local f2 = get_faction(fno) + if f2:get_ally(f, 'give') then + allies[fno] = as + end + end + info[f.id] = { + ['name'] = f.name, + ['race'] = f.race, + ['allies'] = allies + } +end + +eressea.free_game() +eressea.read_game('1138.dat') + +newf = {} + +for fid, rlist in pairs(gifts) do + local name = "Erben von " . info[fid].name + local race = info[fid].race + local f = faction.create(race, "noreply@eressea.de") + f.name = name + f.age = 10 + f.lastturn = 1130 + table.insert(newf, f) + for rid, items in pairs(rlist) do + local r = get_region_by_id(rid) + local u = unit.create(f, r, 1) + for name, count in pairs(items) do + u:add_item(name, count) + end + end + for fno, as in pairs(info[fid].allies) do + local f2 = get_faction(fno) + for _, s in ipairs(as) do + f:set_ally(f2, s) + end + f2:set_ally(f, "give") + end +end + +eressea.write_game('1138.new.dat') diff --git a/scripts/tests/e2/allies.lua b/scripts/tests/e2/allies.lua index d7164c74b..9f86e5f7c 100644 --- a/scripts/tests/e2/allies.lua +++ b/scripts/tests/e2/allies.lua @@ -2,7 +2,7 @@ require "lunit" module("tests.e2.allies", package.seeall, lunit.testcase) -function test_get_set_ally() +function skip_test_get_set_ally() local f1 = faction.create("human") local f2 = faction.create("human") @@ -13,3 +13,18 @@ function test_get_set_ally() f1:set_ally(f2, "give", true) assert_equal(true, f1:get_ally(f2, "give")) end + +function test_get_allies() + local f1 = faction.create("human") + local f2 = faction.create("human") + + local allies = f1.allies + assert_equal('table', type(allies)) + assert_equal(0, #allies) + f1:set_ally(f2, "give", true) + allies = f1.allies + assert_not_nil(1, table.getn(allies)) + assert_equal('table', type(allies[f2.id])) + assert_equal(1, #allies[f2.id]) + assert_equal("give", allies[f2.id][1]) +end diff --git a/src/bind_faction.c b/src/bind_faction.c index bb3de9d04..fd6983f0d 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -492,8 +492,38 @@ static int tolua_faction_set_info(lua_State * L) return 0; } -static int tolua_faction_set_ally(lua_State * L) -{ +/* TODO: this is probably useful elsewhere */ +static const char *status_names[] = { + "money", "fight", "observe", "give", "guard", "stealth", "travel", NULL +}; + +static int cb_ally_push(struct allies *af, struct faction *f, int status, void *udata) { + struct lua_State *L = (struct lua_State *)udata; + int len = 1; + int i; + + lua_pushnumber(L, f->no); + lua_newtable(L); + for (i = 0; status_names[i]; ++i) { + int flag = 1 << i; + if (status & flag) { + lua_pushstring(L, status_names[i]); + lua_rawseti(L, -2, len++); + } + } + + lua_rawset(L, -3); + return 0; +} + +static int tolua_faction_get_allies(lua_State * L) { + faction *f = (faction *)tolua_tousertype(L, 1, NULL); + lua_newtable(L); + allies_walk(f->allies, cb_ally_push, L); + return 1; +} + +static int tolua_faction_set_ally(lua_State * L) { faction *f1 = (faction *)tolua_tousertype(L, 1, NULL); faction *f2 = (faction *)tolua_tousertype(L, 2, NULL); const char *status = tolua_tostring(L, 3, NULL); @@ -618,6 +648,7 @@ void tolua_faction_open(lua_State * L) tolua_variable(L, TOLUA_CAST "alliance", tolua_faction_get_alliances, tolua_faction_set_alliance); + tolua_variable(L, TOLUA_CAST "allies", tolua_faction_get_allies, NULL); tolua_function(L, TOLUA_CAST "set_ally", tolua_faction_set_ally); tolua_function(L, TOLUA_CAST "get_ally", tolua_faction_get_ally); From 52f08917d51a331ce7cdc613728e27246a6690dd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 15 Sep 2019 13:37:04 +0200 Subject: [PATCH 03/11] getn is deprecated --- scripts/tests/e2/allies.lua | 2 +- src/bind_faction.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/tests/e2/allies.lua b/scripts/tests/e2/allies.lua index 9f86e5f7c..ef38a97bf 100644 --- a/scripts/tests/e2/allies.lua +++ b/scripts/tests/e2/allies.lua @@ -23,7 +23,7 @@ function test_get_allies() assert_equal(0, #allies) f1:set_ally(f2, "give", true) allies = f1.allies - assert_not_nil(1, table.getn(allies)) + assert_not_nil(allies[f2.id]) assert_equal('table', type(allies[f2.id])) assert_equal(1, #allies[f2.id]) assert_equal("give", allies[f2.id][1]) diff --git a/src/bind_faction.c b/src/bind_faction.c index fd6983f0d..56164785d 100644 --- a/src/bind_faction.c +++ b/src/bind_faction.c @@ -32,7 +32,10 @@ #include #include #include -#include +#include // for bool +#include // for puts + +struct allies; int tolua_factionlist_next(lua_State * L) { From 65689df308a463587f434961fab86a40432e802d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 15 Sep 2019 14:12:18 +0200 Subject: [PATCH 04/11] quit faction is still disabled --- scripts/tests/e2/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/tests/e2/init.lua b/scripts/tests/e2/init.lua index 39178467b..afe0ac5ad 100644 --- a/scripts/tests/e2/init.lua +++ b/scripts/tests/e2/init.lua @@ -1,6 +1,5 @@ require 'tests.e2.carts' require 'tests.e2.allies' -require 'tests.e2.quit' require 'tests.e2.movement' require 'tests.e2.astral' require 'tests.e2.spells' From 93e82fc6ae1820885af58b4cb68a6a99686b0c0b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 15 Sep 2019 14:30:50 +0200 Subject: [PATCH 05/11] concat in Lua is not PHP --- scripts/fix-death.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/fix-death.lua b/scripts/fix-death.lua index 992af95d3..8f0b52e08 100644 --- a/scripts/fix-death.lua +++ b/scripts/fix-death.lua @@ -50,7 +50,7 @@ eressea.read_game('1138.dat') newf = {} for fid, rlist in pairs(gifts) do - local name = "Erben von " . info[fid].name + local name = "Erben von " .. info[fid].name local race = info[fid].race local f = faction.create(race, "noreply@eressea.de") f.name = name From ea9e31d1b2eea6463108886019bf1f4da906194c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 15 Sep 2019 20:32:07 +0200 Subject: [PATCH 06/11] tests for trolls riding on carts. --- scripts/tests/e2/carts.lua | 47 ++++++ src/bind_unit.c | 293 +++++++++++++++++++------------------ 2 files changed, 194 insertions(+), 146 deletions(-) diff --git a/scripts/tests/e2/carts.lua b/scripts/tests/e2/carts.lua index c2acbc25e..025b473df 100644 --- a/scripts/tests/e2/carts.lua +++ b/scripts/tests/e2/carts.lua @@ -185,3 +185,50 @@ function test_trolls_pull_carts() process_orders() assert_equal(r1, u1.region) end + +function test_trolls_with_horses() + local r0 = region.create(0, 0, "plain") + local r1 = region.create(1, 0, "plain") + local r2 = region.create(2, 0, "plain") + local r3 = region.create(3, 0, "plain") + local f = faction.create("troll") + -- 1. 20 trolls can pull 5 loaded carts: + local u1 = unit.create(f, r0, 20) + u1:add_item("cart", 5) + -- trolls carry 10.8 GE, carts carry 100 GE: + u1:add_item("money", 100 * (5 * 100 + 2 * 108)) + u1:add_order("NACH O O O") + + process_orders() + assert_equal(r1, u1.region) + + u1:add_item("horse", 20) + u1:add_item("money", 100 * 20 * 20) + process_orders() + assert_equal(r2, u1.region) +end + +function test_trolls_ride_carts() + local r0 = region.create(0, 0, "plain") + local r1 = region.create(1, 0, "plain") + local r2 = region.create(2, 0, "plain") + local r3 = region.create(3, 0, "plain") + local r4 = region.create(4, 0, "plain") + local f = faction.create("troll") + -- 1. 20 trolls can pull 5 loaded carts: + local u1 = unit.create(f, r0, 20) + u1:add_item("cart", 5) + -- but with 10 or more horses, they should ride in the cart: + u1:set_skill("riding", 1, true) + u1:add_item("horse", 10) + -- trolls weigh 20 GE, horses carry 20, carts carry 100 GE: + u1:add_item("money", 100 * (10 * 20 + 5 * 100 - u1.number * 20)) + u1:add_order("NACH O O O") + + process_orders() + assert_equal(r2, u1.region) + + u1:add_item("money", 1) -- just one wafer thin mint + process_orders() + assert_equal(r3, u1.region) -- can still walk +end diff --git a/src/bind_unit.c b/src/bind_unit.c index c5954082b..f12b60b55 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -147,129 +147,129 @@ static int tolua_unit_get_group(lua_State * L) static int tolua_unit_set_group(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - group *g = join_group(self, tolua_tostring(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + group *g = join_group(u, tolua_tostring(L, 2, 0)); lua_pushboolean(L, g!=NULL); return 1; } static int tolua_unit_get_name(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushstring(L, unit_getname(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushstring(L, unit_getname(u)); return 1; } static int tolua_unit_set_name(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - unit_setname(self, tolua_tostring(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + unit_setname(u, tolua_tostring(L, 2, 0)); return 0; } static int tolua_unit_get_info(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushstring(L, unit_getinfo(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushstring(L, unit_getinfo(u)); return 1; } static int tolua_unit_set_info(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - unit_setinfo(self, tolua_tostring(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + unit_setinfo(u, tolua_tostring(L, 2, 0)); return 0; } static int tolua_unit_get_id(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, unit_getid(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, unit_getid(u)); return 1; } static int tolua_unit_set_id(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - unit_setid(self, (int)tolua_tonumber(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + unit_setid(u, (int)tolua_tonumber(L, 2, 0)); return 0; } static int tolua_unit_get_auramax(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, max_spellpoints_depr(self->region, self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, max_spellpoints_depr(u->region, u)); return 1; } static int tolua_unit_get_hpmax(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, unit_max_hp(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, unit_max_hp(u)); return 1; } static int tolua_unit_get_hp(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, unit_gethp(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, unit_gethp(u)); return 1; } static int tolua_unit_set_hp(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - unit_sethp(self, (int)tolua_tonumber(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + unit_sethp(u, (int)tolua_tonumber(L, 2, 0)); return 0; } static int tolua_unit_get_number(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, self->number); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, u->number); return 1; } static int tolua_unit_set_number(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); int number = (int)tolua_tonumber(L, 2, 0); - if (self->number == 0) { - set_number(self, number); - self->hp = unit_max_hp(self) * number; + if (u->number == 0) { + set_number(u, number); + u->hp = unit_max_hp(u) * number; } else { - scale_number(self, number); + scale_number(u, number); } return 0; } static int tolua_unit_get_flags(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, self->flags); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, u->flags); return 1; } static int tolua_unit_set_flags(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - self->flags = (int)tolua_tonumber(L, 2, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + u->flags = (int)tolua_tonumber(L, 2, 0); return 0; } static int tolua_unit_get_guard(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushboolean(L, is_guard(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushboolean(L, is_guard(u)); return 1; } static int tolua_unit_set_guard(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); unsigned int flags = (unsigned int)tolua_tonumber(L, 2, 0); - setguard(self, flags!=0); + setguard(u, flags!=0); return 0; } @@ -285,8 +285,8 @@ static const char *unit_getmagic(const unit * u) static int tolua_unit_get_magic(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushstring(L, unit_getmagic(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushstring(L, unit_getmagic(u)); return 1; } @@ -306,64 +306,64 @@ static void unit_setmagic(unit * u, const char *type) static int tolua_unit_set_magic(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *type = tolua_tostring(L, 2, 0); - unit_setmagic(self, type); + unit_setmagic(u, type); return 0; } static int tolua_unit_get_aura(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, get_spellpoints(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, get_spellpoints(u)); return 1; } static int tolua_unit_set_aura(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - set_spellpoints(self, (int)tolua_tonumber(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + set_spellpoints(u, (int)tolua_tonumber(L, 2, 0)); return 0; } static int tolua_unit_get_age(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, self->age); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, u->age); return 1; } static int tolua_unit_set_age(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - self->age = (int)tolua_tonumber(L, 2, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + u->age = (int)tolua_tonumber(L, 2, 0); return 0; } static int tolua_unit_get_status(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, unit_getstatus(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, unit_getstatus(u)); return 1; } static int tolua_unit_set_status(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - unit_setstatus(self, (status_t)tolua_tonumber(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + unit_setstatus(u, (status_t)tolua_tonumber(L, 2, 0)); return 0; } static int tolua_unit_get_item(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *iname = tolua_tostring(L, 2, 0); int result = -1; if (iname != NULL) { const item_type *itype = it_find(iname); if (itype != NULL) { - result = i_get(self->items, itype); + result = i_get(u->items, itype); } } lua_pushinteger(L, result); @@ -372,13 +372,13 @@ static int tolua_unit_get_item(lua_State * L) static int tolua_unit_get_effect(lua_State * L) { - const unit *self = (unit *)tolua_tousertype(L, 1, 0); + const unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *potion_name = tolua_tostring(L, 2, 0); int result = -1; const item_type *it_potion = it_find(potion_name); if (it_potion != NULL) { - result = get_effect(self, it_potion); + result = get_effect(u, it_potion); } lua_pushinteger(L, result); @@ -387,7 +387,7 @@ static int tolua_unit_get_effect(lua_State * L) static int tolua_unit_add_item(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *iname = tolua_tostring(L, 2, 0); int number = (int)tolua_tonumber(L, 3, 0); int result = -1; @@ -395,7 +395,7 @@ static int tolua_unit_add_item(lua_State * L) if (iname != NULL) { const item_type *itype = it_find(iname); if (itype != NULL) { - item *i = i_change(&self->items, itype, number); + item *i = i_change(&u->items, itype, number); result = i ? i->number : 0; } } @@ -405,12 +405,12 @@ static int tolua_unit_add_item(lua_State * L) static int tolua_unit_getskill(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *skname = tolua_tostring(L, 2, 0); skill_t sk = findskill(skname); int value = -1; if (sk != NOSKILL) { - skill *sv = unit_skill(self, sk); + skill *sv = unit_skill(u, sk); if (sv) { value = sv->level; } @@ -423,10 +423,10 @@ static int tolua_unit_getskill(lua_State * L) static int tolua_unit_effskill(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *skname = tolua_tostring(L, 2, 0); skill_t sk = findskill(skname); - int value = (sk == NOSKILL) ? -1 : effskill(self, sk, NULL); + int value = (sk == NOSKILL) ? -1 : effskill(u, sk, NULL); lua_pushinteger(L, value); return 1; } @@ -438,10 +438,10 @@ typedef struct event { static int tolua_unit_addnotice(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *str = tolua_tostring(L, 2, 0); - addmessage(self->region, self->faction, str, MSG_MESSAGE, ML_IMPORTANT); + addmessage(u->region, u->faction, str, MSG_MESSAGE, ML_IMPORTANT); return 0; } @@ -475,11 +475,11 @@ static void unit_castspell(unit * u, const char *name, int level) static int tolua_unit_castspell(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *str = tolua_tostring(L, 2, 0); int level = (int)tolua_tonumber(L, 3, 1); - unit_castspell(self, str, level); + unit_castspell(u, str, level); return 0; } @@ -505,17 +505,17 @@ static int tolua_unit_addspell(lua_State * L) static int tolua_unit_set_racename(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *str = tolua_tostring(L, 2, 0); - set_racename(&self->attribs, str); + set_racename(&u->attribs, str); return 0; } static int tolua_unit_get_racename(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - attrib *a = a_find(self->attribs, &at_racename); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + attrib *a = a_find(u->attribs, &at_racename); if (a) { tolua_pushstring(L, get_racename(a)); return 1; @@ -525,29 +525,30 @@ static int tolua_unit_get_racename(lua_State * L) static int tolua_unit_setskill(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *skname = tolua_tostring(L, 2, 0); int level = (int)tolua_tonumber(L, 3, 0); + bool rcmod = tolua_toboolean(L, 4, 0); skill_t sk = findskill(skname); + + if (rcmod) level -= u_race(u)->bonus[sk]; if (sk != NOSKILL) { - set_level(self, sk, level); + set_level(u, sk, level); + lua_pushinteger(L, level); + return 1; } - else { - level = -1; - } - lua_pushinteger(L, level); - return 1; + return 0; } static int tolua_unit_use_pooled(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *iname = tolua_tostring(L, 2, 0); int number = (int)tolua_tonumber(L, 3, 0); const resource_type *rtype = rt_find(iname); int result = -1; if (rtype != NULL) { - result = use_pooled(self, rtype, GET_DEFAULT, number); + result = use_pooled(u, rtype, GET_DEFAULT, number); } lua_pushinteger(L, result); return 1; @@ -555,12 +556,12 @@ static int tolua_unit_use_pooled(lua_State * L) static int tolua_unit_get_pooled(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *iname = tolua_tostring(L, 2, 0); const resource_type *rtype = rt_find(iname); int result = -1; if (rtype != NULL) { - result = get_pooled(self, rtype, GET_DEFAULT, INT_MAX); + result = get_pooled(u, rtype, GET_DEFAULT, INT_MAX); } lua_pushinteger(L, result); return 1; @@ -577,8 +578,8 @@ static unit *unit_getfamiliar(const unit * u) static int tolua_unit_get_familiar(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushusertype(L, unit_getfamiliar(self), TOLUA_CAST "unit"); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushusertype(L, unit_getfamiliar(u), TOLUA_CAST "unit"); return 1; } @@ -597,8 +598,8 @@ static int tolua_unit_set_familiar(lua_State * L) static int tolua_unit_get_building(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushusertype(L, self->building, TOLUA_CAST "building"); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushusertype(L, u->building, TOLUA_CAST "building"); return 1; } @@ -622,8 +623,8 @@ static int tolua_unit_set_building(lua_State * L) static int tolua_unit_get_ship(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushusertype(L, self->ship, TOLUA_CAST "ship"); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushusertype(L, u->ship, TOLUA_CAST "ship"); return 1; } @@ -638,17 +639,17 @@ static void unit_setship(unit * u, ship * s) static int tolua_unit_set_ship(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - if (self->faction) { - unit_setship(self, (ship *)tolua_tousertype(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + if (u->faction) { + unit_setship(u, (ship *)tolua_tousertype(L, 2, 0)); } return 0; } static int tolua_unit_get_region(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushusertype(L, self->region, TOLUA_CAST "region"); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushusertype(L, u->region, TOLUA_CAST "region"); return 1; } @@ -659,29 +660,29 @@ static void unit_setregion(unit * u, region * r) static int tolua_unit_set_region(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - unit_setregion(self, (region *)tolua_tousertype(L, 2, 0)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + unit_setregion(u, (region *)tolua_tousertype(L, 2, 0)); return 0; } static int tolua_unit_get_order(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); int index = (int)tolua_tonumber(L, 2, -1); order *ord = NULL; if (index < 0) { - ord = self->thisorder; + ord = u->thisorder; } else { int i; - ord = self->orders; + ord = u->orders; for (i = 0; ord && i != index; ++i) { ord = ord->next; } } if (ord) { char buffer[1024]; - get_command(ord, self->faction->locale, buffer, sizeof(buffer)); + get_command(ord, u->faction->locale, buffer, sizeof(buffer)); lua_pushstring(L, buffer); return 1; } @@ -690,30 +691,30 @@ static int tolua_unit_get_order(lua_State * L) static int tolua_unit_add_order(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *str = tolua_tostring(L, 2, 0); - order *ord = parse_order(str, self->faction->locale); - unit_addorder(self, ord); + order *ord = parse_order(str, u->faction->locale); + unit_addorder(u, ord); return 0; } static int tolua_unit_clear_orders(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - free_orders(&self->orders); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + free_orders(&u->orders); return 0; } static int tolua_unit_get_items(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); item **item_ptr = (item **)lua_newuserdata(L, sizeof(item *)); luaL_getmetatable(L, TOLUA_CAST "item"); lua_setmetatable(L, -2); - *item_ptr = self->items; + *item_ptr = u->items; lua_pushcclosure(L, tolua_itemlist_next, 1); @@ -722,8 +723,8 @@ static int tolua_unit_get_items(lua_State * L) static int tolua_unit_get_spells(lua_State * L) { - unit *self = (unit *) tolua_tousertype(L, 1, 0); - struct sc_mage *mage = self ? get_mage(self) : NULL; + unit *u = (unit *) tolua_tousertype(L, 1, 0); + struct sc_mage *mage = u ? get_mage(u) : NULL; spellbook *sb = mage_get_spellbook(mage); selist *slist = 0; if (sb) { @@ -734,10 +735,10 @@ static int tolua_unit_get_spells(lua_State * L) } static int tolua_unit_get_curse(lua_State *L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); - if (self->attribs) { - curse * c = get_curse(self->attribs, ct_find(name)); + if (u->attribs) { + curse * c = get_curse(u->attribs, ct_find(name)); if (c) { lua_pushnumber(L, curse_geteffect(c)); return 1; @@ -747,9 +748,9 @@ static int tolua_unit_get_curse(lua_State *L) { } static int tolua_unit_has_attrib(lua_State *L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); - attrib * a = self->attribs; + attrib * a = u->attribs; while (a) { if (strcmp(a->type->name, name) == 0) { break; @@ -762,105 +763,105 @@ static int tolua_unit_has_attrib(lua_State *L) { static int tolua_unit_get_key(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); int flag = atoi36(name); - lua_pushboolean(L, key_get(self->attribs, flag)); + lua_pushboolean(L, key_get(u->attribs, flag)); return 1; } static int tolua_unit_set_key(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *name = tolua_tostring(L, 2, 0); int value = (int)tolua_tonumber(L, 3, 0); int flag = atoi36(name); if (value) { - key_set(&self->attribs, flag, value); + key_set(&u->attribs, flag, value); } else { - key_unset(&self->attribs, flag); + key_unset(&u->attribs, flag); } return 0; } static int tolua_unit_get_flag(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, NULL); + unit *u = (unit *)tolua_tousertype(L, 1, NULL); int bit = (int)tolua_tonumber(L, 2, 0); - lua_pushboolean(L, (self->flags & (1 << bit))); + lua_pushboolean(L, (u->flags & (1 << bit))); return 1; } static int tolua_unit_set_flag(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, NULL); + unit *u = (unit *)tolua_tousertype(L, 1, NULL); int bit = (int)tolua_tonumber(L, 2, 0); int set = tolua_toboolean(L, 3, 1); if (set) - self->flags |= (1 << bit); + u->flags |= (1 << bit); else - self->flags &= ~(1 << bit); + u->flags &= ~(1 << bit); return 0; } static int tolua_unit_get_weight(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, unit_getweight(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, unit_getweight(u)); return 1; } static int tolua_unit_get_capacity(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushinteger(L, unit_getcapacity(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushinteger(L, unit_getcapacity(u)); return 1; } static int tolua_unit_get_faction(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushusertype(L, (void *)self->faction, TOLUA_CAST "faction"); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushusertype(L, (void *)u->faction, TOLUA_CAST "faction"); return 1; } static int tolua_unit_set_faction(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); faction *f = (faction *)tolua_tousertype(L, 2, 0); - u_setfaction(self, f); + u_setfaction(u, f); return 0; } static int tolua_unit_get_race(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - tolua_pushstring(L, u_race(self)->_name); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + tolua_pushstring(L, u_race(u)->_name); return 1; } static int tolua_unit_set_race(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); + unit *u = (unit *)tolua_tousertype(L, 1, 0); const char *rcname = tolua_tostring(L, 2, 0); const race *rc = rc_find(rcname); if (rc != NULL) { - if (self->irace == u_race(self)) { - self->irace = NULL; + if (u->irace == u_race(u)) { + u->irace = NULL; } - u_setrace(self, rc); + u_setrace(u, rc); } return 0; } static int tolua_unit_destroy(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - if (self) { - remove_unit(&self->region->units, self); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + if (u) { + remove_unit(&u->region->units, u); } return 0; } @@ -884,25 +885,25 @@ static int tolua_unit_create(lua_State * L) static int tolua_unit_tostring(lua_State * L) { - unit *self = (unit *)tolua_tousertype(L, 1, 0); - lua_pushstring(L, unitname(self)); + unit *u = (unit *)tolua_tousertype(L, 1, 0); + lua_pushstring(L, unitname(u)); return 1; } static int tolua_event_gettype(lua_State * L) { - event *self = (event *)tolua_tousertype(L, 1, 0); + event *u = (event *)tolua_tousertype(L, 1, 0); int index = (int)tolua_tonumber(L, 2, 0); - lua_pushstring(L, self->args[index].type); + lua_pushstring(L, u->args[index].type); return 1; } static int tolua_event_get(lua_State * L) { - struct event *self = (struct event *)tolua_tousertype(L, 1, 0); + struct event *u = (struct event *)tolua_tousertype(L, 1, 0); int index = (int)tolua_tonumber(L, 2, 0); - event_arg *arg = self->args + index; + event_arg *arg = u->args + index; if (arg->type) { if (strcmp(arg->type, "string") == 0) { From d5104fa55a02186fc0abd2192a112da39b9150d8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 18 Sep 2019 20:55:44 +0200 Subject: [PATCH 07/11] Bug 2609 VERGESSE Magie --- src/economy.c | 18 +++++++++++++++--- src/kernel/faction.c | 2 +- src/kernel/unit.c | 11 +++++++++++ src/kernel/unit.h | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/economy.c b/src/economy.c index 1fd202369..b73845c06 100644 --- a/src/economy.c +++ b/src/economy.c @@ -282,9 +282,21 @@ static int forget_cmd(unit * u, order * ord) sk = get_skill(s, u->faction->locale); if (sk != NOSKILL) { - if (sk == SK_MAGIC && is_familiar(u)) { - /* some units cannot forget their innate magical abilities */ - return 0; + if (sk == SK_MAGIC) { + if (is_familiar(u)) { + /* some units cannot forget their innate magical abilities */ + return 0; + } + else { + unit *ufam = get_familiar(u); + if (ufam) { + a_removeall(&ufam->attribs, NULL); + u_setfaction(ufam, get_monsters()); + unit_convert_race(ufam, NULL, "ghost"); + } + a_removeall(&u->attribs, &at_mage); + a_removeall(&u->attribs, &at_familiar); + } } ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk)); set_level(u, sk, 0); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 882c1333a..81f2d42b1 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -395,7 +395,7 @@ void save_special_items(unit *usrc) /* some units have plural names, it would be neat if they aren't single: */ scale_number(u, 2); } - set_racename(&u->attribs, "ghost"); + unit_convert_race(u, rc_ghost, "ghost"); give_special_items(u, &usrc->items); } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index f8e737587..06463820c 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1833,3 +1833,14 @@ double u_heal_factor(const unit * u) } return 1.0; } + +void unit_convert_race(unit *u, const race *rc, const char *rcname) +{ + if (rc && u->_race != rc) { + u_setrace(u, rc); + } + if (rcname && strcmp(rcname, u->_race->_name) != 0) { + set_racename(&u->attribs, rcname); + } +} + diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 3290c4f78..863dccd13 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -221,6 +221,7 @@ extern "C" { char *write_unitname(const struct unit *u, char *buffer, size_t size); bool unit_name_equals_race(const struct unit *u); + void unit_convert_race(struct unit *u, const struct race *rc, const char *rcname); /* getunit results: */ #define GET_UNIT 0 #define GET_NOTFOUND 1 From 8433052c649e3a79756edabbe35ea4a69e9babff Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 19 Sep 2019 05:05:13 +0200 Subject: [PATCH 08/11] CID 204092: Memory - illegal accesses (NEGATIVE_RETURNS) --- src/bind_unit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bind_unit.c b/src/bind_unit.c index 921dcc659..45b4d7d0a 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -531,8 +531,8 @@ static int tolua_unit_setskill(lua_State * L) bool rcmod = tolua_toboolean(L, 4, 0); skill_t sk = findskill(skname); - if (rcmod) level -= u_race(u)->bonus[sk]; if (sk != NOSKILL) { + if (rcmod) level -= u_race(u)->bonus[sk]; set_level(u, sk, level); lua_pushinteger(L, level); return 1; From 6c73a58608316eb74925cb3f5f4fa91623654002 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 21 Sep 2019 22:16:46 +0200 Subject: [PATCH 09/11] =?UTF-8?q?Bug=202607:=20BEnutze=20format=5Flist=20f?= =?UTF-8?q?=C3=BCr=20Schemen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clibs | 2 +- res/translations/strings.de.po | 19 ++++++++---- res/translations/strings.en.po | 19 ++++++++---- src/report.c | 53 ++++++++++++++++++++++------------ src/teleport.c | 28 +++++++++++++++++- src/teleport.h | 3 ++ 6 files changed, 93 insertions(+), 31 deletions(-) diff --git a/clibs b/clibs index f8969f44d..abe774f70 160000 --- a/clibs +++ b/clibs @@ -1 +1 @@ -Subproject commit f8969f44de1ec413cfee82b23c9f4b3c32d49b56 +Subproject commit abe774f70265de14ea7f5e530518ca130562a9c9 diff --git a/res/translations/strings.de.po b/res/translations/strings.de.po index 8c90d6657..68f126335 100644 --- a/res/translations/strings.de.po +++ b/res/translations/strings.de.po @@ -570,8 +570,20 @@ msgstr "Dieses Ritual, ausgeführt vor einem Kampf, verwirbelt die astralen Ener msgid "balloon" msgstr "Ballon" -msgid "nr_schemes_postfix" -msgstr "sind erkennbar." +msgid "nr_schemes_template" +msgstr "Schemen der Regionen {0} sind erkennbar." + +msgid "list_two" +msgstr "{0} und {1}" + +msgid "list_start" +msgstr "{0}, {1}" + +msgid "list_middle" +msgstr "{0}, {1}" + +msgid "list_end" +msgstr "{0} und {1}" msgid "SILBER" msgstr "SILBER" @@ -4408,9 +4420,6 @@ msgstr "Magie" msgid "see_lighthouse" msgstr "vom Turm erblickt" -msgid "nr_schemes_prefix" -msgstr "Schemen der Regionen" - msgid "aoc_p" msgstr "Katzenamulette" diff --git a/res/translations/strings.en.po b/res/translations/strings.en.po index 13badb9cb..36020a3f6 100644 --- a/res/translations/strings.en.po +++ b/res/translations/strings.en.po @@ -444,9 +444,6 @@ msgctxt "spellinfo" msgid "draigfumbleshield" msgstr "This ritual, performed before a battle, causes the astral energies on the battlefield to whirl and churn and thereby makes spellcasting more difficult for the enemy mages." -msgid "nr_schemes_postfix" -msgstr "can be discerned." - msgid "SILBER" msgstr "SILVER" @@ -3937,8 +3934,20 @@ msgstr "magic" msgid "see_lighthouse" msgstr "from lighthouse" -msgid "nr_schemes_prefix" -msgstr "Schemes of " +msgid "list_two" +msgstr "{0} and {1}" + +msgid "list_start" +msgstr "{0}, {1}" + +msgid "list_middle" +msgstr "{0}, {1}" + +msgid "list_end" +msgstr "{0}, and {1}" + +msgid "nr_schemes_template" +msgstr "Schemes of {0} can be discerned." msgid "aoc_p" msgstr "amulets of the kitten" diff --git a/src/report.c b/src/report.c index 38f27e327..904fd6f14 100644 --- a/src/report.c +++ b/src/report.c @@ -71,6 +71,7 @@ #include #include +#include #include #include #include @@ -1053,33 +1054,47 @@ static void report_region_edges(struct stream *out, const region * r, faction * } } +char *report_list(const struct locale *lang, char *buffer, size_t len, int argc, const char **argv) { + const char *two = LOC(lang, "list_two"); + const char *start = LOC(lang, "list_start"); + const char *middle = LOC(lang, "list_middle"); + const char *end = LOC(lang, "list_end"); + return format_list(argc, argv, buffer, len, two, start, middle, end); +} + +#define MAX_SCHEMES ((TP_RADIUS * 2 + 1) * (TP_RADIUS * 2 + 1) - 4) + static void report_region_schemes(struct stream *out, const region * r, faction * f) { - char buf[4096]; - sbstring sbs; - sbs_init(&sbs, buf, sizeof(buf)); if (r->seen.mode >= seen_unit && is_astral(r) && !is_cursed(r->attribs, &ct_astralblock)) { /* Sonderbehandlung Teleport-Ebene */ - region_list *rl = astralregions(r, inhabitable); - region_list *rl2; + region *rl[MAX_SCHEMES]; + int num = get_astralregions(r, inhabitable, rl); + char buf[4096]; - if (rl) { - /* this localization might not work for every language but is fine for de and en */ - sbs_strcat(&sbs, LOC(f->locale, "nr_schemes_prefix")); - rl2 = rl; - while (rl2) { + if (num == 1) { + /* single region is easy */ + region *rn = rl[0]; + f_regionid(rn, f, buf, sizeof(buf)); + } + else if (num > 1) { + int i; + char *rnames[MAX_SCHEMES]; + + for (i = 0; i != num; ++i) { char rbuf[REPORTWIDTH]; - f_regionid(rl2->data, f, rbuf, sizeof(rbuf)); - sbs_strcat(&sbs, rbuf); - rl2 = rl2->next; - if (rl2) { - sbs_strcat(&sbs, ", "); - } + region *rn = rl[i]; + f_regionid(rn, f, rbuf, sizeof(rbuf)); + rnames[i] = str_strdup(rbuf); } - sbs_strcat(&sbs,LOC(f->locale, "nr_schemes_postfix")); - free_regionlist(rl); - /* Schreibe Paragraphen */ + report_list(f->locale, buf, sizeof(buf), num, rnames); + for (i = 0; i != num; ++i) { + free(rnames[i]); + } + } + if (num > 0) { + format_replace(LOC(f->locale, "nr_schemes_template"), "{0}", buf, buf, sizeof(buf)); newline(out); paragraph(out, buf, 0, 0, 0); } diff --git a/src/teleport.c b/src/teleport.c index 84e4afe90..c59c92c40 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -22,7 +22,6 @@ #include #define TE_CENTER 1000 -#define TP_RADIUS 2 #define TP_DISTANCE 4 int real2tp(int rk) @@ -75,6 +74,33 @@ region_list *astralregions(const region * r, bool(*valid) (const region *)) return rlist; } + +int get_astralregions(const region * r, bool(*valid) (const region *), region *result[]) +{ + assert(is_astral(r)); + r = r_astral_to_standard(r); + if (r) { + int x, y, num = 0; + for (x = -TP_RADIUS; x <= +TP_RADIUS; ++x) { + for (y = -TP_RADIUS; y <= +TP_RADIUS; ++y) { + region *rn; + int dist = koor_distance(0, 0, x, y); + + if (dist <= TP_RADIUS) { + int nx = r->x + x, ny = r->y + y; + pnormalize(&nx, &ny, rplane(r)); + rn = findregion(nx, ny); + if (rn != NULL && (valid == NULL || valid(rn))) { + result[num++] = rn; + } + } + } + } + return num; + } + return 0; +} + region *r_standard_to_astral(const region * r) { assert(!is_astral(r)); diff --git a/src/teleport.h b/src/teleport.h index 416b6b406..cb225e978 100644 --- a/src/teleport.h +++ b/src/teleport.h @@ -7,6 +7,8 @@ extern "C" { #endif +#define TP_RADIUS 2 /* Radius von Schemen */ + struct region; struct region_list; struct plane; @@ -20,6 +22,7 @@ extern "C" { bool inhabitable(const struct region *r); bool is_astral(const struct region *r); struct plane *get_astralplane(void); + int get_astralregions(const struct region * r, bool(*valid) (const struct region *), struct region *result[]); void create_teleport_plane(void); void spawn_braineaters(float chance); From 08e45dc7229d2bdf8400aca142ef661511bb72ad Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 21 Sep 2019 22:18:41 +0200 Subject: [PATCH 10/11] appease gcc const-check --- src/report.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/report.c b/src/report.c index 904fd6f14..7f0ad8dc0 100644 --- a/src/report.c +++ b/src/report.c @@ -1080,7 +1080,7 @@ static void report_region_schemes(struct stream *out, const region * r, faction } else if (num > 1) { int i; - char *rnames[MAX_SCHEMES]; + const char *rnames[MAX_SCHEMES]; for (i = 0; i != num; ++i) { char rbuf[REPORTWIDTH]; @@ -1090,7 +1090,7 @@ static void report_region_schemes(struct stream *out, const region * r, faction } report_list(f->locale, buf, sizeof(buf), num, rnames); for (i = 0; i != num; ++i) { - free(rnames[i]); + free((char *)rnames[i]); } } if (num > 0) { From 0db9389df665c8266547d63ca60beebddf30c9ee Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 21 Sep 2019 22:28:13 +0200 Subject: [PATCH 11/11] coverity thinks I should check return values --- src/report.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/report.c b/src/report.c index 7f0ad8dc0..392ede0da 100644 --- a/src/report.c +++ b/src/report.c @@ -1094,9 +1094,10 @@ static void report_region_schemes(struct stream *out, const region * r, faction } } if (num > 0) { - format_replace(LOC(f->locale, "nr_schemes_template"), "{0}", buf, buf, sizeof(buf)); - newline(out); - paragraph(out, buf, 0, 0, 0); + if (format_replace(LOC(f->locale, "nr_schemes_template"), "{0}", buf, buf, sizeof(buf))) { + newline(out); + paragraph(out, buf, 0, 0, 0); + } } } }