diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c
index 56a76496e..dc4a748f5 100644
--- a/src/common/gamecode/creport.c
+++ b/src/common/gamecode/creport.c
@@ -717,8 +717,8 @@ cr_output_unit(FILE * F, const region * r,
}
fprintf(F, "%d;Partei\n", u->faction->no);
if (sf!=u->faction) fprintf(F, "%d;Verkleidung\n", sf->no);
- if (fval(u, UFL_PARTEITARNUNG))
- fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_PARTEITARNUNG)));
+ if (fval(u, UFL_ANON_FACTION))
+ fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION)));
if (otherfaction) {
if (otherfaction!=u->faction) {
fprintf(F, "%d;Anderepartei\n", otherfaction->no);
@@ -729,9 +729,9 @@ cr_output_unit(FILE * F, const region * r,
fprintf(F, "%u;familiarmage\n", mage->no);
}
} else {
- if (fval(u, UFL_PARTEITARNUNG)) {
+ if (fval(u, UFL_ANON_FACTION)) {
/* faction info is hidden */
- fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_PARTEITARNUNG)));
+ fprintf(F, "%d;Parteitarnung\n", i2b(fval(u, UFL_ANON_FACTION)));
} else {
const attrib * a_otherfaction = a_find(u->attribs, &at_otherfaction);
const faction * otherfaction = a_otherfaction?get_otherfaction(a_otherfaction):NULL;
@@ -1324,7 +1324,7 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
for (b = rbuildings(r); b; b = b->next) {
int fno = -1;
u = building_owner(b);
- if (u && !fval(u, UFL_PARTEITARNUNG)) {
+ if (u && !fval(u, UFL_ANON_FACTION)) {
const faction * sf = visible_faction(f,u);
fno = sf->no;
}
@@ -1335,7 +1335,7 @@ cr_output_region(FILE * F, report_context * ctx, seen_region * sr)
for (sh = r->ships; sh; sh = sh->next) {
int fno = -1;
u = shipowner(sh);
- if (u && !fval(u, UFL_PARTEITARNUNG)) {
+ if (u && !fval(u, UFL_ANON_FACTION)) {
const faction * sf = visible_faction(f,u);
fno = sf->no;
}
diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c
index c4e8cd39a..e4d281c9e 100644
--- a/src/common/gamecode/randenc.c
+++ b/src/common/gamecode/randenc.c
@@ -348,7 +348,7 @@ get_allies(region * r, unit * u)
if (u->race->flags & RCF_SHAPESHIFT) {
newunit->irace = u->irace;
}
- if (fval(u, UFL_PARTEITARNUNG)) fset(newunit, UFL_PARTEITARNUNG);
+ if (fval(u, UFL_ANON_FACTION)) fset(newunit, UFL_ANON_FACTION);
fset(newunit, UFL_ISNEW);
msg = msg_message("encounter_allies", "unit name", u, name);
diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c
index 6d4c81258..582333140 100644
--- a/src/common/gamecode/report.c
+++ b/src/common/gamecode/report.c
@@ -674,10 +674,10 @@ nr_unit(FILE * F, const faction * f, const unit * u, int indent, int mode)
} else if ALLIED(u->faction, f) {
marker = 'o';
} else if (a_otherfaction && f != u->faction && get_otherfaction(a_otherfaction) == f
- && !fval(u, UFL_PARTEITARNUNG)) {
+ && !fval(u, UFL_ANON_FACTION)) {
marker = '!';
} else {
- if (dh && !fval(u, UFL_PARTEITARNUNG)) {
+ if (dh && !fval(u, UFL_ANON_FACTION)) {
marker = '+';
} else {
marker = '-';
@@ -1644,7 +1644,7 @@ guards(FILE * F, const region * r, const faction * see)
f = fv;
}
- if (f != see && fval(u, UFL_PARTEITARNUNG)) {
+ if (f != see && fval(u, UFL_ANON_FACTION)) {
tarned=true;
} else {
for (i=0;i!=nextguard;++i) if (guardians[i]==f) break;
diff --git a/src/common/gamecode/spy.c b/src/common/gamecode/spy.c
index 07d1dfb59..c488d0a6b 100644
--- a/src/common/gamecode/spy.c
+++ b/src/common/gamecode/spy.c
@@ -299,11 +299,12 @@ setstealth_cmd(unit * u, struct order * ord)
switch(findparam(s, u->faction->locale)) {
case P_FACTION:
/* TARNE PARTEI [NICHT|NUMMER abcd] */
+ if (!rule_stealth_faction()) break;
s = getstrtoken();
if(!s || *s == 0) {
- fset(u, UFL_PARTEITARNUNG);
+ fset(u, UFL_ANON_FACTION);
} else if (findparam(s, u->faction->locale) == P_NOT) {
- freset(u, UFL_PARTEITARNUNG);
+ freset(u, UFL_ANON_FACTION);
} else if (findkeyword(s, u->faction->locale) == K_NUMBER) {
const char *s2 = (const char *)getstrtoken();
int nr = -1;
diff --git a/src/common/gamecode/xmlreport.c b/src/common/gamecode/xmlreport.c
index 237b4f6ce..5cef7feb0 100644
--- a/src/common/gamecode/xmlreport.c
+++ b/src/common/gamecode/xmlreport.c
@@ -352,7 +352,7 @@ xml_unit(report_context * ctx, unit * u, int mode)
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "true");
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "ref", xml_ref_faction(u->faction));
- if (fval(u, UFL_PARTEITARNUNG)) {
+ if (fval(u, UFL_ANON_FACTION)) {
const faction * sf = visible_faction(NULL, u);
child = xmlAddChild(node, xmlNewNode(xct->ns_atl, BAD_CAST "faction"));
xmlNewNsProp(child, xct->ns_atl, BAD_CAST "rel", BAD_CAST "stealth");
diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c
index b7a4b5518..9ecad26f3 100644
--- a/src/common/kernel/battle.c
+++ b/src/common/kernel/battle.c
@@ -3272,7 +3272,7 @@ make_fighter(battle * b, unit * u, side * s1, boolean attack)
unsigned int flags = 0;
assert(u->number);
- if (fval(u, UFL_PARTEITARNUNG)!=0) flags |= SIDE_STEALTH;
+ if (fval(u, UFL_ANON_FACTION)!=0) flags |= SIDE_STEALTH;
if (fval(u, UFL_GROUP)) {
const attrib * agroup = a_find(u->attribs, &at_group);
diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c
index db33fe40c..ab00c5fde 100644
--- a/src/common/kernel/eressea.c
+++ b/src/common/kernel/eressea.c
@@ -979,7 +979,7 @@ alliedunit(const unit * u, const faction * f2, int mode)
boolean
seefaction(const faction * f, const region * r, const unit * u, int modifier)
{
- if (((f == u->faction) || !fval(u, UFL_PARTEITARNUNG)) && cansee(f, r, u, modifier))
+ if (((f == u->faction) || !fval(u, UFL_ANON_FACTION)) && cansee(f, r, u, modifier))
return true;
return false;
}
@@ -2700,6 +2700,15 @@ cmp_current_owner(const building * b, const building * a)
return -1;
}
+int rule_stealth_faction(void)
+{
+ static int rule = -1;
+ if (rule<0) {
+ rule = get_param_int(global.parameters, "rules.stealth.faction", 1);
+ }
+ return rule;
+}
+
int rule_region_owners(void)
{
static int rule_owners = -1;
diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h
index b5fa7fa66..6d362257f 100644
--- a/src/common/kernel/eressea.h
+++ b/src/common/kernel/eressea.h
@@ -254,6 +254,7 @@ int cmp_current_owner(const struct building * b, const struct building * bother)
#define TAX_OWNER 0x01
int rule_auto_taxation(void);
int rule_region_owners(void);
+int rule_stealth_faction(void);
extern int count_all(const struct faction * f);
extern int count_migrants (const struct faction * f);
diff --git a/src/common/kernel/faction.c b/src/common/kernel/faction.c
index 71daafb31..a335f98ea 100644
--- a/src/common/kernel/faction.c
+++ b/src/common/kernel/faction.c
@@ -267,7 +267,6 @@ write_faction_reference(const faction * f, struct storage * store)
void
destroyfaction(faction * f)
{
- region *rc;
unit *u = f->units;
faction *ff;
@@ -353,13 +352,16 @@ destroyfaction(faction * f)
/* units of other factions that were disguised as this faction
* have their disguise replaced by ordinary faction hiding. */
- for (rc=regions; rc; rc=rc->next) {
- for(u=rc->units; u; u=u->next) {
- attrib *a = a_find(u->attribs, &at_otherfaction);
- if(!a) continue;
- if (get_otherfaction(a) == f) {
- a_removeall(&u->attribs, &at_otherfaction);
- fset(u, UFL_PARTEITARNUNG);
+ if (rule_stealth_faction()) {
+ region * rc;
+ for (rc=regions; rc; rc=rc->next) {
+ for(u=rc->units; u; u=u->next) {
+ attrib *a = a_find(u->attribs, &at_otherfaction);
+ if(!a) continue;
+ if (get_otherfaction(a) == f) {
+ a_removeall(&u->attribs, &at_otherfaction);
+ fset(u, UFL_ANON_FACTION);
+ }
}
}
}
diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c
index 37f0ae6dd..e9eea362f 100644
--- a/src/common/kernel/reports.c
+++ b/src/common/kernel/reports.c
@@ -424,7 +424,7 @@ int
bufunit(const faction * f, const unit * u, int indent, int mode, char * buf, size_t size)
{
int i, dh;
- int getarnt = fval(u, UFL_PARTEITARNUNG);
+ int getarnt = fval(u, UFL_ANON_FACTION);
const char *pzTmp, *str;
building * b;
boolean isbattle = (boolean)(mode == see_battle);
@@ -995,7 +995,7 @@ get_addresses(report_context * ctx)
if (u->faction!=ctx->f) {
faction * sf = visible_faction(ctx->f, u);
boolean ballied = sf && sf!=ctx->f && sf!=lastf
- && !fval(u, UFL_PARTEITARNUNG) && cansee(ctx->f, r, u, stealthmod);
+ && !fval(u, UFL_ANON_FACTION) && cansee(ctx->f, r, u, stealthmod);
if (ballied || ALLIED(ctx->f, sf)) {
add_faction(&flist, sf);
lastf = sf;
diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c
index bc3610451..d7feae64f 100644
--- a/src/common/kernel/save.c
+++ b/src/common/kernel/save.c
@@ -789,8 +789,13 @@ read_unit(struct storage * store)
guard(u, GUARD_NONE);
}
} else {
- u->flags = store->r_int(store) & ~UFL_DEBUG;
+ u->flags = store->r_int(store);
u->flags &= UFL_SAVEMASK;
+ if ((u->flags&UFL_ANON_FACTION) && !rule_stealth_faction()) {
+ /* if this rule is broken, then fix broken units */
+ u->flags -= UFL_ANON_FACTION;
+ log_warning(("%s was anonymous.\n", unitname(u)));
+ }
}
/* Persistente Befehle einlesen */
free_orders(&u->orders);
diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c
index bbcf22bd1..33a4860e9 100644
--- a/src/common/kernel/unit.c
+++ b/src/common/kernel/unit.c
@@ -1518,8 +1518,8 @@ create_unit(region * r, faction * f, int number, const struct race *urace, int i
}
/* Temps von parteigetarnten Einheiten sind wieder parteigetarnt */
- if (fval(creator, UFL_PARTEITARNUNG)) {
- fset(u, UFL_PARTEITARNUNG);
+ if (fval(creator, UFL_ANON_FACTION)) {
+ fset(u, UFL_ANON_FACTION);
}
/* Daemonentarnung */
set_racename(&u->attribs, get_racename(creator->attribs));
@@ -1543,8 +1543,6 @@ create_unit(region * r, faction * f, int number, const struct race *urace, int i
a = a_add(&u->attribs, a_new(&at_creator));
a->data.v = creator;
}
- /* Monster sind grundsätzlich parteigetarnt */
- if (f->no <= 0) fset(u, UFL_PARTEITARNUNG);
return u;
}
diff --git a/src/common/kernel/unit.h b/src/common/kernel/unit.h
index 95c1ce70a..52e072913 100644
--- a/src/common/kernel/unit.h
+++ b/src/common/kernel/unit.h
@@ -35,7 +35,7 @@ struct item;
#define UFL_ISNEW (1<<1) /* 2 */
#define UFL_LONGACTION (1<<2) /* 4 */
#define UFL_OWNER (1<<3) /* 8 */
-#define UFL_PARTEITARNUNG (1<<4) /* 16 */
+#define UFL_ANON_FACTION (1<<4) /* 16 */
#define UFL_DISBELIEVES (1<<5) /* 32 */
#define UFL_WARMTH (1<<6) /* 64 */
#define UFL_HERO (1<<7)
@@ -66,7 +66,7 @@ struct item;
#define UFL_GROUP (1<<28)
/* Flags, die gespeichert werden sollen: */
-#define UFL_SAVEMASK (UFL_DEFENDER|UFL_MOVED|UFL_NOAID|UFL_OWNER|UFL_PARTEITARNUNG|UFL_LOCKED|UFL_HUNGER|UFL_TAKEALL|UFL_GUARD|UFL_STEALTH|UFL_GROUP|UFL_HERO)
+#define UFL_SAVEMASK (UFL_DEFENDER|UFL_MOVED|UFL_NOAID|UFL_OWNER|UFL_ANON_FACTION|UFL_LOCKED|UFL_HUNGER|UFL_TAKEALL|UFL_GUARD|UFL_STEALTH|UFL_GROUP|UFL_HERO)
#define UNIT_MAXSIZE 50000
extern int maxheroes(const struct faction * f);
diff --git a/src/common/modules/arena.c b/src/common/modules/arena.c
index fc835bf35..f07a60047 100644
--- a/src/common/modules/arena.c
+++ b/src/common/modules/arena.c
@@ -156,7 +156,7 @@ enter_arena(unit * u, const item_type * itype, int amount, order * ord)
use_pooled(u, itype->rtype, GET_SLACK|GET_RESERVE, 1);
use_pooled(u, oldresourcetype[R_SILVER], GET_DEFAULT, fee);
set_money(u, 109);
- fset(u, UFL_PARTEITARNUNG);
+ fset(u, UFL_ANON_FACTION);
move_unit(u, start_region[rng_int() % 6], NULL);
return 0;
}
@@ -345,7 +345,7 @@ guardian_faction(plane * pl, int id)
set_string(&u->name, "Igjarjuks Auge");
set_item(u, I_RING_OF_INVISIBILITY, 1);
set_order(&u->thisorder, NULL);
- fset(u, UFL_PARTEITARNUNG);
+ fset(u, UFL_ANON_FACTION);
set_money(u, 1000);
}
}
diff --git a/src/common/spells/combatspells.c b/src/common/spells/combatspells.c
index fd5e2e39d..0d2b8d48e 100644
--- a/src/common/spells/combatspells.c
+++ b/src/common/spells/combatspells.c
@@ -783,8 +783,9 @@ sp_wolfhowl(fighter * fi, int level, double power, spell * sp)
set_level(u, SK_STAMINA, (int)(power/3));
u->hp = u->number * unit_max_hp(u);
- if (fval(mage, UFL_PARTEITARNUNG))
- fset(u, UFL_PARTEITARNUNG);
+ if (fval(mage, UFL_ANON_FACTION)) {
+ fset(u, UFL_ANON_FACTION);
+ }
a = a_new(&at_unitdissolve);
a->data.ca[0] = 0;
@@ -818,8 +819,9 @@ sp_shadowknights(fighter * fi, int level, double power, spell * sp)
u->hp = u->number * unit_max_hp(u);
- if (fval(mage, UFL_PARTEITARNUNG))
- fset(u, UFL_PARTEITARNUNG);
+ if (fval(mage, UFL_ANON_FACTION)) {
+ fset(u, UFL_ANON_FACTION);
+ }
a = a_new(&at_unitdissolve);
a->data.ca[0] = 0;
@@ -1625,8 +1627,8 @@ sp_undeadhero(fighter * fi, int level, double power, spell * sp)
setguard(u, GUARD_NONE);
/* inherit stealth from magician */
- if (fval(mage, UFL_PARTEITARNUNG)) {
- fset(u, UFL_PARTEITARNUNG);
+ if (fval(mage, UFL_ANON_FACTION)) {
+ fset(u, UFL_ANON_FACTION);
}
/* transfer dead people to new unit, set hitpoints to those of old unit */
diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c
index 12f538ed7..b6514b8db 100644
--- a/src/common/spells/spells.c
+++ b/src/common/spells/spells.c
@@ -2154,7 +2154,10 @@ sp_ironkeeper(castorder *co)
guard(keeper, GUARD_MINING);
fset(keeper, UFL_ISNEW);
/* Parteitarnen, damit man nicht sofort weiß, wer dahinter steckt */
- fset(keeper, UFL_PARTEITARNUNG);
+ if (rule_stealth_faction()) {
+ fset(keeper, UFL_ANON_FACTION);
+ }
+
{
trigger * tkill = trigger_killunit(keeper);
add_trigger(&keeper->attribs, "timer", trigger_timeout(cast_level+2, tkill));
@@ -3876,7 +3879,9 @@ sp_charmingsong(castorder *co)
/* setze Parteitarnung, damit nicht sofort klar ist, wer dahinter
* steckt */
- fset(target, UFL_PARTEITARNUNG);
+ if (rule_stealth_faction()) {
+ fset(target, UFL_ANON_FACTION);
+ }
ADDMSG(&mage->faction->msgs, msg_message("charming_effect", "mage unit duration", mage, target, duration));
@@ -4594,7 +4599,9 @@ sp_raisepeasants(castorder *co)
u2 = create_unit(r, mage->faction, bauern, new_race[RC_PEASANT], 0, LOC(mage->faction->locale, "furious_mob"), mage);
fset(u2, UFL_LOCKED);
- fset(u2, UFL_PARTEITARNUNG);
+ if (rule_stealth_faction()) {
+ fset(u2, UFL_ANON_FACTION);
+ }
a = a_new(&at_unitdissolve);
a->data.ca[0] = 1; /* An rpeasants(r). */
@@ -5859,7 +5866,7 @@ sp_showastral(castorder *co)
c++;
scat(unitname(u));
scat(" (");
- if (!fval(u, UFL_PARTEITARNUNG)) {
+ if (!fval(u, UFL_ANON_FACTION)) {
scat(factionname(u->faction));
scat(", ");
}
diff --git a/src/res/e3a.xml b/src/res/e3a.xml
index add95c752..f250e790f 100644
--- a/src/res/e3a.xml
+++ b/src/res/e3a.xml
@@ -140,6 +140,7 @@
+