Merge pull request #651 from ennorehling/develop

refactoring: race, locale, dict removal pt. 1
This commit is contained in:
Enno Rehling 2017-02-11 22:48:41 +01:00 committed by GitHub
commit 17fc2adcb5
43 changed files with 358 additions and 706 deletions

2
cmake

@ -1 +1 @@
Subproject commit d88983c7ff4bc3a4884a7c3f74e8190bac5eab23
Subproject commit f1fb3943ace59994d90d71a891b80033dc2700a2

View file

@ -1,19 +1,5 @@
-- Muschelplateau
-- global exports (use item)
function use_seashell(u, amount)
-- Muschelplateau...
local visit = u.faction.objects:get("embassy_muschel")
if visit and u.region~= home then
local turns = get_turn() - visit
local msg = message.create('msg_event')
msg:set_string("string", u.name .. "(" .. itoa36(u.id) .. ") erzählt den Bewohnern von " .. u.region.name .. " von Muschelplateau, das die Partei " .. u.faction.name .. " vor " .. turns .. " Wochen besucht hat." )
msg:send_region(u.region)
return 0
end
return -4
end
if not config.embassy then return nil end
local embassy = {}
@ -34,10 +20,10 @@ function embassy.update()
eressea.log.debug("updating embassies in " .. tostring(home))
local u
for u in home.units do
if u.faction.objects:get('embassy_muschel')==nil then
if not u.faction:get_key('mupL') then
if (u.faction:add_item('seashell', 1)>0) then
eressea.log.debug("new seashell for " .. tostring(u.faction))
u.faction.objects:set('embassy_muschel', get_turn())
u.faction:set_key('mupL', get_turn())
end
end
end

View file

@ -7,3 +7,4 @@ if config.rules then
assert(0 == read_xml(confdir .. rules .. 'config.xml', confdir .. rules .. 'catalog.xml'), "could not load XML data, did you compile with LIBXML2 ?")
assert(0 == eressea.config.read(rules .. 'config.json', confdir), "could not read JSON data")
end
eressea.game.reset()

View file

@ -330,17 +330,6 @@ function test_message()
return msg
end
function test_hashtable()
local f = faction.create("noreply1@eressea.de", "human", "de")
f.objects:set("enno", "smart guy")
f.objects:set("age", 10)
assert(f.objects:get("jesus") == nil)
assert(f.objects:get("enno") == "smart guy")
assert(f.objects:get("age") == 10)
f.objects:set("age", nil)
assert(f.objects:get("age") == nil)
end
function test_events()
local fail = 1
local function msg_handler(u, evt)

View file

@ -46,23 +46,17 @@ function test_snowglobe()
local r2 = region.create(1, 0, "ocean")
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()
u:add_order("BENUTZEN 1 Schneekugel Ost")
local xform = { ocean = "glacier", glacier = "glacier", firewall = "volcano", desert = "plain", volcano = "mountain", plain = "plain" }
for k, v in pairs(xform) do
r2.terrain = k
process_orders()
use_snowglobe(u, 1, "Ost", nil)
assert_equal(v, r2.terrain)
if k~=v then
have=have - 1
else
if k==v then
fail = fail + 1
assert_equal(fail, f:count_msg_type('target_region_invalid'))
end
assert_equal(have, u:get_item("snowglobe"))
end
end

View file

@ -148,7 +148,6 @@ set(SERVER_SRC
bind_locale.c
bind_eressea.c
bind_faction.c
bind_dict.c
bind_order.c
bindings.c
bind_message.c

View file

@ -58,10 +58,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <storage.h>
attrib_type at_scare = { // monster scares peasants
"scare", NULL, NULL, NULL, a_writeint, a_readint
};
attrib_type at_unitdissolve = {
"unitdissolve", NULL, NULL, NULL, a_writechars, a_readchars
};
@ -78,7 +74,6 @@ static int read_ext(attrib * a, void *owner, gamedata *data)
void register_attributes(void)
{
/* Alle speicherbaren Attribute müssen hier registriert werden */
at_register(&at_scare);
at_register(&at_shiptrail);
at_register(&at_familiar);
at_register(&at_familiarmage);

View file

@ -23,7 +23,6 @@ extern "C" {
#endif
struct attrib_type;
extern struct attrib_type at_scare;
extern void register_attributes(void);
#ifdef __cplusplus

View file

@ -19,6 +19,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <platform.h>
#include <kernel/config.h>
#include "dict.h"
#include "key.h"
/* kernel includes */
#include <kernel/building.h>
@ -29,6 +30,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* util includes */
#include <util/attrib.h>
#include <util/base36.h>
#include <util/log.h>
#include <util/gamedata.h>
#include <util/resolve.h>
@ -54,46 +57,6 @@ typedef struct dict_data {
} data;
} dict_data;
static void
dict_write(const attrib * a, const void *owner, struct storage *store)
{
const dict_data *data = (dict_data *)a->data.v;
int type = (int)data->type;
WRITE_TOK(store, data->name);
WRITE_INT(store, type);
switch (data->type) {
case TINTEGER:
WRITE_INT(store, data->data.i);
break;
case TREAL:
WRITE_FLT(store, (float)data->data.real);
break;
case TSTRING:
WRITE_STR(store, data->data.str);
break;
case TUNIT:
write_unit_reference(data->data.u, store);
break;
case TFACTION:
write_faction_reference(data->data.f, store);
break;
case TBUILDING:
write_building_reference(data->data.b, store);
break;
case TSHIP:
/* write_ship_reference(data->data.sh, store); */
assert(!"not implemented");
break;
case TREGION:
write_region_reference(data->data.r, store);
break;
case TNONE:
break;
default:
assert(!"illegal type in object-attribute");
}
}
static int dict_read(attrib * a, void *owner, gamedata *data)
{
storage *store = data->store;
@ -164,7 +127,7 @@ static int dict_read(attrib * a, void *owner, gamedata *data)
default:
return AT_READ_FAIL;
}
return AT_READ_OK;
return AT_READ_DEPR;
}
static void dict_init(attrib * a)
@ -184,100 +147,46 @@ static void dict_done(attrib * a)
free(a->data.v);
}
static void dict_upgrade(attrib **alist, attrib *abegin) {
int n = 0, *keys = 0;
int i = 0, val[4];
attrib *a, *ak = a_find(*alist, &at_keys);
if (ak) {
keys = (int *)ak->data.v;
if (keys) n = keys[0];
}
for (a = abegin; a && a->type == abegin->type; a = a->next) {
dict_data *dd = (dict_data *)a->data.v;
if (dd->type != TINTEGER) {
log_error("dict conversion, bad type %d for %s", dd->type, dd->name);
}
else {
if (strcmp(dd->name, "embassy_muschel")==0) {
val[i++] = atoi36("mupL");
}
else {
log_error("dict conversion, bad entry %s", dd->name);
}
}
if (i == 4) {
keys = realloc(keys, sizeof(int) * (n + i + 1));
memcpy(keys + n + 1, val, sizeof(int)*i);
n += i;
i = 0;
}
}
if (i > 0) {
keys = realloc(keys, sizeof(int) * (n + i + 1));
memcpy(keys + n + 1, val, sizeof(int)*i);
if (!ak) {
ak = a_add(alist, a_new(&at_keys));
}
}
ak->data.v = keys;
keys[0] = n + i;
}
attrib_type at_dict = {
"object", dict_init, dict_done, NULL,
dict_write, dict_read
NULL, dict_read, dict_upgrade
};
const char *dict_name(const attrib * a)
{
dict_data *data = (dict_data *)a->data.v;
return data->name;
}
struct attrib *dict_create(const char *name, dict_type type, variant value)
{
attrib *a = a_new(&at_dict);
dict_data *data = (dict_data *)a->data.v;
data->name = strdup(name);
dict_set(a, type, value);
return a;
}
void dict_set(attrib * a, dict_type type, variant value)
{
dict_data *data = (dict_data *)a->data.v;
if (data->type == TSTRING)
free(data->data.str);
data->type = type;
switch (type) {
case TSTRING:
data->data.str = value.v ? strdup(value.v) : NULL;
break;
case TINTEGER:
data->data.i = value.i;
break;
case TREAL:
data->data.real = value.f;
break;
case TREGION:
data->data.r = (region *)value.v;
break;
case TBUILDING:
data->data.b = (building *)value.v;
break;
case TFACTION:
data->data.f = (faction *)value.v;
break;
case TUNIT:
data->data.u = (unit *)value.v;
break;
case TSHIP:
data->data.sh = (ship *)value.v;
break;
case TNONE:
break;
default:
assert(!"invalid object-type");
break;
}
}
void dict_get(const struct attrib *a, dict_type * type, variant * value)
{
dict_data *data = (dict_data *)a->data.v;
*type = data->type;
switch (data->type) {
case TSTRING:
value->v = data->data.str;
break;
case TINTEGER:
value->i = data->data.i;
break;
case TREAL:
value->f = (float)data->data.real;
break;
case TREGION:
value->v = data->data.r;
break;
case TBUILDING:
value->v = data->data.b;
break;
case TFACTION:
value->v = data->data.f;
break;
case TUNIT:
value->v = data->data.u;
break;
case TSHIP:
value->v = data->data.sh;
break;
case TNONE:
break;
default:
assert(!"invalid object-type");
break;
}
}

