diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index e323da435..e60b19715 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -583,6 +583,8 @@ givemen(int n, unit * u, unit * u2, const char * cmd) error = 73; } else if (u2 && (has_skill(u, SK_MAGIC) || has_skill(u2, SK_MAGIC))) { error = 158; + } else if (fval(u, UFL_WERE) != fval(u2, UFL_WERE)) { + error = 312; } else { if (n > u->number) n = u->number; if (n == 0) { @@ -3002,6 +3004,11 @@ entertain(region * r, unit * u) int max_e; request *o; + if (fval(u, UFL_WERE)) { + cmistake(u, findorder(u, u->thisorder), 58, MSG_INCOME); + return; + } + if (!effskill(u, SK_ENTERTAINMENT)) { cmistake(u, findorder(u, u->thisorder), 58, MSG_INCOME); return; @@ -3094,6 +3101,10 @@ work(region * r, unit * u) request *o; int w; + if(fval(u, UFL_WERE)) { + cmistake(u, findorder(u, u->thisorder), 313, MSG_INCOME); + return; + } if (besieged(u)) { cmistake(u, findorder(u, u->thisorder), 60, MSG_INCOME); return; @@ -3146,6 +3157,11 @@ tax(region * r, unit * u, request ** taxorders) cmistake(u, findorder(u, u->thisorder), 228, MSG_INCOME); return; } + + if (fval(u, UFL_WERE)) { + cmistake(u, findorder(u, u->thisorder), 228, MSG_INCOME); + return; + } if (besieged(u)) { cmistake(u, findorder(u, u->thisorder), 60, MSG_INCOME); diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 3b7265e2c..0a9a0f73d 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -2405,6 +2405,10 @@ instant_orders(void) setstealth(u, S); break; + case K_WEREWOLF: + setwere(u, S); + break; + case K_STATUS: param = getstrtoken(); switch (findparam(param, u->faction->locale)) { @@ -3126,6 +3130,7 @@ setdefaults (void) case K_WORK: case K_DRIVE: case K_MOVE: + case K_WEREWOLF: cmd = S->s; #if HUNGER_DISABLES_LONGORDERS if (fval(u, FL_HUNGER)) { @@ -3161,6 +3166,7 @@ setdefaults (void) case K_MOVE: case K_BIETE: case K_ATTACK: + case K_WEREWOLF: break; default: diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c index 4711f8ed1..f5b389d70 100644 --- a/src/common/gamecode/randenc.c +++ b/src/common/gamecode/randenc.c @@ -1044,6 +1044,7 @@ godcurse(void) void randomevents(void) { + faction *f; region *r; building *b, *b2; unit *u; @@ -1471,6 +1472,19 @@ randomevents(void) } } } + + for (f = factions; f; f=f->next) { + int level = fspecial(f, FS_LYCANTROPE); + if(level > 0) { + for(u = f->units; u; u=u->nextF) { + if(rand()%100 < 2*level) { + ADDMSG(&u->faction->msgs, msg_message("becomewere", + "unit region", u, u->region)); + fset(u, UFL_WERE); + } + } + } + } /* Frühling, die Bäume schlagen aus. */ diff --git a/src/common/gamecode/spy.c b/src/common/gamecode/spy.c index adaeea1dd..1682f5259 100644 --- a/src/common/gamecode/spy.c +++ b/src/common/gamecode/spy.c @@ -108,6 +108,45 @@ spy(region * r, unit * u) } } +void +setwere(unit *u, strlist *S) +{ + int level = fspecial(u->faction,FS_LYCANTROPE); + char *s; + + if(!level) { + cmistake(u, S->s, 311, MSG_EVENT); + return; + } + + s = getstrtoken(); + + if(s == NULL || *s == '\0') { + if(fval(u, UFL_WERE)) { + cmistake(u, S->s, 309, MSG_EVENT); + } else if(rand()%100 < 35+(level-1)*20) { /* 35, 55, 75, 95% */ + fset(u, UFL_WERE); + } else { + cmistake(u, S->s, 311, MSG_EVENT); + } + return; + } + + if(findparam(s, u->faction->locale) == P_NOT) { + if(fval(u, UFL_WERE)) { + cmistake(u, S->s, 310, MSG_EVENT); + } else if(rand()%100 < 90-level*20) { /* 70, 50, 30, 10% */ + freset(u, UFL_WERE); + } else { + cmistake(u, S->s, 311, MSG_EVENT); + } + + return; + } + + return; +} + void setstealth(unit * u, strlist * S) { @@ -125,7 +164,6 @@ setstealth(unit * u, strlist * S) return; } - trace = findrace(s, u->faction->locale); if (trace) { /* Dämonen können sich nur als andere Spielerrassen tarnen */ diff --git a/src/common/gamecode/study.c b/src/common/gamecode/study.c index 1c5afd284..4ff572be0 100644 --- a/src/common/gamecode/study.c +++ b/src/common/gamecode/study.c @@ -246,7 +246,7 @@ teach(region * r, unit * u) char *s; skill_t sk; - if ((u->race->flags & RCF_NOTEACH)) { + if ((u->race->flags & RCF_NOTEACH) || fval(u, UFL_WERE)) { cmistake(u, u->thisorder, 274, MSG_EVENT); return; } @@ -471,7 +471,7 @@ learn(void) cmistake(u, findorder(u, u->thisorder), 52, MSG_PRODUCE); continue; } - if ((u->race->flags & RCF_NOLEARN)) { + if ((u->race->flags & RCF_NOLEARN) || fval(u, UFL_WERE)) { sprintf(buf, "%s können nichts lernen", LOC(default_locale, rc_name(u->race, 1))); mistake(u, u->thisorder, buf, MSG_EVENT); continue; diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index ebef64f22..fdd625d82 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -773,9 +773,13 @@ select_armor(troop t) int geschuetzt = 0; /* Drachen benutzen keine Rüstungen */ - if (!(t.fighter->unit->race->battle_flags & BF_EQUIPMENT)) return AR_NONE; + + /* ... und Werwölfe auch nicht */ + if(fval(t.fighter->unit, UFL_WERE)) { + return AR_NONE; + } do { if (armordata[a].shield == 0) { @@ -1026,6 +1030,11 @@ terminate(troop dt, troop at, int type, const char *damage, boolean missile) ar += armordata[shield].prot; /* natürliche Rüstung */ an = du->race->armor; + if(fval(du, UFL_WERE)) { + int level = fspecial(du->faction, FS_LYCANTROPE); + an += level; + da += level; + } /* magische Rüstung durch Artefakte oder Sprüche */ /* Momentan nur Trollgürtel */ am = select_magicarmor(dt); @@ -1583,6 +1592,11 @@ skilldiff(troop at, troop dt, int dist) skdiff += 5; } + /* Werwolf */ + if(fval(au, UFL_WERE)) { + skdiff += fspecial(au->faction, FS_LYCANTROPE); + } + if (old_race(au->race) == RC_GOBLIN && af->side->size[SUM_ROW] >= df->side->size[SUM_ROW] * 10) skdiff += 1; @@ -2862,12 +2876,12 @@ make_fighter(battle * b, unit * u, boolean attack) if (fig->horses) { if ((r->terrain != T_PLAIN && r->terrain != T_HIGHLAND && r->terrain != T_DESERT) || r_isforest(r) - || eff_skill(u, SK_RIDING, r) < 2 || old_race(u->race) == RC_TROLL) + || eff_skill(u, SK_RIDING, r) < 2 || old_race(u->race) == RC_TROLL || fval(u, UFL_WERE)) fig->horses = 0; } if (fig->elvenhorses) { - if (eff_skill(u, SK_RIDING, r) < 5 || old_race(u->race) == RC_TROLL) + if (eff_skill(u, SK_RIDING, r) < 5 || old_race(u->race) == RC_TROLL || fval(u, UFL_WERE)) fig->elvenhorses = 0; } diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index 983b54e1c..3e35f4ebb 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -231,9 +231,8 @@ const char *keywords[MAXKEYWORDS] = #endif "PRÄFIX", "SYNONYM", -#if GROWING_TREES "PFLANZEN", -#endif + "WERWESEN" }; const char *report_options[MAX_MSG] = diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index 7c80c5c8e..37489b19e 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -438,6 +438,7 @@ enum { K_PREFIX, K_SYNONYM, K_PFLANZE, + K_WEREWOLF, MAXKEYWORDS, NOKEYWORD = (keyword_t) - 1 }; @@ -891,6 +892,8 @@ extern int max_unique_id; #define FFL_RESTART (1<<2) #define FFL_OVERRIDE (1<<27) /* Override-Passwort wurde benutzt */ +#define UFL_WERE (1<<28) + /* Flags, die gespeichert werden sollen: */ #define UFL_SAVEMASK (FL_NOAID | FL_OWNER | FL_PARTEITARNUNG | FL_LOCKED | FL_HUNGER | FL_NOIDLEOUT | FL_TAKEALL | FL_UNNAMED) diff --git a/src/common/kernel/karma.c b/src/common/kernel/karma.c index 469b66ee6..7b8e3cbe3 100644 --- a/src/common/kernel/karma.c +++ b/src/common/kernel/karma.c @@ -274,20 +274,21 @@ struct fspecialdata fspecials[MAXFACTIONSPECIALS] = { "Auswirkungen.", 100 }, - /* TODO: Noch nicht implementiert */ { "Lykanthrop", "Angehörige einer Partei mit dieser Eigenschaft sind Werwesen. Einheiten " - "einer solchen Partei können sich mit Hilfe der Befehle 'WERWESEN' und " + "einer solchen Partei können sich mit Hilfe der langen Befehle 'WERWESEN' und " "'WERWESEN NICHT' in eine andere Form verwandeln. Beide Befehle haben " - "nur eine gewisse Erfolgswahrscheinlichkeit und funktionieren nicht immer. " - "In Werform erhalten die Einheiten +2 auf Angriff und Schaden und " - "eine natürliche Rüstung von 2. Sie können sich so schnell " - "bewegen, als wäre sie beritten, benutzen aber keine Pferde im " - "Kampf, und verwenden als Rüstungen nur Schilde. Sie sind " - "eingeschränkt und können in Werform kein Geld verdienen " - "und nicht Lernen oder Lehren.", - 1 + "nur eine gewisse Erfolgswahrscheinlichkeit und funktionieren nicht immer: " + "Je höher die Stufe der Eigenschaft, desto größer die Wahrscheinlichkeit, " + "dass die Verwandlung gelingt, und je geringer die Chance, sich " + "zurückzuverwandeln. Zudem besteht eine zunehmende kleine Chance der " + "spontanen Verwandlung. In Werform erhalten die Einheiten einen Bonus auf " + "Angriff, Schaden und natürliche Rüstung in Höhe der Eigenschaft. Sie " + "benutzen jedoch keine Pferde im Kampf, und verwenden als Rüstungen nur " + "Schilde. Sie sind eingeschränkt und können in Werform kein Geld verdienen, " + "nicht Zaubern und nicht Lernen oder Lehren.", + 4 }, /* TODO: Noch nicht implementiert */ /* Einheitenlimit-Senkung sinnlos für alte Parteien. */ @@ -295,7 +296,9 @@ struct fspecialdata fspecials[MAXFACTIONSPECIALS] = { "Elite", "Für eine Partei mit dieser Eigenschaft verdoppeln sich alle Boni- und " "Mali ihrer Rasse. Ihre Unterhaltskosten erhöhen sich auf 12 Silber pro " - "Runde, ihr Einheitenlimit reduziert sich auf 25%%.", + "Runde, ihr Einheitenlimit reduziert sich auf 25%%. Diese Eigenschaft " + "kann nicht erworben werden, wenn die Partei nach dem Erwerb zuviele " + "Einheiten hätte.", 1 } }; diff --git a/src/common/kernel/karma.h b/src/common/kernel/karma.h index 836f84326..e41b7c31a 100644 --- a/src/common/kernel/karma.h +++ b/src/common/kernel/karma.h @@ -36,7 +36,7 @@ typedef enum { FS_UNDEAD, FS_QUICK, FS_LUCKY, - FS_LYCANTROP, + FS_LYCANTROPE, FS_ELITE, MAXFACTIONSPECIALS } fspecial_t; diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c index ff8214f40..d57c896a8 100644 --- a/src/common/kernel/magic.c +++ b/src/common/kernel/magic.c @@ -2888,6 +2888,10 @@ magic(void) !is_cursed(u->attribs, C_KAELTESCHUTZ,0)) continue; + if(fval(u, UFL_WERE)) { + continue; + } + if (attacked(u)) { continue; } diff --git a/src/common/kernel/spy.h b/src/common/kernel/spy.h index 9b17e28a6..e6ce4d87c 100644 --- a/src/common/kernel/spy.h +++ b/src/common/kernel/spy.h @@ -26,6 +26,7 @@ struct unit; struct region; struct strlist; +void setwere(struct unit * u, struct strlist * S); void setstealth(struct unit * u, struct strlist * S); void spy(struct region * r, struct unit * u); void sabotage(struct region * r, struct unit * u); diff --git a/src/res/de/messages.xml b/src/res/de/messages.xml index e992c1a47..881182329 100644 --- a/src/res/de/messages.xml +++ b/src/res/de/messages.xml @@ -4340,6 +4340,96 @@ + + + + + + + + + + "$unit($unit) in $region($region): '$command' - Diese Einheit ist schon ein Werwesen." + + + + + "$unit($unit) in $region($region): '$command' - This unit already assumed lycantropic form." + + + + + + + + + + + + + "$unit($unit) in $region($region): '$command' - Diese Einheit ist kein Werwesen." + + + + + "$unit($unit) in $region($region): '$command' - This unit is not in lycantropic form." + + + + + + + + + + + + + "$unit($unit) in $region($region): '$command' - Die Einheit kann sich nicht verwandeln." + + + + + "$unit($unit) in $region($region): '$command' - This unit can not change shape." + + + + + + + + + + + + + "$unit($unit) in $region($region): '$command' - Werwesen können nicht mit anderen Personen gemischt werden." + + + + + "$unit($unit) in $region($region): '$command' - Lycantropes may not be mixed with normal people." + + + + + + + + + + + + + "$unit($unit) in $region($region): '$command' - Werwesen können nicht arbeiten." + + + + + "$unit($unit) in $region($region): '$command' - Lycantropes don't work." + + + @@ -7366,5 +7456,15 @@ "SIEG! $if($eq($n,1), "Die Partei $winners hat", "Die Parteien $winners haben") die Siegbedingung für die erforderliche Zeit erfüllt. Das Spiel ist damit beendet." "VICTORY! $if($eq($n,1), "The faction $winners has", "The factions $winners have") fulfilled the victory condition for the necessary time. The game is over." + + + + + + + "$unit($unit) in $region($region) verwandelt sich in ein Werwesen." + "$unit($unit) in $region($region) becomes a lycantrope." + + diff --git a/src/res/de/strings.xml b/src/res/de/strings.xml index c0a3e5f55..bc48ef316 100644 --- a/src/res/de/strings.xml +++ b/src/res/de/strings.xml @@ -1780,7 +1780,9 @@ GM - + + WERWESEN + Adler diff --git a/src/res/en/strings.xml b/src/res/en/strings.xml index f206fa301..5a7d70965 100644 --- a/src/res/en/strings.xml +++ b/src/res/en/strings.xml @@ -1593,6 +1593,9 @@ GROW + + LYCANTROPE + eagle