From 3b864b10fc92f5dc339643f26756bb89846ac237 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Aug 2020 10:31:58 +0200 Subject: [PATCH 1/2] bug 2686: stealth races not translated correctly. --- res/e3a/races.xml | 4 ++-- res/eressea/races.xml | 2 +- src/creport.c | 47 ++++++++++++++++++++++--------------------- src/kernel/gamedata.h | 5 +++-- src/kernel/save.c | 21 ++++++++++++++++++- 5 files changed, 50 insertions(+), 29 deletions(-) diff --git a/res/e3a/races.xml b/res/e3a/races.xml index 117759ca8..2316b8aa5 100644 --- a/res/e3a/races.xml +++ b/res/e3a/races.xml @@ -4,7 +4,7 @@ - + @@ -101,7 +101,7 @@ - + diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 8c3822110..9063fbe1d 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -840,7 +840,7 @@ - + diff --git a/src/creport.c b/src/creport.c index 0e88972f7..7773cdea4 100644 --- a/src/creport.c +++ b/src/creport.c @@ -117,24 +117,26 @@ static translation *junkyard; static const char *translate(const char *key, const char *value) { - int kk = ((key[0] << 5) + key[0]) % TRANSMAXHASH; - translation *t = translation_table[kk]; - while (t && strcmp(t->key, key) != 0) - t = t->next; - if (!t) { - if (junkyard) { - t = junkyard; - junkyard = junkyard->next; + if (value) { + int kk = ((key[0] << 5) + key[0]) % TRANSMAXHASH; + translation *t = translation_table[kk]; + while (t && strcmp(t->key, key) != 0) + t = t->next; + if (!t) { + if (junkyard) { + t = junkyard; + junkyard = junkyard->next; + } + else { + t = malloc(sizeof(translation)); + if (!t) abort(); + } + t->key = str_strdup(key); + if (!t->key) abort(); + t->value = value; + t->next = translation_table[kk]; + translation_table[kk] = t; } - else { - t = malloc(sizeof(translation)); - if (!t) abort(); - } - t->key = str_strdup(key); - if (!t->key) abort(); - t->value = value; - t->next = translation_table[kk]; - translation_table[kk] = t; } return crtag(key); } @@ -796,19 +798,18 @@ void cr_output_unit(stream *out, const faction * f, pzTmp = get_racename(u->attribs); if (pzTmp) { - const char *pzRace = locale_string(lang, mkname("race", pzTmp), false); + char buffer[64]; + const char *key = rc_key(pzTmp, NAME_PLURAL, buffer, sizeof(buffer)); + const char *pzRace = locale_string(lang, key, false); if (pzRace) { + /* ex: "Ritter von Go */ pzTmp = pzRace; } - pzRace = translate(pzTmp, locale_string(lang, pzTmp, false)); + pzRace = translate(key, pzTmp); if (!pzRace) { pzRace = pzTmp; } stream_printf(out, "\"%s\";Typ\n", pzRace); - if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { - pzRace = rc_name_s(u_race(u), NAME_PLURAL); - stream_printf(out, "\"%s\";wahrerTyp\n", pzRace); - } } else { const race *irace = u_irace(u); diff --git a/src/kernel/gamedata.h b/src/kernel/gamedata.h index b0fd7762c..0830d11c9 100644 --- a/src/kernel/gamedata.h +++ b/src/kernel/gamedata.h @@ -45,9 +45,10 @@ #define FIX_RES_BASE_VERSION 367 /* fixing resource base */ #define FIX_CLONES_VERSION 368 /* dissolve clones */ #define FIX_MIGRANT_AURA_VERSION 369 /* bug 2585, migrants with aura */ -#define SHIP_NUMBER_VERISON 370 /* ships have a number */ +#define SHIP_NUMBER_VERSION 370 /* ships have a number */ +#define FIX_SHAPESHIFT_VERSION 371 /* ships have a number */ -#define RELEASE_VERSION SHIP_NUMBER_VERISON /* current datafile */ +#define RELEASE_VERSION FIX_SHAPESHIFT_VERSION /* current datafile */ #define MIN_VERSION UIDHASH_VERSION /* minimal datafile we support */ #define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */ diff --git a/src/kernel/save.c b/src/kernel/save.c index 66eb22471..4d9574a61 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -34,6 +34,7 @@ /* attributes includes */ #include #include +#include #include #include @@ -381,6 +382,12 @@ unit *read_unit(gamedata *data) char obuf[DISPLAYSIZE]; faction *f; char rname[32]; + static const struct race * rc_demon; + static int config; + + if (rc_changed(&config)) { + rc_demon = get_race(RC_DAEMON); + } READ_INT(data->store, &n); if (n <= 0) { @@ -518,6 +525,18 @@ unit *read_unit(gamedata *data) u->hp = u->number; } read_attribs(data, &u->attribs, u); + if (rc_demon && data->version < FIX_SHAPESHIFT_VERSION) { + if (u_race(u) == rc_demon) { + const char *zRace = get_racename(u->attribs); + if (zRace) { + const struct race *rc = rc_find(zRace); + if (rc) { + set_racename(&u->attribs, NULL); + u->irace = rc; + } + } + } + } resolve_unit(u); return u; } @@ -1322,7 +1341,7 @@ ship *read_ship(gamedata *data) } assert(sh->type || !"ship_type not registered!"); - if (data->version < SHIP_NUMBER_VERISON) { + if (data->version < SHIP_NUMBER_VERSION) { sh->number = 1; } else { From eed04734215eb225c98a2e510136888898837c36 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 3 Aug 2020 10:33:24 +0200 Subject: [PATCH 2/2] remove the stealthany race flag --- res/eressea/races.xml | 7 +- src/attributes/racename.c | 23 +++--- src/creport.c | 17 ++-- src/creport.test.c | 18 +++- src/kernel/race.h | 1 - src/reports.c | 2 +- src/spy.c | 168 ++++++++++++++++++-------------------- 7 files changed, 121 insertions(+), 115 deletions(-) diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 9063fbe1d..71eacc458 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -689,7 +689,7 @@ - + @@ -840,7 +840,10 @@ - + diff --git a/src/attributes/racename.c b/src/attributes/racename.c index 138355e3c..901630731 100644 --- a/src/attributes/racename.c +++ b/src/attributes/racename.c @@ -24,17 +24,20 @@ const char *get_racename(attrib * alist) void set_racename(attrib ** palist, const char *name) { attrib *a = a_find(*palist, &at_racename); - if (!a && name) { + + if (a) { + if (name) { + if (strcmp(a->data.v, name) != 0) { + free(a->data.v); + a->data.v = str_strdup(name); + } + } + else { + a_remove(palist, a); + } + } + else if (name) { a = a_add(palist, a_new(&at_racename)); a->data.v = str_strdup(name); } - else if (a && !name) { - a_remove(palist, a); - } - else if (a) { - if (strcmp(a->data.v, name) != 0) { - free(a->data.v); - a->data.v = str_strdup(name); - } - } } diff --git a/src/creport.c b/src/creport.c index 7773cdea4..4f92fe132 100644 --- a/src/creport.c +++ b/src/creport.c @@ -798,18 +798,15 @@ void cr_output_unit(stream *out, const faction * f, pzTmp = get_racename(u->attribs); if (pzTmp) { - char buffer[64]; - const char *key = rc_key(pzTmp, NAME_PLURAL, buffer, sizeof(buffer)); - const char *pzRace = locale_string(lang, key, false); - if (pzRace) { - /* ex: "Ritter von Go */ - pzTmp = pzRace; + const race *irace = rc_find(pzTmp); + if (irace) { + const char *pzRace = rc_name_s(irace, NAME_PLURAL); + stream_printf(out, "\"%s\";Typ\n", + translate(pzRace, LOC(lang, pzRace))); } - pzRace = translate(key, pzTmp); - if (!pzRace) { - pzRace = pzTmp; + else { + stream_printf(out, "\"%s\";Typ\n", pzTmp); } - stream_printf(out, "\"%s\";Typ\n", pzRace); } else { const race *irace = u_irace(u); diff --git a/src/creport.test.c b/src/creport.test.c index 53b2e9d93..a17fca6de 100644 --- a/src/creport.test.c +++ b/src/creport.test.c @@ -299,15 +299,27 @@ static void test_cr_hiderace(CuTest *tc) { /* when we use racename, nobody can tell it's not the real deal */ u->irace = NULL; - set_racename(&u->attribs, "Zwerge"); + set_racename(&u->attribs, "human"); mstream_init(&strm); cr_output_unit(&strm, f1, u, seen_unit); - CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Zwerge")); + CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Menschen")); CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", NULL)); mstream_done(&strm); mstream_init(&strm); cr_output_unit(&strm, f2, u, seen_unit); - CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Zwerge")); + CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Menschen")); + CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", NULL)); + mstream_done(&strm); + + set_racename(&u->attribs, "Ritter von Go"); + mstream_init(&strm); + cr_output_unit(&strm, f1, u, seen_unit); + CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Ritter von Go")); + CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", NULL)); + mstream_done(&strm); + mstream_init(&strm); + cr_output_unit(&strm, f2, u, seen_unit); + CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Ritter von Go")); CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", NULL)); mstream_done(&strm); diff --git a/src/kernel/race.h b/src/kernel/race.h index 4cd7fd3b7..8918437e1 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -207,7 +207,6 @@ extern "C" { #define RCF_NOHEAL (1<<16) /* Einheit kann nicht geheilt werden */ #define RCF_NOWEAPONS (1<<17) /* Einheit kann keine Waffen benutzen */ #define RCF_SHAPESHIFT (1<<18) /* Kann TARNE RASSE benutzen. */ -#define RCF_SHAPESHIFTANY (1<<19) /* Kann TARNE RASSE "string" benutzen. */ #define RCF_UNDEAD (1<<20) /* Undead. */ #define RCF_DRAGON (1<<21) /* Drachenart (fuer Zauber) */ #define RCF_COASTAL (1<<22) /* kann in Landregionen an der Kueste sein */ diff --git a/src/reports.c b/src/reports.c index c690aa345..2553920d1 100644 --- a/src/reports.c +++ b/src/reports.c @@ -698,7 +698,7 @@ void bufunit(const faction * f, const unit * u, const faction *fv, if (pzTmp) { const char *name = locale_string(lang, mkname("race", pzTmp), false); sbs_strcat(sbp, name ? name : pzTmp); - if (u->faction == f && fval(u_race(u), RCF_SHAPESHIFTANY)) { + if (u->faction == f) { sbs_strcat(sbp, " ("); sbs_strcat(sbp, racename(lang, u, u_race(u))); sbs_strcat(sbp, ")"); diff --git a/src/spy.c b/src/spy.c index c4752ff72..8fcfa31e2 100644 --- a/src/spy.c +++ b/src/spy.c @@ -195,6 +195,39 @@ void set_factionstealth(unit *u, faction *f) { a->data.v = f; } +static void stealth_race(unit *u, const char *s) { + const race *trace; + + trace = findrace(s, u->faction->locale); + if (trace) { + /* demons can cloak as other player-races */ + if (u_race(u) == get_race(RC_DAEMON)) { + if (playerrace(trace)) { + u->irace = trace; + } + } + /* Singdrachen können sich nur als Drachen tarnen */ + else if (u_race(u) == get_race(RC_SONGDRAGON) + || u_race(u) == get_race(RC_BIRTHDAYDRAGON)) { + if (trace == get_race(RC_SONGDRAGON) || trace == get_race(RC_FIREDRAGON) + || trace == get_race(RC_DRAGON) || trace == get_race(RC_WYRM)) { + u->irace = trace; + } + } + + /* Schablonen können sich als alles mögliche tarnen */ + if (u_race(u)->flags & RCF_SHAPESHIFT) { + u->irace = trace; + set_racename(&u->attribs, NULL); + } + } + else { + if (u_race(u)->flags & RCF_SHAPESHIFT) { + set_racename(&u->attribs, s); + } + } +} + int setstealth_cmd(unit * u, struct order *ord) { char token[64]; @@ -207,111 +240,70 @@ int setstealth_cmd(unit * u, struct order *ord) if (s == NULL || *s == 0) { u_seteffstealth(u, -1); - return 0; } - - if (isdigit(*(const unsigned char *)s)) { + else if (isdigit(*(const unsigned char *)s)) { /* Tarnungslevel setzen */ int level = atoi((const char *)s); if (level > effskill(u, SK_STEALTH, NULL)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_lowstealth", "")); - return 0; } - u_seteffstealth(u, level); - return 0; - } - - if (skill_enabled(SK_STEALTH)) { /* hack! E3 erlaubt keine Tarnung */ - const race *trace; - - trace = findrace(s, u->faction->locale); - if (trace) { - /* demons can cloak as other player-races */ - if (u_race(u) == get_race(RC_DAEMON)) { - if (playerrace(trace)) { - u->irace = trace; - if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) { - set_racename(&u->attribs, NULL); - } - } - return 0; - } - /* Singdrachen koennen sich nur als Drachen tarnen */ - else if (u_race(u) == get_race(RC_SONGDRAGON) - || u_race(u) == get_race(RC_BIRTHDAYDRAGON)) { - if (trace == get_race(RC_SONGDRAGON) || trace == get_race(RC_FIREDRAGON) - || trace == get_race(RC_DRAGON) || trace == get_race(RC_WYRM)) { - u->irace = trace; - if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) - set_racename(&u->attribs, NULL); - } - return 0; - } - - /* Daemomen und Illusionsparteien koennen sich als andere race tarnen */ - if (u_race(u)->flags & RCF_SHAPESHIFT) { - if (playerrace(trace)) { - u->irace = trace; - if ((u_race(u)->flags & RCF_SHAPESHIFTANY) && get_racename(u->attribs)) - set_racename(&u->attribs, NULL); - } - } - return 0; + else { + u_seteffstealth(u, level); } } - - switch (findparam(s, u->faction->locale)) { - case P_FACTION: - /* TARNE PARTEI [NICHT|NUMMER abcd] */ - s = gettoken(token, sizeof(token)); - if (rule_stealth_anon()) { - if (!s || *s == 0) { - u->flags |= UFL_ANON_FACTION; - break; - } - else if (findparam(s, u->faction->locale) == P_NOT) { - u->flags &= ~UFL_ANON_FACTION; - break; - } - } - if (rule_stealth_other()) { - if (get_keyword(s, u->faction->locale) == K_NUMBER) { - int nr = -1; - - s = gettoken(token, sizeof(token)); - if (s) { - nr = atoi36(s); - } - if (!s || *s == 0 || nr == u->faction->no) { - a_removeall(&u->attribs, &at_otherfaction); + else { + switch (findparam(s, u->faction->locale)) { + case P_FACTION: + /* TARNE PARTEI [NICHT|NUMMER abcd] */ + s = gettoken(token, sizeof(token)); + if (rule_stealth_anon()) { + if (!s || *s == 0) { + u->flags |= UFL_ANON_FACTION; break; } - else { - struct faction *f = findfaction(nr); - if (f == NULL || !can_set_factionstealth(u, f)) { - cmistake(u, ord, 66, MSG_EVENT); + else if (findparam(s, u->faction->locale) == P_NOT) { + u->flags &= ~UFL_ANON_FACTION; + break; + } + } + if (rule_stealth_other()) { + if (get_keyword(s, u->faction->locale) == K_NUMBER) { + int nr = -1; + + s = gettoken(token, sizeof(token)); + if (s) { + nr = atoi36(s); + } + if (!s || *s == 0 || nr == u->faction->no) { + a_removeall(&u->attribs, &at_otherfaction); break; } else { - set_factionstealth(u, f); - break; + struct faction *f = findfaction(nr); + if (f == NULL || !can_set_factionstealth(u, f)) { + cmistake(u, ord, 66, MSG_EVENT); + break; + } + else { + set_factionstealth(u, f); + break; + } } } } - } - cmistake(u, ord, 289, MSG_EVENT); - break; - case P_ANY: - case P_NOT: - /* TARNE ALLES (was nicht so alles geht?) */ - u_seteffstealth(u, -1); - break; - default: - if (u_race(u)->flags & RCF_SHAPESHIFTANY) { - set_racename(&u->attribs, s); - } - else { cmistake(u, ord, 289, MSG_EVENT); + break; + + case P_ANY: + case P_NOT: + /* TARNE ALLES (was nicht so alles geht?) */ + u_seteffstealth(u, -1); + break; + + default: + if (skill_enabled(SK_STEALTH)) { /* hack! E3 erlaubt keine Tarnung */ + stealth_race(u, s); + } } } return 0;