View file

@ -26,13 +26,6 @@ extern "C" {
extern struct attrib_type at_dict;
struct attrib *dict_create(const char *name, dict_type type,
variant value);
void dict_get(const struct attrib *a, dict_type * type,
variant * value);
void dict_set(struct attrib *a, dict_type type, variant value);
const char *dict_name(const struct attrib *a);
#ifdef __cplusplus
}
#endif

View file

@ -66,7 +66,7 @@ attrib_type at_keys = {
NULL
};
void a_upgradekeys(attrib **alist, attrib *abegin) {
static void a_upgradekeys(attrib **alist, attrib *abegin) {
int n = 0, *keys = 0;
int i = 0, val[4];
attrib *a, *ak = a_find(*alist, &at_keys);

View file

@ -760,10 +760,6 @@ bool missile)
if (is_riding(t) && (wtype == NULL || (fval(wtype, WTF_HORSEBONUS)
&& !fval(wtype, WTF_MISSILE)))) {
skill += CavalryBonus(tu, enemy, BONUS_SKILL);
if (wtype)
skill =
skillmod(u_race(tu)->attribs, tu, tu->region, wtype->skill, skill,
SMF_RIDING);
}
if (t.index < tf->elvenhorses) {

View file

@ -225,10 +225,10 @@ static void test_natural_armor(CuTest * tc)
set_level(u, SK_STAMINA, 2);
CuAssertIntEquals(tc, 0, rc_armor_bonus(rc));
CuAssertIntEquals(tc, 0, natural_armor(u));
set_param(&rc->parameters, "armor.stamina", "1");
rc_set_param(rc, "armor.stamina", "1");
CuAssertIntEquals(tc, 1, rc_armor_bonus(rc));
CuAssertIntEquals(tc, 2, natural_armor(u));
set_param(&rc->parameters, "armor.stamina", "2");
rc_set_param(rc, "armor.stamina", "2");
CuAssertIntEquals(tc, 2, rc_armor_bonus(rc));
CuAssertIntEquals(tc, 1, natural_armor(u));
test_cleanup();

View file

@ -13,7 +13,6 @@ without prior permission by the authors of Eressea.
#include <platform.h>
#include "bind_building.h"
#include "bind_unit.h"
#include "bind_dict.h"
#include <kernel/config.h>
#include <kernel/unit.h>
@ -41,13 +40,6 @@ int tolua_buildinglist_next(lua_State * L)
return 0; /* no more values to return */
}
static int tolua_building_get_objects(lua_State * L)
{
building *self = (building *)tolua_tousertype(L, 1, 0);
tolua_pushusertype(L, (void *)&self->attribs, USERTYPE_DICT);
return 1;
}
static int tolua_building_set_working(lua_State * L)
{
building *self = (building *)tolua_tousertype(L, 1, 0);
@ -258,7 +250,6 @@ void tolua_building_open(lua_State * L)
tolua_variable(L, TOLUA_CAST "size", tolua_building_get_size,
tolua_building_set_size);
tolua_function(L, TOLUA_CAST "get_typename", tolua_building_get_typename);
tolua_variable(L, TOLUA_CAST "objects", tolua_building_get_objects, 0);
tolua_variable(L, TOLUA_CAST "working", tolua_building_get_working, tolua_building_set_working);
}

View file

@ -20,9 +20,7 @@
#include "kernel/terrain.h"
void config_reset(void) {
default_locale = 0;
free_config();
free_locales();
free_nrmesssages();
free_spells();
free_buildingtypes();
@ -37,7 +35,6 @@ int config_parse(const char *json)
if (conf) {
json_config(conf);
cJSON_Delete(conf);
init_locales();
return 0;
}
else {

View file

@ -1,185 +0,0 @@
/*
+-------------------+
| | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
| (c) 1998 - 2008 | Katja Zedel <katze@felidae.kn-bremen.de>
| | Henning Peters <faroul@beyond.kn-bremen.de>
+-------------------+
This program may not be used, modified or distributed
without prior permission by the authors of Eressea.
*/
#include <platform.h>
#include "bind_dict.h"
#include <kernel/building.h>
#include <kernel/unit.h>
#include <kernel/ship.h>
#include <kernel/region.h>
#include <attributes/dict.h>
#include <util/variant.h>
#include <util/attrib.h>
#include <tolua.h>
#include <lua.h>
#include <string.h>
#include <assert.h>
static int tolua_dict_get(lua_State * L)
{
dict self = (dict)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
attrib *a = a_find(*self, &at_dict);
for (; a && a->type == &at_dict; a = a->next) {
const char *obj_name = dict_name(a);
if (obj_name && name && strcmp(obj_name, name) == 0) {
variant val;
dict_type type;
dict_get(a, &type, &val);
switch (type) {
case TNONE:
lua_pushnil(L);
break;
case TINTEGER:
lua_pushinteger(L, val.i);
break;
case TREAL:
lua_pushnumber(L, (lua_Number)val.f);
break;
case TREGION:
tolua_pushusertype(L, val.v, TOLUA_CAST "region");
break;
case TBUILDING:
tolua_pushusertype(L, val.v, TOLUA_CAST "building");
break;
case TUNIT:
tolua_pushusertype(L, val.v, TOLUA_CAST "unit");
break;
case TSHIP:
tolua_pushusertype(L, val.v, TOLUA_CAST "ship");
break;
case TSTRING:
tolua_pushstring(L, (const char *)val.v);
break;
default:
assert(!"not implemented");
}
return 1;
}
}
lua_pushnil(L);
return 1;
}
static int tolua_dict_set_number(lua_State * L)
{
dict self = (dict)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
lua_Number value = tolua_tonumber(L, 3, 0);
attrib *a = a_find(*self, &at_dict);
variant val;
val.f = (float)value;
for (; a && a->type == &at_dict; a = a->next) {
if (strcmp(dict_name(a), name) == 0) {
dict_set(a, TREAL, val);
return 0;
}
}
a = a_add(self, dict_create(name, TREAL, val));
return 0;
}
static int tolua_dict_set_string(lua_State * L)
{
dict self = (dict)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
const char *value = tolua_tostring(L, 3, 0);
attrib *a = a_find(*self, &at_dict);
variant val;
val.v = strdup(value);
for (; a && a->type == &at_dict; a = a->next) {
if (strcmp(dict_name(a), name) == 0) {
dict_set(a, TSTRING, val);
return 0;
}
}
a = a_add(self, dict_create(name, TSTRING, val));
return 0;
}
static int tolua_dict_set_usertype(lua_State * L, int type)
{
dict self = (dict)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
unit *value = tolua_tousertype(L, 3, 0);
attrib *a = a_find(*self, &at_dict);
variant val;
val.v = value;
for (; a && a->type == &at_dict; a = a->next) {
if (strcmp(dict_name(a), name) == 0) {
dict_set(a, type, val);
return 0;
}
}
a = a_add(self, dict_create(name, type, val));
return 0;
}
static int tolua_dict_set(lua_State * L)
{
tolua_Error tolua_err;
if (tolua_isnumber(L, 3, 0, &tolua_err)) {
return tolua_dict_set_number(L);
}
else if (tolua_isusertype(L, 3, TOLUA_CAST "unit", 0, &tolua_err)) {
return tolua_dict_set_usertype(L, TUNIT);
}
else if (tolua_isusertype(L, 3, TOLUA_CAST "faction", 0, &tolua_err)) {
return tolua_dict_set_usertype(L, TFACTION);
}
else if (tolua_isusertype(L, 3, TOLUA_CAST "ship", 0, &tolua_err)) {
return tolua_dict_set_usertype(L, TSHIP);
}
else if (tolua_isusertype(L, 3, TOLUA_CAST "building", 0, &tolua_err)) {
return tolua_dict_set_usertype(L, TBUILDING);
}
else if (tolua_isusertype(L, 3, TOLUA_CAST "region", 0, &tolua_err)) {
return tolua_dict_set_usertype(L, TREGION);
}
return tolua_dict_set_string(L);
}
void tolua_dict_open(lua_State * L)
{
/* register user types */
tolua_usertype(L, USERTYPE_DICT);
tolua_module(L, NULL, 0);
tolua_beginmodule(L, NULL);
{
tolua_cclass(L, USERTYPE_DICT, USERTYPE_DICT,
TOLUA_CAST "", NULL);
tolua_beginmodule(L, USERTYPE_DICT);
{
tolua_function(L, TOLUA_CAST "get", tolua_dict_get);
tolua_function(L, TOLUA_CAST "set", tolua_dict_set);
}
tolua_endmodule(L);
}
tolua_endmodule(L);
}

View file

@ -1,26 +0,0 @@
/*
+-------------------+
| | Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
| (c) 1998 - 2008 | Katja Zedel <katze@felidae.kn-bremen.de>
| | Henning Peters <faroul@beyond.kn-bremen.de>
+-------------------+
This program may not be used, modified or distributed
without prior permission by the authors of Eressea.
*/
#ifdef __cplusplus
extern "C" {
#endif
#define USERTYPE_DICT ((char *)"dict")
struct lua_State;
void tolua_dict_open(struct lua_State *L);
typedef struct attrib **dict;
#ifdef __cplusplus
}
#endif

View file

@ -9,6 +9,8 @@
#include <kernel/config.h>
#include <kernel/save.h>
#include <util/language.h>
#include <stream.h>
#include <filestream.h>
@ -16,6 +18,7 @@
void eressea_free_game(void) {
free_gamedata();
init_resources();
init_locales();
}
int eressea_read_game(const char * filename) {

View file

@ -13,7 +13,6 @@ without prior permission by the authors of Eressea.
#include <platform.h>
#include "bind_faction.h"
#include "bind_unit.h"
#include "bind_dict.h"
#include "bindings.h"
#include "helpers.h"
@ -27,7 +26,9 @@ without prior permission by the authors of Eressea.
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/spellbook.h>
#include <attributes/key.h>
#include <util/base36.h>
#include <util/language.h>
#include <util/log.h>
#include <util/password.h>
@ -241,6 +242,32 @@ static int tolua_faction_addnotice(lua_State * L)
return 0;
}
static int tolua_faction_getkey(lua_State * L)
{
faction *self = (faction *)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));
return 1;
}
static int tolua_faction_setkey(lua_State * L)
{
faction *self = (faction *)tolua_tousertype(L, 1, 0);
const char *name = tolua_tostring(L, 2, 0);
int value = tolua_toboolean(L, 3, 0);
int flag = atoi36(name);
if (value) {
key_set(&self->attribs, flag);
}
else {
key_unset(&self->attribs, flag);
}
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);
@ -258,13 +285,6 @@ static int tolua_faction_count_msg_type(lua_State *L) {
return 1;
}
static int tolua_faction_get_objects(lua_State * L)
{
faction *self = (faction *)tolua_tousertype(L, 1, 0);
tolua_pushusertype(L, (void *)&self->attribs, USERTYPE_DICT);
return 1;
}
static int tolua_faction_get_policy(lua_State * L)
{
faction *self = (faction *)tolua_tousertype(L, 1, 0);
@ -618,8 +638,8 @@ void tolua_faction_open(lua_State * L)
/* 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);
tolua_function(L, TOLUA_CAST "get_key", tolua_faction_getkey);
tolua_function(L, TOLUA_CAST "set_key", tolua_faction_setkey);
}
tolua_endmodule(L);
}

View file

@ -14,7 +14,6 @@ without prior permission by the authors of Eressea.
#include "bind_region.h"
#include "bind_unit.h"
#include "bind_ship.h"
#include "bind_dict.h"
#include "bind_building.h"
#include "chaos.h"
@ -36,10 +35,11 @@ without prior permission by the authors of Eressea.
#include <util/attrib.h>
#include <util/base36.h>
#include <critbit.h>
#include <util/language.h>
#include <util/log.h>
#include <critbit.h>
#include <tolua.h>
#include <assert.h>
@ -434,13 +434,6 @@ static int tolua_region_set_resource(lua_State * L)
return 0;
}
static int tolua_region_get_objects(lua_State * L)
{
region *self = (region *)tolua_tousertype(L, 1, 0);
tolua_pushusertype(L, (void *)&self->attribs, USERTYPE_DICT);
return 1;
}
static int tolua_region_destroy(lua_State * L)
{
region *self = (region *)tolua_tousertype(L, 1, 0);
@ -733,8 +726,6 @@ void tolua_region_open(lua_State * L)
tolua_function(L, TOLUA_CAST "get_key", tolua_region_getkey);
tolua_function(L, TOLUA_CAST "set_key", tolua_region_setkey);
tolua_variable(L, TOLUA_CAST "objects", tolua_region_get_objects, 0);
}
tolua_endmodule(L);

View file

@ -13,7 +13,6 @@ without prior permission by the authors of Eressea.
#include <platform.h>
#include "bind_ship.h"
#include "bind_unit.h"
#include "bind_dict.h"
#include "move.h"
@ -115,13 +114,6 @@ static int tolua_ship_get_units(lua_State * L)
return 1;
}
static int tolua_ship_get_objects(lua_State * L)
{
ship *self = (ship *)tolua_tousertype(L, 1, 0);
tolua_pushusertype(L, (void *)&self->attribs, USERTYPE_DICT);
return 1;
}
static int tolua_ship_create(lua_State * L)
{
region *r = (region *)tolua_tousertype(L, 1, 0);
@ -233,8 +225,6 @@ void tolua_ship_open(lua_State * L)
tolua_variable(L, TOLUA_CAST "type", tolua_ship_get_type, 0);
tolua_variable(L, TOLUA_CAST "damage", tolua_ship_get_damage,
tolua_ship_set_damage);
tolua_variable(L, TOLUA_CAST "objects", tolua_ship_get_objects, 0);
tolua_function(L, TOLUA_CAST "create", tolua_ship_create);
}
tolua_endmodule(L);

View file

@ -13,7 +13,6 @@ without prior permission by the authors of Eressea.
#include <platform.h>
#include "bind_unit.h"
#include "bind_dict.h"
#include "alchemy.h"
#include "bindings.h"
#include "move.h"
@ -67,12 +66,6 @@ static int tolua_bufunit(lua_State * L) {
return 1;
}
static int tolua_unit_get_objects(lua_State * L)
{
unit *self = (unit *)tolua_tousertype(L, 1, 0);
tolua_pushusertype(L, (void *)&self->attribs, USERTYPE_DICT);
return 1;
}
int tolua_unitlist_nextf(lua_State * L)
{
@ -1013,7 +1006,6 @@ void tolua_unit_open(lua_State * L)
tolua_unit_set_race);
tolua_variable(L, TOLUA_CAST "hp_max", &tolua_unit_get_hpmax, 0);
tolua_variable(L, TOLUA_CAST "objects", &tolua_unit_get_objects, 0);
tolua_function(L, TOLUA_CAST "show", &tolua_bufunit);
}
tolua_endmodule(L);

View file

@ -15,7 +15,6 @@ without prior permission by the authors of Eressea.
#include "bind_unit.h"
#include "bind_storage.h"
#include "bind_building.h"
#include "bind_dict.h"
#include "bind_message.h"
#include "bind_building.h"
#include "bind_faction.h"
@ -517,7 +516,7 @@ static void reset_game(void)
for (f = factions; f; f = f->next) {
f->flags &= FFL_SAVEMASK;
}
init_locales();
// init_locales();
}
static int tolua_process_orders(lua_State * L)
@ -1143,7 +1142,6 @@ lua_State *lua_init(const dictionary *inifile) {
tolua_unit_open(L);
tolua_message_open(L);
tolua_order_open(L);
tolua_dict_open(L);
#ifdef USE_CURSES
tolua_gmtool_open(L);
#endif

View file

@ -422,10 +422,7 @@ static void expandrecruit(region * r, request * recruitorders)
static int recruit_cost(const faction * f, const race * rc)
{
if (is_monsters(f) || f->race == rc) {
return rc->recruitcost;
}
else if (valid_race(f, rc)) {
if (is_monsters(f) || valid_race(f, rc)) {
return rc->recruitcost;
}
return -1;

View file

@ -563,10 +563,7 @@ bool valid_race(const struct faction *f, const struct race *rc)
if (f->race == rc)
return true;
else {
const char *str = get_param(f->race->parameters, "other_race");
if (str)
return rc_find(str) == rc;
return false;
return rc_otherrace(f->race) == rc;
}
}

View file

@ -209,6 +209,22 @@ static void test_max_migrants(CuTest *tc) {
test_cleanup();
}
static void test_valid_race(CuTest *tc) {
race * rc1, *rc2;
faction *f;
test_setup();
rc1 = test_create_race("human");
rc2 = test_create_race("elf");
f = test_create_faction(rc1);
CuAssertTrue(tc, valid_race(f, rc1));
CuAssertTrue(tc, !valid_race(f, rc2));
rc_set_param(rc1, "other_race", "elf");
CuAssertTrue(tc, valid_race(f, rc1));
CuAssertTrue(tc, valid_race(f, rc2));
test_cleanup();
}
CuSuite *get_faction_suite(void)
{
CuSuite *suite = CuSuiteNew();
@ -222,5 +238,6 @@ CuSuite *get_faction_suite(void)
SUITE_ADD_TEST(suite, test_set_origin);
SUITE_ADD_TEST(suite, test_set_origin_bug);
SUITE_ADD_TEST(suite, test_check_passwd);
SUITE_ADD_TEST(suite, test_valid_race);
return suite;
}

View file

@ -44,6 +44,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/language.h>
#include <util/log.h>
#include <util/rng.h>
#include <util/variant.h>
#include <storage.h>
@ -77,6 +78,79 @@ static const char *racenames[MAXRACES] = {
"clone"
};
#define MAXOPTIONS 4
typedef struct rcoption {
unsigned char key[MAXOPTIONS];
variant value[MAXOPTIONS];
} rcoption;
enum {
RCO_NONE,
RCO_SCARE, // races that scare and eat peasants
RCO_OTHER, // may recruit from another race
RCO_STAMINA, // every n levels of stamina add +1 RC
RCO_HUNGER, // custom hunger.damage override (char *)
RCO_TRADELUX,
RCO_TRADEHERB,
};
static void rc_setoption(race *rc, int k, const char *value) {
unsigned char key = (unsigned char)k;
int i;
variant *v = NULL;
if (!rc->options) {
rc->options = malloc(sizeof(rcoption));
rc->options->key[0] = key;
rc->options->key[1] = RCO_NONE;
v = rc->options->value;
} else {
for (i=0;!v && i < MAXOPTIONS && rc->options->key[i]!=RCO_NONE;++i) {
if (rc->options->key[i]==key) {
v = rc->options->value+i;
}
}
if (!v) {
assert(i<MAXOPTIONS || !"MAXOPTIONS too small for race");
v = rc->options->value+i;
rc->options->key[i] = key;
if (i+1<MAXOPTIONS) {
rc->options->key[i+1]=RCO_NONE;
}
}
}
assert(v);
if (key == RCO_SCARE) {
v->i = atoi(value);
}
else if (key == RCO_STAMINA) {
v->i = atoi(value);
}
else if (key == RCO_OTHER) {
v->v = rc_get_or_create(value);
}
else if (key == RCO_HUNGER) {
v->v = strdup(value);
}
else if (key == RCO_TRADEHERB) {
v->i = atoi(value);
}
else if (key == RCO_TRADELUX) {
v->i = atoi(value);
}
}
static variant *rc_getoption(const race *rc, int key) {
if (rc->options) {
int i;
for (i=0;i!=MAXOPTIONS && rc->options->key[i]!=RCO_NONE;++i) {
if (rc->options->key[i]==key) {
return rc->options->value+i;
}
}
}
return NULL;
}
const struct race *findrace(const char *s, const struct locale *lang)
{
void **tokens = get_translations(lang, UT_RACES);
@ -184,12 +258,26 @@ void free_races(void) {
while (races) {
int i;
race * rc = races->next;
rcoption * opt = races->options;
if (opt) {
for (i=0;i!=MAXOPTIONS && opt->key[i]!=RCO_NONE;++i) {
if (opt->key[i]==RCO_HUNGER) {
free(opt->value[i].v);
}
}
free(opt);
}
for (i = 0; races->attack[i].type!=AT_NONE; ++i) {
spellref_free(races->attack[i].data.sp);
att *at = races->attack + i;
if (at->type == AT_SPELL) {
spellref_free(at->data.sp);
}
else {
free(at->data.dice);
}
}
spellref_free(races->precombatspell);
free_params(&races->parameters);
free(xrefs);
xrefs = 0;
free(races->_name);
@ -290,8 +378,46 @@ double rc_maxaura(const race *rc) {
return rc->maxaura / 100.0;
}
int rc_armor_bonus(const race *rc) {
return get_param_int(rc->parameters, "armor.stamina", 0);
const char * rc_hungerdamage(const race *rc)
{
variant *v = rc_getoption(rc, RCO_HUNGER);
return v ? (const char *)v->v : NULL;
}
int rc_armor_bonus(const race *rc)
{
variant *v = rc_getoption(rc, RCO_STAMINA);
return v ? v->i : 0;
}
int rc_scare(const struct race *rc)
{
variant *v = rc_getoption(rc, RCO_SCARE);
return v ? v->i : 0;
}
int rc_luxury_trade(const struct race *rc)
{
if (rc) {
variant *v = rc_getoption(rc, RCO_TRADELUX);
if (v) return v->i;
}
return 1000;
}
int rc_herb_trade(const struct race *rc)
{
if (rc) {
variant *v = rc_getoption(rc, RCO_TRADEHERB);
if (v) return v->i;
}
return 500;
}
const race *rc_otherrace(const race *rc)
{
variant *v = rc_getoption(rc, RCO_OTHER);
return v ? (const race *)v->v : NULL;
}
int rc_migrants_formula(const race *rc)
@ -299,6 +425,38 @@ int rc_migrants_formula(const race *rc)
return (rc->flags&RCF_MIGRANTS) ? MIGRANTS_LOG10 : MIGRANTS_NONE;
}
void rc_set_param(struct race *rc, const char *key, const char *value) {
if (strcmp(key, "recruit_multi") == 0) {
rc->recruit_multi = atof(value);
}
else if (strcmp(key, "migrants.formula") == 0) {
if (value[0] == '1') {
rc->flags |= RCF_MIGRANTS;
}
}
else if (strcmp(key, "other_race")==0) {
rc_setoption(rc, RCO_OTHER, value);
}
else if (strcmp(key, "ai.scare")==0) {
rc_setoption(rc, RCO_SCARE, value);
}
else if (strcmp(key, "hunger.damage")==0) {
rc_setoption(rc, RCO_HUNGER, value);
}
else if (strcmp(key, "armor.stamina")==0) {
rc_setoption(rc, RCO_STAMINA, value);
}
else if (strcmp(key, "luxury_trade")==0) {
rc_setoption(rc, RCO_TRADELUX, value);
}
else if (strcmp(key, "herb_trade")==0) {
rc_setoption(rc, RCO_TRADEHERB, value);
}
else {
log_error("unknown property for race %s: %s=%s", rc->_name, key, value);
}
}
const char* rc_name(const race * rc, name_t n, char *name, size_t size) {
const char * postfix = 0;
if (!rc) {

View file

@ -47,6 +47,7 @@ extern "C" {
struct spell;
struct spellref;
struct locale;
struct rcoption;
extern int num_races;
@ -104,7 +105,7 @@ extern "C" {
typedef struct att {
int type;
union {
const char *dice;
char *dice;
struct spellref *sp;
} data;
int flags;
@ -137,7 +138,6 @@ extern "C" {
int df_default; /* Verteidigungsskill Unbewaffnet (default: -2) */
int at_bonus; /* Ver<65>ndert den Angriffsskill (default: 0) */
int df_bonus; /* Ver<65>ndert den Verteidigungskill (default: 0) */
struct param *parameters; // additional properties, for an example see natural_armor
struct spellref *precombatspell;
signed char *study_speed; /* study-speed-bonus in points/turn (0=30 Tage) */
int flags;
@ -153,8 +153,9 @@ extern "C" {
struct item *(*itemdrop) (const struct race *, int size);
void(*init_familiar) (struct unit *);
struct rcoption *options; // rarely used properties
const struct race *familiars[MAXMAGIETYP];
struct attrib *attribs;
struct race *next;
} race;
@ -184,9 +185,16 @@ extern "C" {
const char * rc_name_s(const race *rc, name_t n);
const char * rc_name(const race *rc, name_t n, char *name, size_t size);
void rc_set_param(struct race *rc, const char *key, const char *value);
int rc_luxury_trade(const struct race *rc);
int rc_herb_trade(const struct race *rc);
double rc_magres(const struct race *rc);
double rc_maxaura(const struct race *rc);
int rc_armor_bonus(const struct race *rc);
int rc_scare(const struct race *rc);
const char * rc_hungerdamage(const race *rc);
const race *rc_otherrace(const race *rc);
#define MIGRANTS_NONE 0
#define MIGRANTS_LOG10 1

View file

@ -84,6 +84,23 @@ static void test_old_race(CuTest *tc)
test_cleanup();
}
static void test_rc_set_param(CuTest *tc) {
race *rc;
test_setup();
rc = test_create_race("human");
CuAssertPtrEquals(tc, NULL, rc->options);
rc_set_param(rc, "recruit_multi", "0.5");
CuAssertDblEquals(tc, 0.5, rc->recruit_multi, 0.0);
rc_set_param(rc, "migrants.formula", "1");
CuAssertIntEquals(tc, RCF_MIGRANTS, rc->flags&RCF_MIGRANTS);
CuAssertIntEquals(tc, MIGRANTS_LOG10, rc_migrants_formula(rc));
rc_set_param(rc, "ai.scare", "400");
CuAssertIntEquals(tc, 400, rc_scare(rc));
rc_set_param(rc, "hunger.damage", "1d10+12");
CuAssertStrEquals(tc, "1d10+12", rc_hungerdamage(rc));
test_cleanup();
}
CuSuite *get_race_suite(void)
{
CuSuite *suite = CuSuiteNew();
@ -92,6 +109,7 @@ CuSuite *get_race_suite(void)
SUITE_ADD_TEST(suite, test_rc_name);
SUITE_ADD_TEST(suite, test_rc_defaults);
SUITE_ADD_TEST(suite, test_rc_find);
SUITE_ADD_TEST(suite, test_rc_set_param);
return suite;
}

View file

@ -1470,7 +1470,6 @@ int readgame(const char *filename)
FILE *F;
size_t sz;
init_locales();
log_debug("- reading game data from %s", filename);
join_path(datapath(), filename, path, sizeof(path));

View file

@ -358,16 +358,12 @@ static int parse_calendar(xmlDocPtr doc)
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
xmlXPathObjectPtr xpathCalendars;
xmlNodeSetPtr nsetCalendars;
int c, rv = 0;
/* reading eressea/buildings/building */
xpathCalendars = xmlXPathEvalExpression(BAD_CAST "/eressea/calendar", xpath);
nsetCalendars = xpathCalendars->nodesetval;
months_per_year = 0;
if (nsetCalendars == NULL || nsetCalendars->nodeNr == 0) {
rv = -1;
}
else
if (nsetCalendars != NULL && nsetCalendars->nodeNr != 0) {
int c;
for (c = 0; c != nsetCalendars->nodeNr; ++c) {
xmlNodePtr calendar = nsetCalendars->nodeTab[c];
xmlXPathObjectPtr xpathWeeks, xpathMonths, xpathSeasons;
@ -377,7 +373,7 @@ static int parse_calendar(xmlDocPtr doc)
xmlChar *start;
start = xmlGetProp(calendar, BAD_CAST "start");
if (start && config_get("game.start")==NULL) {
if (start && config_get("game.start") == NULL) {
config_set("game.start", (const char *)start);
xmlFree(start);
}
@ -477,10 +473,11 @@ static int parse_calendar(xmlDocPtr doc)
xmlFree(newyear);
newyear = NULL;
}
}
xmlXPathFreeObject(xpathCalendars);
xmlXPathFreeContext(xpath);
return rv;
return 0;
}
static int parse_ships(xmlDocPtr doc)
@ -1575,13 +1572,12 @@ static int parse_spells(xmlDocPtr doc)
static void parse_ai(race * rc, xmlNodePtr node)
{
int n;
n = xml_ivalue(node, "scare", 0);
if (n>0) {
attrib *a = a_new(&at_scare);
a->data.i = n;
a_add(&rc->attribs, a);
xmlChar *propValue;
propValue = xmlGetProp(node, BAD_CAST "scare");
if (propValue) {
rc_set_param(rc, "ai.scare", (const char *)propValue);
xmlFree(propValue);
}
rc->splitsize = xml_ivalue(node, "splitsize", 0);
rc->aggression = (float)xml_fvalue(node, "aggression", 0.04);
@ -1734,22 +1730,11 @@ static int parse_races(xmlDocPtr doc)
else if (strcmp((const char *)child->name, "param") == 0) {
xmlChar *propName = xmlGetProp(child, BAD_CAST "name");
xmlChar *propValue = xmlGetProp(child, BAD_CAST "value");
if (strcmp((const char *)propName, "recruit_multi")==0) {
rc->recruit_multi = atof((const char *)propValue);
}
else if (strcmp((const char *)propName, "migrants.formula") == 0) {
if (propValue[0] == '1') {
rc->flags |= RCF_MIGRANTS;
}
}
else {
set_param(&rc->parameters, (const char *)propName, (const char *)propValue);
}
rc_set_param(rc, (const char *)propName, (const char *)propValue);
xmlFree(propName);
xmlFree(propValue);
}
}
rc->recruit_multi = get_param_flt(rc->parameters, "recruit_multi", 1.0);
/* reading eressea/races/race/skill */
xpath->node = node;

View file

@ -2,6 +2,7 @@
#include "magic.h"
#include "teleport.h"
#include "give.h"
#include <kernel/config.h>
#include <kernel/race.h>
@ -448,6 +449,24 @@ static void test_max_spellpoints(CuTest *tc) {
test_cleanup();
}
static void test_familiar_mage(CuTest *tc) {
unit *um, *uf, *ut;
test_setup();
um = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
uf = test_create_unit(um->faction, um->region);
ut = test_create_unit(um->faction, um->region);
set_number(ut, 0);
CuAssertTrue(tc, create_newfamiliar(um, uf));
CuAssertTrue(tc, is_familiar(uf));
CuAssertTrue(tc, !is_familiar(um));
CuAssertPtrEquals(tc, um, get_familiar_mage(uf));
CuAssertPtrEquals(tc, uf, get_familiar(um));
CuAssertPtrEquals(tc, NULL, give_men(1, um, ut, NULL));
CuAssertPtrEquals(tc, ut, get_familiar_mage(uf));
test_cleanup();
}
CuSuite *get_magic_suite(void)
{
CuSuite *suite = CuSuiteNew();
@ -465,5 +484,6 @@ CuSuite *get_magic_suite(void)
SUITE_ADD_TEST(suite, test_hasspell);
SUITE_ADD_TEST(suite, test_magic_resistance);
SUITE_ADD_TEST(suite, test_max_spellpoints);
DISABLE_TEST(suite, test_familiar_mage);
return suite;
}

View file

@ -66,22 +66,6 @@ attrib_type at_market = {
NULL, NULL, NULL, ATF_UNIQUE
};
int rc_luxury_trade(const struct race *rc)
{
if (rc) {
return get_param_int(rc->parameters, "luxury_trade", 1000);
}
return 1000;
}
int rc_herb_trade(const struct race *rc)
{
if (rc) {
return get_param_int(rc->parameters, "herb_trade", 500);
}
return 500;
}
#define MAX_MARKETS 128
#define MIN_PEASANTS 50 /* if there are at least this many peasants, you will get 1 good */

View file

@ -86,8 +86,8 @@ static void test_rc_trade(CuTest *tc) {
rc = test_create_race("human");
CuAssertIntEquals(tc, 1000, rc_luxury_trade(rc));
CuAssertIntEquals(tc, 500, rc_herb_trade(rc));
set_param(&rc->parameters, "luxury_trade", "100");
set_param(&rc->parameters, "herb_trade", "50");
rc_set_param(rc, "luxury_trade", "100");
rc_set_param(rc, "herb_trade", "50");
CuAssertIntEquals(tc, 100, rc_luxury_trade(rc));
CuAssertIntEquals(tc, 50, rc_herb_trade(rc));
test_cleanup();

View file

@ -31,7 +31,6 @@
#include "study.h"
/* attributes includes */
#include <attributes/attributes.h>
#include <attributes/targetregion.h>
#include <attributes/hate.h>
@ -1013,11 +1012,11 @@ static void eaten_by_monster(unit * u)
int horse = -1;
const resource_type *rhorse = get_resourcetype(R_HORSE);
const race *rc = u_race(u);
attrib *a;
int scare;
a = a_find(rc->attribs, &at_scare);
if (a) {
n = rng_int() & a->data.i * u->number;
scare = rc_scare(rc);
if (scare>0) {
n = rng_int() % scare * u->number;
} else {
n = rng_int() % (u->number / 20 + 1);
horse = 0;
@ -1093,10 +1092,11 @@ static void scared_by_monster(unit * u)
{
int n;
const race *rc = u_race(u);
attrib *a;
a = a_find(rc->attribs, &at_scare);
if (a) {
n = rng_int() & a->data.i * u->number;
int scare;
scare = rc_scare(rc);
if (scare>0) {
n = rng_int() % scare * u->number;
} else {
n = rng_int() % (u->number / 4 + 1);
}

View file

@ -31,10 +31,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <assert.h>
static double rc_popularity(const struct race *rc)
static double popularity(void)
{
int pop = get_param_int(rc->parameters, "morale", MORALE_AVERAGE);
return 1.0 / (pop - MORALE_COOLDOWN); /* 10 turns average */
return 1.0 / (MORALE_AVERAGE - MORALE_COOLDOWN); /* 10 turns average */
}
void morale_update(region *r) {
@ -52,7 +51,7 @@ void morale_update(region *r) {
if (morale < maxmorale) {
if (stability > MORALE_COOLDOWN && r->land->ownership->owner
&& morale < MORALE_MAX) {
double ch = rc_popularity(r->land->ownership->owner->race);
double ch = popularity();
if (is_cursed(r->attribs, C_GENEROUS, 0)) {
ch *= 1.2; /* 20% improvement */
}

View file

@ -95,7 +95,6 @@
#include <triggers/createunit.h>
#include <triggers/killunit.h>
#include <triggers/timeout.h>
#include <triggers/unitmessage.h>
/* attributes includes */
#include <attributes/targetregion.h>

View file

@ -11,7 +11,6 @@ killunit.c
shock.c
timeout.c
triggers.c
unitmessage.c
)
FOREACH(_FILE ${_FILES})
LIST(APPEND _SOURCES ${PROJECT_NAME}/${_FILE})

View file

@ -28,7 +28,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <triggers/killunit.h>
#include <triggers/shock.h>
#include <triggers/timeout.h>
#include <triggers/unitmessage.h>
#include <triggers/clonedied.h>
/* util includes */
@ -47,7 +46,6 @@ void register_triggers(void)
tt_register(&tt_giveitem);
tt_register(&tt_killunit);
tt_register(&tt_shock);
tt_register(&tt_unitmessage);
tt_register(&tt_timeout);
tt_register(&tt_clonedied);
}

View file

@ -1,124 +0,0 @@
/*
+-------------------+ Enno Rehling <enno@eressea.de>
| Eressea PBEM host | Christian Schlittchen <corwin@amber.kn-bremen.de>
| (c) 1998 - 2008 | Katja Zedel <katze@felidae.kn-bremen.de>
+-------------------+
This program may not be used, modified or distributed
without prior permission by the authors of Eressea.
*/
#include <platform.h>
#include "unitmessage.h"
/* kernel includes */
#include <kernel/unit.h>
#include <kernel/faction.h>
#include <kernel/messages.h>
/* util includes */
#include <util/attrib.h>
#include <util/base36.h>
#include <util/event.h>
#include <util/gamedata.h>
#include <util/goodies.h>
#include <util/language.h>
#include <util/log.h>
#include <util/resolve.h>
#include <storage.h>
/* ansi includes */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
/***
** give an item to someone
**/
typedef struct unitmessage_data {
struct unit *target;
char *string;
int type;
int level;
} unitmessage_data;
static void unitmessage_init(trigger * t)
{
t->data.v = calloc(sizeof(unitmessage_data), 1);
}
static void unitmessage_free(trigger * t)
{
unitmessage_data *sd = (unitmessage_data *)t->data.v;
free(sd->string);
free(t->data.v);
}
static int unitmessage_handle(trigger * t, void *data)
{
/* call an event handler on unitmessage.
* data.v -> ( variant event, int timer )
*/
unitmessage_data *td = (unitmessage_data *)t->data.v;
if (td->target && td->target->no) {
struct faction *f = td->target->faction;
const char * str = LOC(f->locale, td->string);
/* bug found in turn 733: sometimes, alps have f*cked up messages */
if (td->string && td->string[0]) {
addmessage(td->target->region, f, str, td->type,
td->level);
}
}
UNUSED_ARG(data);
return 0;
}
static void unitmessage_write(const trigger * t, struct storage *store)
{
unitmessage_data *td = (unitmessage_data *)t->data.v;
write_unit_reference(td->target, store);
WRITE_TOK(store, td->string);
WRITE_INT(store, td->type);
WRITE_INT(store, td->level);
}
static int unitmessage_read(trigger * t, gamedata *data)
{
unitmessage_data *td = (unitmessage_data *)t->data.v;
char zText[256];
int result = read_reference(&td->target, data, read_unit_reference,
resolve_unit);
READ_TOK(data->store, zText, sizeof(zText));
td->string = strdup(zText);
READ_INT(data->store, &td->type);
READ_INT(data->store, &td->level);
if (result == 0 && td->target == NULL) {
return AT_READ_FAIL;
}
return AT_READ_OK;
}
trigger_type tt_unitmessage = {
"unitmessage",
unitmessage_init,
unitmessage_free,
unitmessage_handle,
unitmessage_write,
unitmessage_read
};
trigger *trigger_unitmessage(unit * target, const char *string, int type,
int level)
{
trigger *t = t_new(&tt_unitmessage);
unitmessage_data *td = (unitmessage_data *)t->data.v;
td->target = target;
td->string = strdup(string);
td->type = type;
td->level = level;
return t;
}

View file

@ -1,37 +0,0 @@
/*
Copyright (c) 1998-2015, Enno Rehling <enno@eressea.de>
Katja Zedel <katze@felidae.kn-bremen.de
Christian Schlittchen <corwin@amber.kn-bremen.de>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
#ifndef UNITMESSAGE_H
#define UNITMESSAGE_H
#ifdef __cplusplus
extern "C" {
#endif
/* all types we use are defined here to reduce dependencies */
struct trigger_type;
struct trigger;
struct unit;
extern struct trigger_type tt_unitmessage;
extern struct trigger *trigger_unitmessage(struct unit *target,
const char *string, int type, int level);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -59,7 +59,7 @@ static void help_feed(unit * donor, unit * u, int *need_p)
}
static const char *hunger_damage(const race *rc) {
const char * damage = rc->parameters ? get_param(rc->parameters, "hunger.damage") : NULL;
const char * damage = rc_hungerdamage(rc);
if (!damage) {
damage = config_get("hunger.damage");
}
@ -98,11 +98,11 @@ static bool hunger(int number, unit * u)
deathcounts(r, dead);
}
if (hpsub > 0) {
/* Jetzt die Schäden der nicht gestorbenen abziehen. */
/* Jetzt die Sch<EFBFBD>den der nicht gestorbenen abziehen. */
u->hp -= hpsub;
/* Meldung nur, wenn noch keine für Tote generiert. */
/* Meldung nur, wenn noch keine f<EFBFBD>r Tote generiert. */
if (dead == 0) {
/* Durch unzureichende Ernährung wird %s geschwächt */
/* Durch unzureichende Ern<EFBFBD>hrung wird %s geschw<68>cht */
ADDMSG(&u->faction->msgs, msg_message("malnourish", "unit region", u, r));
}
}
@ -125,13 +125,13 @@ void get_food(region * r)
return;
}
/* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber
* wird zunächst so auf die Einheiten aufgeteilt, dass idealerweise
* jede Einheit genug Silber für ihren Unterhalt hat. */
* wird zun<EFBFBD>chst so auf die Einheiten aufgeteilt, dass idealerweise
* jede Einheit genug Silber f<EFBFBD>r ihren Unterhalt hat. */
for (u = r->units; u; u = u->next) {
int need = lifestyle(u);
/* Erstmal zurücksetzen */
/* Erstmal zur<EFBFBD>cksetzen */
freset(u, UFL_HUNGER);
if (u->ship && (u->ship->flags & SF_FISHING)) {
@ -230,7 +230,7 @@ void get_food(region * r)
}
/* 3. bestimmen, wie viele Bauern gefressen werden.
* bei fehlenden Bauern den Dämon hungern lassen
* bei fehlenden Bauern den D<EFBFBD>mon hungern lassen
*/
for (u = r->units; u; u = u->next) {
if (u_race(u) == rc_demon) {
@ -293,7 +293,7 @@ void get_food(region * r)
}
rsetpeasants(r, peasantfood / 10);
/* 3. Von den überlebenden das Geld abziehen: */
/* 3. Von den <EFBFBD>berlebenden das Geld abziehen: */
for (u = r->units; u; u = u->next) {
int need = MIN(get_money(u), lifestyle(u));
change_money(u, -need);

View file

@ -300,6 +300,9 @@ void init_translations(const struct locale *lang, int ut, const char * (*string_
struct critbit_tree ** cb = (struct critbit_tree **)tokens;
add_translation(cb, key, i);
}
else {
log_warning("no translation for %s in locale %s", s, lang->name);
}
}
}
}