Merge branch 'master' into develop

This commit is contained in:
Enno Rehling 2020-05-10 18:01:43 +02:00
commit 2d849b17d7
9 changed files with 151 additions and 62 deletions

View File

@ -6,10 +6,6 @@ local function equip_first(u)
equip_unit(u, name, 255) equip_unit(u, name, 255)
end end
local function equip_demon(u)
u.race_name = 'human'
end
local mysets = { local mysets = {
['first_unit'] = { ['first_unit'] = {
['items'] = { ['items'] = {
@ -82,7 +78,6 @@ local mysets = {
['skills'] = { ['skills'] = {
['stamina'] = 15 ['stamina'] = 15
}, },
['callback'] = equip_demon
}, },
['seed_insect'] = { ['seed_insect'] = {
['items'] = { ['items'] = {

View File

@ -300,15 +300,16 @@ fighter *select_corpse(battle * b, fighter * af)
/* Geflohene haben auch 0 hp, duerfen hier aber nicht ausgewaehlt /* Geflohene haben auch 0 hp, duerfen hier aber nicht ausgewaehlt
* werden! */ * werden! */
int dead = dead_fighters(df); int dead = dead_fighters(df);
if (!playerrace(u_race(df->unit))) const race *rc = u_race(df->unit);
continue; /* Untote sinc für immer tot */
if (!undeadrace(rc)) {
if (af && !helping(af->side, df->side)) if (af && !helping(af->side, df->side))
continue; continue;
if (di < dead) { if (di < dead) {
return df; return df;
}
di -= dead;
} }
di -= dead;
} }
} }
} }
@ -2076,9 +2077,6 @@ static void make_heroes(battle * b)
unit *u = fig->unit; unit *u = fig->unit;
if (fval(u, UFL_HERO)) { if (fval(u, UFL_HERO)) {
int i; int i;
if (!playerrace(u_race(u))) {
log_error("Hero %s is a %s.\n", unitname(u), u_race(u)->_name);
}
for (i = 0; i != u->number; ++i) { for (i = 0; i != u->number; ++i) {
fig->person[i].speed += (rule_hero_speed - 1); fig->person[i].speed += (rule_hero_speed - 1);
} }
@ -2609,11 +2607,12 @@ static void aftermath(battle * b)
for (df = s->fighters; df; df = df->next) { for (df = s->fighters; df; df = df->next) {
unit *du = df->unit; unit *du = df->unit;
int dead = dead_fighters(df); int dead = dead_fighters(df);
const race *rc = u_race(du);
/* tote insgesamt: */ /* tote insgesamt: */
s->dead += dead; s->dead += dead;
/* Tote, die wiederbelebt werde koennen: */ /* Tote, die wiederbelebt werde koennen: */
if (playerrace(u_race(df->unit))) { if (!undeadrace(rc)) {
s->casualties += dead; s->casualties += dead;
} }
if (df->hits + df->kills) { if (df->hits + df->kills) {
@ -2640,6 +2639,7 @@ static void aftermath(battle * b)
for (df = s->fighters; df; df = df->next) { for (df = s->fighters; df; df = df->next) {
unit *du = df->unit; unit *du = df->unit;
const race *rc = u_race(du);
int dead = dead_fighters(df); int dead = dead_fighters(df);
int sum_hp = 0; int sum_hp = 0;
int n; int n;
@ -2732,7 +2732,7 @@ static void aftermath(battle * b)
} }
s->flee += df->run.number; s->flee += df->run.number;
if (playerrace(u_race(du))) { if (!undeadrace(rc)) {
/* tote im kampf werden zu regionsuntoten: /* tote im kampf werden zu regionsuntoten:
* for each of them, a peasant will die as well */ * for each of them, a peasant will die as well */
dead_players += dead; dead_players += dead;
@ -3102,7 +3102,7 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack)
} }
else { else {
building *bld = u->building; building *bld = u->building;
if (bld && bld->sizeleft >= u->number && playerrace(u_race(u))) { if (bld && bld->sizeleft >= u->number && humanoidrace(u_race(u))) {
fig->building = bld; fig->building = bld;
fig->building->sizeleft -= u->number; fig->building->sizeleft -= u->number;
} }

View File

@ -83,7 +83,7 @@ static void chaos(region * r)
case 0: /* Untote */ case 0: /* Untote */
if (!(r->terrain->flags & SEA_REGION)) { if (!(r->terrain->flags & SEA_REGION)) {
unit *u = random_unit(r); unit *u = random_unit(r);
if (u && playerrace(u_race(u))) { if (u && !undeadrace(u_race(u))) {
ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u)); ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u));
u_setfaction(u, get_monsters()); u_setfaction(u, get_monsters());
u_freeorders(u); u_freeorders(u);

View File

@ -724,6 +724,7 @@ static void cr_output_spells(stream *out, const unit * u, int maxlevel)
void cr_output_unit(stream *out, const faction * f, void cr_output_unit(stream *out, const faction * f,
const unit * u, seen_mode mode) const unit * u, seen_mode mode)
{ {
const struct locale *lang = crtag_locale();
/* Race attributes are always plural and item attributes always /* Race attributes are always plural and item attributes always
* singular */ * singular */
const char *str; const char *str;
@ -736,7 +737,6 @@ void cr_output_unit(stream *out, const faction * f,
const faction *fother; const faction *fother;
const char *prefix; const char *prefix;
bool allied; bool allied;
const struct locale *lang = f->locale;
assert(u && u->number); assert(u && u->number);
@ -796,17 +796,16 @@ void cr_output_unit(stream *out, const faction * f,
pzTmp = get_racename(u->attribs); pzTmp = get_racename(u->attribs);
if (pzTmp) { if (pzTmp) {
const char *pzRace = locale_string(lang, mkname("race", pzTmp), false); const char *pzRace = pzTmp;
if (pzRace) { const struct race *rc = rc_find(pzTmp);
pzTmp = pzRace; if (rc) {
pzRace = rc_name_s(rc, NAME_PLURAL);
} }
pzRace = translate(pzTmp, locale_string(lang, pzTmp, false)); pzTmp = translate(pzRace, locale_string(lang, pzRace, false));
if (!pzRace) { stream_printf(out, "\"%s\";Typ\n", pzTmp);
pzRace = pzTmp; rc = u_race(u);
} if (u->faction == f && fval(rc, RCF_SHAPESHIFTANY)) {
stream_printf(out, "\"%s\";Typ\n", pzRace); pzRace = rc_name_s(rc, NAME_PLURAL);
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); stream_printf(out, "\"%s\";wahrerTyp\n", pzRace);
} }
} }
@ -1514,7 +1513,7 @@ static void report_itemtype(FILE *F, faction *f, const item_type *itype) {
static int static int
report_computer(const char *filename, report_context * ctx, const char *bom) report_computer(const char *filename, report_context * ctx, const char *bom)
{ {
static int era = -1; const struct locale *lang = crtag_locale();
int i; int i;
faction *f = ctx->f; faction *f = ctx->f;
const char *prefix, *str; const char *prefix, *str;
@ -1524,6 +1523,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
FILE *F = fopen(filename, "w"); FILE *F = fopen(filename, "w");
static const race *rc_human; static const race *rc_human;
static int rc_cache; static int rc_cache;
static int era = -1;
if (era < 0) { if (era < 0) {
era = config_get_int("game.era", 1); era = config_get_int("game.era", 1);
@ -1578,13 +1578,13 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
} }
{ {
const char *zRace = rc_name_s(f->race, NAME_PLURAL); const char *zRace = rc_name_s(f->race, NAME_PLURAL);
fprintf(F, "\"%s\";Typ\n", translate(zRace, LOC(f->locale, zRace))); fprintf(F, "\"%s\";Typ\n", translate(zRace, LOC(lang, zRace)));
} }
prefix = get_prefix(f->attribs); prefix = get_prefix(f->attribs);
if (prefix != NULL) { if (prefix != NULL) {
prefix = mkname("prefix", prefix); prefix = mkname("prefix", prefix);
fprintf(F, "\"%s\";typprefix\n", fprintf(F, "\"%s\";typprefix\n",
translate(prefix, LOC(f->locale, prefix))); translate(prefix, LOC(lang, prefix)));
} }
fprintf(F, "%d;Rekrutierungskosten\n", f->race->recruitcost); fprintf(F, "%d;Rekrutierungskosten\n", f->race->recruitcost);
fprintf(F, "%d;Anzahl Personen\n", f->num_people); fprintf(F, "%d;Anzahl Personen\n", f->num_people);
@ -1637,7 +1637,7 @@ report_computer(const char *filename, report_context * ctx, const char *bom)
if (prefix != NULL) { if (prefix != NULL) {
prefix = mkname("prefix", prefix); prefix = mkname("prefix", prefix);
fprintf(F, "\"%s\";typprefix\n", fprintf(F, "\"%s\";typprefix\n",
translate(prefix, LOC(f->locale, prefix))); translate(prefix, LOC(lang, prefix)));
} }
show_allies_cr(F, f, g); show_allies_cr(F, f, g);
} }

View File

@ -4,6 +4,13 @@
#include "spy.h" #include "spy.h"
#include "travelthru.h" #include "travelthru.h"
#include "attributes/racename.h"
#include "util/keyword.h"
#include <util/language.h>
#include <util/lists.h>
#include <util/message.h>
#include <kernel/ally.h> #include <kernel/ally.h>
#include <kernel/building.h> #include <kernel/building.h>
#include <kernel/faction.h> #include <kernel/faction.h>
@ -16,11 +23,6 @@
#include <kernel/spell.h> #include <kernel/spell.h>
#include <kernel/spellbook.h> #include <kernel/spellbook.h>
#include "util/keyword.h"
#include <util/language.h>
#include <util/lists.h>
#include <util/message.h>
#include <stream.h> #include <stream.h>
#include <memstream.h> #include <memstream.h>
@ -222,6 +224,96 @@ static int cr_get_int(stream *strm, const char *match, int def)
return def; return def;
} }
static bool cr_find_string(stream *strm, const char *match, const char *value)
{
char line[1024];
size_t len = strlen(match);
strm->api->rewind(strm->handle);
while (strm->api->readln(strm->handle, line, sizeof(line))==0) {
if (line[0] == '\"') {
const char * pos = strstr(line + 1, match);
if (pos && pos[len] == '\0') {
size_t vlen = strlen(value);
if (value != NULL && strncmp(line + 1, value, vlen) == 0) {
return (line[vlen + 1] == '\"');
}
return false;
}
}
}
return value == NULL;
}
static void test_cr_hiderace(CuTest *tc) {
stream strm;
faction *f1, *f2;
region *r;
unit *u;
struct locale * lang;
test_setup();
default_locale = test_create_locale();
locale_setstring(default_locale, "race::elf_p", "Elfen");
locale_setstring(default_locale, "race::elf", "elf");
locale_setstring(default_locale, "race::human_p", "Menschen");
locale_setstring(default_locale, "race::human", "Mensch");
lang = get_or_create_locale("en");
locale_setstring(lang, "race::human_p", "humans");
locale_setstring(lang, "race::human", "human");
locale_setstring(lang, "race::elf_p", "elves");
locale_setstring(lang, "race::elf", "elf");
f1 = test_create_faction(NULL);
f2 = test_create_faction(NULL);
r = test_create_region(0, 0, NULL);
u = test_create_unit(f1, r);
mstream_init(&strm);
CuAssertPtrEquals(tc, default_locale, (struct locale *)f1->locale);
CuAssertPtrEquals(tc, default_locale, (struct locale *)f2->locale);
cr_output_unit(&strm, f1, u, seen_unit);
CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Menschen"));
CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", NULL));
mstream_done(&strm);
mstream_init(&strm);
CuAssertPtrEquals(tc, default_locale, (struct locale *)f1->locale);
CuAssertPtrEquals(tc, default_locale, (struct locale *)f2->locale);
cr_output_unit(&strm, f2, u, seen_unit);
CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Menschen"));
CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", NULL));
mstream_done(&strm);
/* when we use irace, the owner can see the true race */
f1->locale = lang;
u->irace = test_create_race("elf");
mstream_init(&strm);
cr_output_unit(&strm, f1, u, seen_unit);
CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Elfen"));
CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", "Menschen"));
mstream_done(&strm);
mstream_init(&strm);
cr_output_unit(&strm, f2, u, seen_unit);
CuAssertTrue(tc, cr_find_string(&strm, ";Typ", "Elfen"));
CuAssertTrue(tc, cr_find_string(&strm, ";wahrerTyp", NULL));
mstream_done(&strm);
/* when we use racename, nobody can tell it's not the real deal */
u->irace = NULL;
set_racename(&u->attribs, "Zwerge");
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, ";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, ";wahrerTyp", NULL));
mstream_done(&strm);
test_teardown();
}
static void test_cr_factionstealth(CuTest *tc) { static void test_cr_factionstealth(CuTest *tc) {
stream strm; stream strm;
faction *f1, *f2; faction *f1, *f2;
@ -326,6 +418,7 @@ CuSuite *get_creport_suite(void)
SUITE_ADD_TEST(suite, test_cr_unit); SUITE_ADD_TEST(suite, test_cr_unit);
SUITE_ADD_TEST(suite, test_cr_resources); SUITE_ADD_TEST(suite, test_cr_resources);
SUITE_ADD_TEST(suite, test_cr_mallorn); SUITE_ADD_TEST(suite, test_cr_mallorn);
SUITE_ADD_TEST(suite, test_cr_hiderace);
SUITE_ADD_TEST(suite, test_cr_factionstealth); SUITE_ADD_TEST(suite, test_cr_factionstealth);
return suite; return suite;
} }

View File

@ -279,12 +279,10 @@ unit *addplayer(region * r, faction * f)
u->hp = unit_max_hp(u) * u->number; u->hp = unit_max_hp(u) * u->number;
fset(u, UFL_ISNEW); fset(u, UFL_ISNEW);
if (f->race == get_race(RC_DAEMON)) { if (f->race == get_race(RC_DAEMON)) {
race_t urc;
const race *rc; const race *rc;
do { int urc = (race_t)(rng_int() % MAX_START_RACE);
urc = (race_t)(rng_int() % MAXRACES); if (urc >= RC_DAEMON) ++urc;
rc = get_race(urc); rc = get_race(urc);
} while (rc == NULL || urc == RC_DAEMON || !playerrace(rc));
u->irace = rc; u->irace = rc;
} }
f->lastorders = turn; f->lastorders = turn;

View File

@ -48,16 +48,14 @@ int num_races = 0;
static int rc_changes = 1; static int rc_changes = 1;
const char *racenames[MAXRACES] = { const char *racenames[MAXRACES] = {
"dwarf", "elf", NULL, "goblin", "human", "troll", "demon", "insect", "dwarf", "elf", "goblin", "human", "troll", "demon", "insect",
"halfling", "cat", "aquarian", "orc", "snotling", "undead", NULL, "halfling", "cat", "aquarian", "orc", "snotling", "undead",
"youngdragon", "dragon", "wyrm", "ent", "catdragon", "dracoid", "youngdragon", "dragon", "wyrm", "ent", "catdragon", "dracoid",
NULL, NULL, "irongolem", "stonegolem", "shadowdemon", "irongolem", "stonegolem", "shadowdemon",
"shadowmaster", "mountainguard", "alp", "toad", "braineater", "peasant", "shadowmaster", "mountainguard", "alp", "toad", "braineater", "peasant",
"wolf", NULL, NULL, NULL, NULL, "songdragon", NULL, "wolf", "songdragon", "seaserpent",
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "shadowknight", "skeleton", "skeletonlord", "zombie",
NULL, NULL, NULL, NULL, NULL, "seaserpent", "juju", "ghoul", "ghast", "template",
"shadowknight", NULL, "skeleton", "skeletonlord", "zombie",
"juju", "ghoul", "ghast", NULL, NULL, "template",
"clone" "clone"
}; };

View File

@ -35,7 +35,7 @@ extern "C" {
typedef enum { typedef enum {
RC_DWARF, /* 0 - Zwerg */ RC_DWARF, /* 0 - Zwerg */
RC_ELF, RC_ELF,
RC_GOBLIN = 3, RC_GOBLIN,
RC_HUMAN, RC_HUMAN,
RC_TROLL, RC_TROLL,
RC_DAEMON, RC_DAEMON,
@ -44,17 +44,19 @@ extern "C" {
RC_CAT, RC_CAT,
RC_AQUARIAN, RC_AQUARIAN,
RC_ORC, RC_ORC,
/* last of the addplayer races */
RC_SNOTLING, RC_SNOTLING,
RC_UNDEAD, RC_UNDEAD,
RC_FIREDRAGON = 15, RC_FIREDRAGON,
RC_DRAGON, RC_DRAGON,
RC_WYRM, RC_WYRM,
RC_TREEMAN, RC_TREEMAN,
RC_BIRTHDAYDRAGON, RC_BIRTHDAYDRAGON,
RC_DRACOID, RC_DRACOID,
RC_IRONGOLEM = 23, RC_IRONGOLEM,
RC_STONEGOLEM, RC_STONEGOLEM,
RC_SHADOW, RC_SHADOW,
RC_SHADOWLORD, RC_SHADOWLORD,
@ -63,25 +65,27 @@ extern "C" {
RC_TOAD, RC_TOAD,
RC_HIRNTOETER, RC_HIRNTOETER,
RC_PEASANT, RC_PEASANT,
RC_WOLF = 32, RC_WOLF,
RC_SONGDRAGON = 37, RC_SONGDRAGON,
RC_SEASERPENT = 51, RC_SEASERPENT,
RC_SHADOWKNIGHT, RC_SHADOWKNIGHT,
RC_SKELETON = 54, RC_SKELETON,
RC_SKELETON_LORD, RC_SKELETON_LORD,
RC_ZOMBIE, RC_ZOMBIE,
RC_ZOMBIE_LORD, RC_ZOMBIE_LORD,
RC_GHOUL, RC_GHOUL,
RC_GHOUL_LORD, RC_GHOUL_LORD,
RC_TEMPLATE = 62, RC_TEMPLATE,
RC_CLONE, RC_CLONE,
MAXRACES, MAXRACES,
NORACE = -1 NORACE = -1
} race_t; } race_t;
#define MAX_START_RACE RC_ORC
extern int num_races; extern int num_races;
extern const char *racenames[MAXRACES]; extern const char *racenames[MAXRACES];
@ -241,6 +245,7 @@ extern "C" {
#define playerrace(rc) ((rc)->flags & RCF_PLAYABLE) #define playerrace(rc) ((rc)->flags & RCF_PLAYABLE)
#define dragonrace(rc) ((rc)->flags & RCF_DRAGON) #define dragonrace(rc) ((rc)->flags & RCF_DRAGON)
#define humanoidrace(rc) (((rc)->flags & RCF_UNDEAD) || (rc)==get_race(RC_DRACOID) || playerrace(rc)) #define humanoidrace(rc) (((rc)->flags & RCF_UNDEAD) || (rc)==get_race(RC_DRACOID) || playerrace(rc))
#define undeadrace(rc) (((rc)->flags & RCF_UNDEAD) || (rc)==get_race(RC_DRACOID))
#define illusionaryrace(rc) ((rc)->flags & RCF_ILLUSIONARY) #define illusionaryrace(rc) ((rc)->flags & RCF_ILLUSIONARY)
bool allowed_dragon(const struct region *src, bool allowed_dragon(const struct region *src,

View File

@ -1399,7 +1399,7 @@ static int heal_fighters(selist * fgs, int *power, bool heal_monsters)
continue; continue;
/* wir heilen erstmal keine Monster */ /* wir heilen erstmal keine Monster */
if (heal_monsters || playerrace(u_race(df->unit))) { if (heal_monsters || !undeadrace(u_race(df->unit))) {
int n, hp = df->unit->hp / df->unit->number; int n, hp = df->unit->hp / df->unit->number;
int rest = df->unit->hp % df->unit->number; int rest = df->unit->hp % df->unit->number;