New rules, with defines

This commit is contained in:
Enno Rehling 2004-08-03 15:34:26 +00:00
parent 73cda7a160
commit cd4fc9e2bc
22 changed files with 271 additions and 129 deletions

View File

@ -729,16 +729,25 @@ cr_output_unit(FILE * F, const region * r,
fputs("1;unaided\n", F); fputs("1;unaided\n", F);
} }
i = u_geteffstealth(u); i = u_geteffstealth(u);
if (i >= 0) if (i >= 0) {
fprintf(F, "%d;Tarnung\n", i); fprintf(F, "%d;Tarnung\n", i);
}
c = uprivate(u); c = uprivate(u);
if (c) if (c) {
fprintf(F, "\"%s\";privat\n", c); fprintf(F, "\"%s\";privat\n", c);
}
c = hp_status(u); c = hp_status(u);
if (c && *c && (u->faction == f || omniscient(f))) if (c && *c && (u->faction == f || omniscient(f))) {
fprintf(F, "\"%s\";hp\n", add_translation(c, locale_string(u->faction->locale, c))); fprintf(F, "\"%s\";hp\n", add_translation(c, locale_string(u->faction->locale, c)));
if (fval(u, UFL_HUNGER) && (u->faction == f)) }
#ifdef HEROES
if (fval(u, UFL_HERO)) {
fputs("1;hero\n", F);
}
#endif
if (fval(u, UFL_HUNGER) && (u->faction == f)) {
fputs("1;hunger\n", F); fputs("1;hunger\n", F);
}
if (is_mage(u)) { if (is_mage(u)) {
fprintf(F, "%d;Aura\n", get_spellpoints(u)); fprintf(F, "%d;Aura\n", get_spellpoints(u));
fprintf(F, "%d;Auramax\n", max_spellpoints(u->region,u)); fprintf(F, "%d;Auramax\n", max_spellpoints(u->region,u));

View File

@ -2444,6 +2444,36 @@ reshow(unit * u, struct order * ord, const char * s, param_t p)
} }
} }
#ifdef HEROES
static int
promote_cmd(unit * u, struct order * ord)
{
int money, people;
if (maxheroes(u->faction) < countheroes(u->faction)+u->number) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_maxed", "max count",
maxheroes(u->faction), countheroes(u->faction)));
return 0;
}
if (!playerrace(u->race)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_race", "race",
u->race));
return 0;
}
money = get_all(u, i_silver->rtype);
people = count_all(u->faction) * u->number;
if (people>money) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_cost", "cost have",
people, money));
return 0;
}
use_all(u, i_silver->rtype, people);
fset(u, UFL_HERO);
return 0;
}
#endif
static int static int
group_cmd(unit * u, struct order * ord) group_cmd(unit * u, struct order * ord)
{ {
@ -3320,7 +3350,7 @@ setdefaults (void)
order *ord; order *ord;
boolean trade = false; boolean trade = false;
if (LongHunger() && fval(u, UFL_HUNGER)) { if (LongHunger(u)) {
/* Hungernde Einheiten führen NUR den default-Befehl aus */ /* Hungernde Einheiten führen NUR den default-Befehl aus */
set_order(&u->thisorder, default_order(u->faction->locale)); set_order(&u->thisorder, default_order(u->faction->locale));
continue; continue;
@ -3465,27 +3495,17 @@ use_item(unit * u, const item_type * itype, int amount, struct order * ord)
} }
static int static double
canheal(const unit *u) heal_factor(const race *rc)
{ {
switch(old_race(u->race)) { switch(old_race(rc)) {
case RC_DAEMON: case RC_TROLL:
return 15; case RC_DAEMON:
break; return 1.5;
case RC_GOBLIN: case RC_GOBLIN:
return 20; return 2.0;
break;
case RC_TROLL:
return 15;
break;
case RC_FIREDRAGON:
case RC_DRAGON:
case RC_WYRM:
return 10;
break;
} }
if (u->race->flags & RCF_NOHEAL) return 0; return 1.0;
return 10;
} }
static void static void
@ -3508,55 +3528,53 @@ monthly_healing(void)
} }
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
int umhp = unit_max_hp(u) * u->number; int umhp = unit_max_hp(u) * u->number;
int p; double p = 1.0;
/* hp über Maximum bauen sich ab. Wird zb durch Elixier der Macht /* hp über Maximum bauen sich ab. Wird zb durch Elixier der Macht
* oder verändertes Ausdauertalent verursacht */ * oder verändertes Ausdauertalent verursacht */
if (u->hp > umhp) { if (u->hp > umhp) {
u->hp -= (int) ceil((u->hp - umhp) / 2.0); u->hp -= (int) ceil((u->hp - umhp) / 2.0);
if (u->hp < umhp) if (u->hp < umhp) u->hp = umhp;
u->hp = umhp; continue;
} }
if((u->race->flags & RCF_NOHEAL) || fval(u, UFL_HUNGER) || fspecial(u->faction, FS_UNDEAD)) if (u->race->flags & RCF_NOHEAL) continue;
continue; if (fval(u, UFL_HUNGER)) continue;
if (fspecial(u->faction, FS_UNDEAD)) continue;
if(rterrain(r) == T_OCEAN && !u->ship && !(canswim(u))) if (rterrain(r)==T_OCEAN && u->ship==NULL && !canswim(u)) continue;
continue;
if(fspecial(u->faction, FS_REGENERATION)) { if(fspecial(u->faction, FS_REGENERATION)) {
u->hp = umhp; u->hp = umhp;
continue; continue;
} }
p = canheal(u); p *= heal_factor(u->race);
if (u->hp < umhp && p > 0) { if (u->hp < umhp) {
/* Mind 1 HP wird pro Runde geheilt, weil angenommen wird, #ifdef NEW_DAEMONHUNGER_RULE
das alle Personen mind. 10 HP haben. */ double maxheal = max(u->number, umhp/20.0);
int max_unit = max(umhp, u->number * 10); #else
#ifdef NEW_TAVERN double maxheal = max(u->number, umhp/10.0);
#endif
int addhp;
struct building * b = inside_building(u); struct building * b = inside_building(u);
const struct building_type * btype = b?b->type:NULL; const struct building_type * btype = b?b->type:NULL;
if (btype == bt_find("inn")) { if (btype == bt_find("inn")) {
max_unit = max_unit * 3 / 2; p *= 1.5;
}
#endif
/* der healing curse verändert den Regenerationsprozentsatz.
* Wenn dies für negative Heilung benutzt wird, kann es zu
* negativen u->hp führen! */
if (healingcurse != 0) {
p += healingcurse;
} }
/* pro punkt 5% höher */
p *= (1.0 + healingcurse * 0.05);
maxheal = p * maxheal;
addhp = (int)maxheal;
maxheal -= addhp;
if (maxheal>0.0 && chance(maxheal)) ++addhp;
/* Aufaddieren der geheilten HP. */ /* Aufaddieren der geheilten HP. */
u->hp = min(u->hp + max_unit*p/100, umhp); u->hp = min(u->hp + addhp, umhp);
if (u->hp < umhp && (rand() % 10 < max_unit % 10)){
++u->hp;
}
/* soll man an negativer regeneration sterben können? */ /* soll man an negativer regeneration sterben können? */
if (u->hp <= 0){ assert(u->hp > 0);
u->hp = 1;
}
} }
} }
} }
@ -3807,6 +3825,12 @@ processorders (void)
puts(" - Krieg & Frieden"); puts(" - Krieg & Frieden");
declare_war(); declare_war();
#endif #endif
#ifdef HEROES
puts(" - Heldenbeförderung");
parse(K_PROMOTION, promote_cmd, false);
#endif
puts(" - Neue Nummern"); puts(" - Neue Nummern");
renumber(); renumber();

View File

@ -55,8 +55,6 @@
#define STANDARD_LUCK 0 #define STANDARD_LUCK 0
extern struct item_type *i_silver;
static void static void
lucky_silver(const unit *u) lucky_silver(const unit *u)
{ {

View File

@ -20,7 +20,7 @@
*/ */
#define TEACH_ALL 1 #define TEACH_ALL 1
#define TEACH_FRIENDS 1 #define TEACH_FRIENDS
#include <config.h> #include <config.h>
#include "eressea.h" #include "eressea.h"
@ -293,7 +293,12 @@ teach(unit * u, struct order * ord)
teachskill[i++]=sk; teachskill[i++]=sk;
} while (sk!=NOSKILL); } while (sk!=NOSKILL);
while (teaching && student) { while (teaching && student) {
if (student->faction == u->faction && !fval(student, UFL_HUNGER)) { if (student->faction == u->faction) {
#ifdef NEW_DAEMONHUNGER_RULE
if (LongHunger(student)) continue;
#else
if (fval(student, UFL_HUNGER)) continue;
#endif
if (get_keyword(student->thisorder) == K_STUDY) { if (get_keyword(student->thisorder) == K_STUDY) {
/* Input ist nun von student->thisorder !! */ /* Input ist nun von student->thisorder !! */
init_tokens(student->thisorder); init_tokens(student->thisorder);
@ -310,9 +315,14 @@ teach(unit * u, struct order * ord)
} }
student = student->next; student = student->next;
} }
#if TEACH_FRIENDS #ifdef TEACH_FRIENDS
while (teaching && student) { while (teaching && student) {
if (student->faction != u->faction && !fval(student, UFL_HUNGER) && alliedunit(u, student->faction, HELP_GUARD)) { if (student->faction != u->faction && alliedunit(u, student->faction, HELP_GUARD)) {
#ifdef NEW_DAEMONHUNGER_RULE
if (LongHunger(student)) continue;
#else
if (fval(student, UFL_HUNGER)) continue;
#endif
if (get_keyword(student->thisorder) == K_STUDY) { if (get_keyword(student->thisorder) == K_STUDY) {
/* Input ist nun von student->thisorder !! */ /* Input ist nun von student->thisorder !! */
init_tokens(student->thisorder); init_tokens(student->thisorder);
@ -699,7 +709,7 @@ learn(void)
days *= 2; days *= 2;
} }
if (fval(u, UFL_HUNGER)) days = days / 2; if (fval(u, UFL_HUNGER)) days /= 2;
while (days) { while (days) {
if (days>=u->number*30) { if (days>=u->number*30) {

View File

@ -19,9 +19,14 @@
#define CATAPULT_INITIAL_RELOAD 4 /* erster schuss in runde 1 + rand() % INITIAL */ #define CATAPULT_INITIAL_RELOAD 4 /* erster schuss in runde 1 + rand() % INITIAL */
#define CATAPULT_STRUCTURAL_DAMAGE #define CATAPULT_STRUCTURAL_DAMAGE
#define BASE_CHANCE 70 /* 70% Überlebenschance */ #define BASE_CHANCE 70 /* 70% Basis-Überlebenschance */
#ifdef NEW_COMBATSKILLS_RULE
#define TDIFF_CHANGE 5 /* 5% höher pro Stufe */
#define DAMAGE_QUOTIENT 2 /* damage += skilldiff/DAMAGE_QUOTIENT */
#else
#define TDIFF_CHANGE 10 #define TDIFF_CHANGE 10
# define DAMAGE_QUOTIENT 1 /* damage += skilldiff/DAMAGE_QUOTIENT */
#endif
typedef enum combatmagic { typedef enum combatmagic {
DO_PRECOMBATSPELL, DO_PRECOMBATSPELL,
@ -107,16 +112,12 @@ static int obs_count = 0;
#define MINSPELLRANGE 1 #define MINSPELLRANGE 1
#define MAXSPELLRANGE 7 #define MAXSPELLRANGE 7
#ifndef ROW_FACTOR
# define ROW_FACTOR 10
#endif
static const double EFFECT_PANIC_SPELL = 0.25; static const double EFFECT_PANIC_SPELL = 0.25;
static const double TROLL_REGENERATION = 0.10; static const double TROLL_REGENERATION = 0.10;
#define MAX_ADVANTAGE 5
enum {
SI_DEFENDER,
SI_ATTACKER
};
extern weapon_type * oldweapontype[]; extern weapon_type * oldweapontype[];
/* Nach dem alten System: */ /* Nach dem alten System: */
@ -516,7 +517,7 @@ get_unitrow(const fighter * af)
if (enemyfront) { if (enemyfront) {
for (line=FIRST_ROW;line!=NUMROWS;++line) { for (line=FIRST_ROW;line!=NUMROWS;++line) {
front += size[line]; front += size[line];
if (!front || front<enemyfront/10) ++retreat; if (!front || front<enemyfront/ROW_FACTOR) ++retreat;
else if (front) break; else if (front) break;
} }
} }
@ -568,21 +569,11 @@ contest(int skilldiff, armor_t ar, armor_t sh)
int p, vw = BASE_CHANCE - TDIFF_CHANGE * skilldiff; int p, vw = BASE_CHANCE - TDIFF_CHANGE * skilldiff;
double mod = 1.0; double mod = 1.0;
/* Hardcodet, muß geändert werden. */
#ifdef OLD_ARMOR
if (ar != AR_NONE)
mod *= (1 - armordata[ar].penalty);
if (sh != AR_NONE)
mod *= (1 - armordata[sh].penalty);
vw = (int) (vw * mod);
#else
if (ar != AR_NONE) if (ar != AR_NONE)
mod *= (1 + armordata[ar].penalty); mod *= (1 + armordata[ar].penalty);
if (sh != AR_NONE) if (sh != AR_NONE)
mod *= (1 + armordata[sh].penalty); mod *= (1 + armordata[sh].penalty);
vw = (int)(100 - ((100 - vw) * mod)); vw = (int)(100 - ((100 - vw) * mod));
#endif
do { do {
p = rand() % 100; p = rand() % 100;
@ -1098,7 +1089,7 @@ terminate(troop dt, troop at, int type, const char *damage, boolean missile)
} }
/* Skilldifferenzbonus */ /* Skilldifferenzbonus */
da += max(0, sk-sd); da += max(0, (sk-sd)/DAMAGE_QUOTIENT);
} }
@ -1182,7 +1173,7 @@ terminate(troop dt, troop at, int type, const char *damage, boolean missile)
#ifdef TODO_RUNESWORD #ifdef TODO_RUNESWORD
if (select_weapon(dt, 0, -1) == WP_RUNESWORD) continue; if (select_weapon(dt, 0, -1) == WP_RUNESWORD) continue;
#endif #endif
if (!(df->person[dt.index].flags & FL_HERO)) { if (!(df->person[dt.index].flags & FL_COURAGE)) {
df->person[dt.index].flags |= FL_DAZZLED; df->person[dt.index].flags |= FL_DAZZLED;
df->person[dt.index].defence--; df->person[dt.index].defence--;
} }
@ -1897,7 +1888,7 @@ dazzle(battle *b, troop *td)
return; return;
} }
#endif #endif
if (td->fighter->person[td->index].flags & FL_HERO) { if (td->fighter->person[td->index].flags & FL_COURAGE) {
#ifdef SMALL_BATTLE_MESSAGES #ifdef SMALL_BATTLE_MESSAGES
if (b->small) { if (b->small) {
sprintf(smallbuf, "Eine kurze Schwäche erfaßt %s/%d, vergeht jedoch " sprintf(smallbuf, "Eine kurze Schwäche erfaßt %s/%d, vergeht jedoch "
@ -1964,6 +1955,29 @@ attacks_per_round(troop t)
return t.fighter->person[t.index].speed; return t.fighter->person[t.index].speed;
} }
#ifdef HEROES
#define HERO_SPEED 10
static void
make_heroes(battle * b)
{
side * s;
cv_foreach(s, b->sides) {
fighter * fig;
cv_foreach(fig, s->fighters) {
unit * u = fig->unit;
if (fval(u, UFL_HERO)) {
int i;
assert(playerrace(u->race));
for (i=0;i!=u->number;++i) {
fig->person[i].speed += (HERO_SPEED-1);
}
}
} cv_next(fig);
} cv_next(s);
}
#endif
static void static void
attack(battle *b, troop ta, const att *a) attack(battle *b, troop ta, const att *a)
{ {
@ -2148,8 +2162,6 @@ do_attack(fighter * af)
unit *au = af->unit; unit *au = af->unit;
side *side = af->side; side *side = af->side;
battle *b = side->battle; battle *b = side->battle;
int apr;
int a;
ta.fighter = af; ta.fighter = af;
@ -2165,11 +2177,21 @@ do_attack(fighter * af)
/* Wir suchen eine beliebige Feind-Einheit aus. An der können /* Wir suchen eine beliebige Feind-Einheit aus. An der können
* wir feststellen, ob noch jemand da ist. */ * wir feststellen, ob noch jemand da ist. */
int enemies = count_enemies(b, af->side, FIGHT_ROW, LAST_ROW); int enemies = count_enemies(b, af->side, FIGHT_ROW, LAST_ROW);
int apr, attacks = attacks_per_round(ta);
if (!enemies) break; if (!enemies) break;
for (apr=attacks_per_round(ta); apr > 0; apr--) { for (apr=0;apr!=attacks;++apr) {
for (a=0; a!=10; ++a) { int a;
if (au->race->attack[a].type != AT_NONE) for (a=0; a!=10 && au->race->attack[a].type!=AT_NONE; ++a) {
if (apr>0) {
/* Wenn die Waffe nachladen muss, oder es sich nicht um einen
* Waffen-Angriff handelt, dann gilt der Speed nicht. */
if (au->race->attack[a].type!=AT_STANDARD) continue;
else {
weapon * wp = preferred_weapon(ta, true);
if (wp->type->reload) continue;
}
}
attack(b, ta, &(au->race->attack[a])); attack(b, ta, &(au->race->attack[a]));
} }
} }
@ -2926,7 +2948,7 @@ make_fighter(battle * b, unit * u, side * s1, boolean attack)
fig->person[i].defence++; fig->person[i].defence++;
fig->person[i].damage++; fig->person[i].damage++;
fig->person[i].damage_rear++; fig->person[i].damage_rear++;
fig->person[i].flags |= FL_HERO; fig->person[i].flags |= FL_COURAGE;
} }
/* Leute mit Kraftzauber machen +2 Schaden im Nahkampf. */ /* Leute mit Kraftzauber machen +2 Schaden im Nahkampf. */
if (i < strongmen) { if (i < strongmen) {
@ -3053,7 +3075,7 @@ make_fighter(battle * b, unit * u, side * s1, boolean attack)
if (t > 0 && get_unitrow(fig) > BEHIND_ROW) if (t > 0 && get_unitrow(fig) > BEHIND_ROW)
t -= 1; t -= 1;
#endif #endif
#if TACTICS_RANDOM #ifdef TACTICS_RANDOM
if (t > 0) { if (t > 0) {
int bonus = 0; int bonus = 0;
@ -3074,9 +3096,6 @@ make_fighter(battle * b, unit * u, side * s1, boolean attack)
} }
t += bonus; t += bonus;
} }
/* Nicht gut, da nicht personenbezogen. */
/* if (t > 0) t += rand() % TACTICS_RANDOM; */
/* statt +/- 2 kann man auch random(5) nehmen */
#endif #endif
add_tactics(&fig->side->leader, fig, t); add_tactics(&fig->side->leader, fig, t);
return fig; return fig;
@ -3393,8 +3412,6 @@ join_allies(battle * b)
} }
} }
extern struct item_type * i_silver;
static void static void
flee(const troop dt) flee(const troop dt)
{ {
@ -3503,7 +3520,7 @@ init_battle(region * r, battle **bp)
msg_message("no_attack_after_advance", "unit region command", u, u->region, ord)); msg_message("no_attack_after_advance", "unit region command", u, u->region, ord));
} }
#endif #endif
if (fval(u, UFL_HUNGER)) { if (LongHunger(u)) {
cmistake(u, ord, 225, MSG_BATTLE); cmistake(u, ord, 225, MSG_BATTLE);
continue; continue;
} }
@ -3708,7 +3725,9 @@ do_battle(void)
continue; continue;
} }
join_allies(b); join_allies(b);
#ifdef HEROES
make_heroes(b);
#endif
/* Alle Mann raus aus der Burg! */ /* Alle Mann raus aus der Burg! */
for (bu=r->buildings; bu!=NULL; bu=bu->next) bu->sizeleft = bu->size; for (bu=r->buildings; bu!=NULL; bu=bu->next) bu->sizeleft = bu->size;
@ -3802,7 +3821,7 @@ do_battle(void)
if ((u->status == ST_FLEE if ((u->status == ST_FLEE
|| (b->turn>1 && fig->person[dt.index].hp <= runhp) || (b->turn>1 && fig->person[dt.index].hp <= runhp)
|| (fig->person[dt.index].flags & FL_PANICED)) || (fig->person[dt.index].flags & FL_PANICED))
&& !(fig->person[dt.index].flags & FL_HERO)) && !(fig->person[dt.index].flags & FL_COURAGE))
{ {
double ispaniced = 0.0; double ispaniced = 0.0;
if (fig->person[dt.index].flags & FL_PANICED) { if (fig->person[dt.index].flags & FL_PANICED) {

View File

@ -105,7 +105,7 @@ extern "C" {
#define FL_TIRED 1 #define FL_TIRED 1
#define FL_DAZZLED 2 /* durch Untote oder Dämonen eingeschüchtert */ #define FL_DAZZLED 2 /* durch Untote oder Dämonen eingeschüchtert */
#define FL_PANICED 4 #define FL_PANICED 4
#define FL_HERO 8 /* Helden fliehen nie */ #define FL_COURAGE 8 /* Helden fliehen nie */
#define FL_SLEEPING 16 #define FL_SLEEPING 16
#define FL_STUNNED 32 /* eine Runde keinen Angriff */ #define FL_STUNNED 32 /* eine Runde keinen Angriff */
@ -162,7 +162,7 @@ extern "C" {
int speed : 8; /* (Magie) Geschwindigkeitsmultiplkator. */ int speed : 8; /* (Magie) Geschwindigkeitsmultiplkator. */
int reload : 4; /* Anzahl Runden, die die Waffe x noch laden muss. int reload : 4; /* Anzahl Runden, die die Waffe x noch laden muss.
* dahinter steckt ein array[RL_MAX] wenn er min. eine hat. */ * dahinter steckt ein array[RL_MAX] wenn er min. eine hat. */
int last_action : 8; /* In welcher Runde haben wir zuletzt etwas getan */ int last_action : 4; /* In welcher Runde haben wir zuletzt etwas getan */
struct weapon * missile; /* missile weapon */ struct weapon * missile; /* missile weapon */
struct weapon * melee; /* melee weapon */ struct weapon * melee; /* melee weapon */
#undef FIXED_OPPONENTS #undef FIXED_OPPONENTS

View File

@ -62,7 +62,6 @@
#include <items/catapultammo.h> #include <items/catapultammo.h>
#define NEW_TAVERN
#define STONERECYCLE 50 #define STONERECYCLE 50
/* Name, MaxGroesse, MinBauTalent, Kapazitaet, {Eisen, Holz, Stein, BauSilber, /* Name, MaxGroesse, MinBauTalent, Kapazitaet, {Eisen, Holz, Stein, BauSilber,
* Laen, Mallorn}, UnterSilber, UnterSpezialTyp, UnterSpezial */ * Laen, Mallorn}, UnterSilber, UnterSpezialTyp, UnterSpezial */

View File

@ -1025,7 +1025,7 @@ sp_flee(fighter * fi, int level, double power, spell * sp)
df->person[n].attack -= 1; df->person[n].attack -= 1;
--force; --force;
++panik; ++panik;
} else if (!(df->person[n].flags & FL_HERO) } else if (!(df->person[n].flags & FL_COURAGE)
|| !fval(df->unit->race, RCF_UNDEAD)) || !fval(df->unit->race, RCF_UNDEAD))
{ {
if (is_magic_resistant(mage, df->unit, 0) == false) { if (is_magic_resistant(mage, df->unit, 0) == false) {
@ -1085,9 +1085,9 @@ sp_hero(fighter * fi, int level, double power, spell * sp)
--allies; --allies;
if (df) { if (df) {
if (!(df->person[dt.index].flags & FL_HERO)) { if (!(df->person[dt.index].flags & FL_COURAGE)) {
df->person[dt.index].defence += df_bonus; df->person[dt.index].defence += df_bonus;
df->person[dt.index].flags = df->person[dt.index].flags | FL_HERO; df->person[dt.index].flags = df->person[dt.index].flags | FL_COURAGE;
targets++; targets++;
--force; --force;
} }
@ -1145,10 +1145,10 @@ sp_berserk(fighter * fi, int level, double power, spell * sp)
--allies; --allies;
if (df) { if (df) {
if (!(df->person[dt.index].flags & FL_HERO)) { if (!(df->person[dt.index].flags & FL_COURAGE)) {
df->person[dt.index].attack += at_bonus; df->person[dt.index].attack += at_bonus;
df->person[dt.index].defence -= df_malus; df->person[dt.index].defence -= df_malus;
df->person[dt.index].flags = df->person[dt.index].flags | FL_HERO; df->person[dt.index].flags = df->person[dt.index].flags | FL_COURAGE;
targets++; targets++;
--force; --force;
} }
@ -1202,8 +1202,8 @@ sp_frighten(fighter * fi, int level, double power, spell * sp)
assert(!helping(fi->side, df->side)); assert(!helping(fi->side, df->side));
if (df->person[dt.index].flags & FL_HERO) { if (df->person[dt.index].flags & FL_COURAGE) {
df->person[dt.index].flags &= ~(FL_HERO); df->person[dt.index].flags &= ~(FL_COURAGE);
} }
if (is_magic_resistant(mage, df->unit, 0) == false) { if (is_magic_resistant(mage, df->unit, 0) == false) {
df->person[dt.index].attack -= at_malus; df->person[dt.index].attack -= at_malus;

View File

@ -194,8 +194,14 @@ FirstTurn(void)
} }
int int
LongHunger(void) { LongHunger(const struct unit * u) {
static int value = -1; static int value = -1;
if (u!=NULL) {
if (!fval(u, UFL_HUNGER)) return false;
#ifdef NEW_DAEMONHUNGER_RULE
if (u->race==new_race[RC_DAEMON]) return false;
#endif
}
if (value<0) { if (value<0) {
const char * str = get_param(global.parameters, "hunger.long"); const char * str = get_param(global.parameters, "hunger.long");
value = str?atoi(str):0; value = str?atoi(str):0;
@ -399,7 +405,8 @@ const char *keywords[MAXKEYWORDS] =
"PFLANZEN", "PFLANZEN",
"WERWESEN", "WERWESEN",
"XONTORMIA", "XONTORMIA",
"ALLIANZ" "ALLIANZ",
"PROMOTION"
}; };
const char *report_options[MAX_MSG] = const char *report_options[MAX_MSG] =
@ -923,7 +930,7 @@ autoalliance(const plane * pl, const faction * sf, const faction * f2)
} }
} }
if (sf->alliance && AllianceAuto()) { if (sf->alliance!=NULL && AllianceAuto()) {
if (sf->alliance==f2->alliance) return AllianceAuto(); if (sf->alliance==f2->alliance) return AllianceAuto();
} }
@ -1223,11 +1230,12 @@ count_all(const faction * f)
{ {
int n = 0; int n = 0;
unit *u; unit *u;
for (u=f->units;u;u=u->nextF) for (u=f->units;u;u=u->nextF) {
if (playerrace(u->race)) { if (playerrace(u->race)) {
n += u->number; n += u->number;
assert(f==u->faction); assert(f==u->faction);
} }
}
return n; return n;
} }

View File

@ -100,7 +100,6 @@ struct building_type;
#define PARTIAL_STUDY /* Wenn nicht genug Silber vorhanden, wird ein Talent anteilig gelernt */ #define PARTIAL_STUDY /* Wenn nicht genug Silber vorhanden, wird ein Talent anteilig gelernt */
#define HUNGER_REDUCES_SKILL /* Hunger reduziert den Talentwert auf die Hälfte */ #define HUNGER_REDUCES_SKILL /* Hunger reduziert den Talentwert auf die Hälfte */
#define NEW_RECEIPIES /* Vereinfachte, besser verteilte Kräuterzutaten für Tränke */ #define NEW_RECEIPIES /* Vereinfachte, besser verteilte Kräuterzutaten für Tränke */
#define NEW_TAVERN
#define GOBLINKILL #define GOBLINKILL
#define USE_FIREWALL 1 #define USE_FIREWALL 1
@ -450,6 +449,9 @@ enum {
K_WEREWOLF, K_WEREWOLF,
K_XE, K_XE,
K_ALLIANCE, K_ALLIANCE,
#ifdef HEROES
K_PROMOTION,
#endif
MAXKEYWORDS, MAXKEYWORDS,
NOKEYWORD = (keyword_t) - 1 NOKEYWORD = (keyword_t) - 1
}; };
@ -1169,7 +1171,7 @@ extern const char* get_param(const struct param * p, const char * name);
extern boolean ExpensiveMigrants(void); extern boolean ExpensiveMigrants(void);
extern int FirstTurn(void); extern int FirstTurn(void);
extern int NMRTimeout(void); extern int NMRTimeout(void);
extern int LongHunger(void); extern int LongHunger(const struct unit * u);
extern boolean TradeDisabled(void); extern boolean TradeDisabled(void);
extern int SkillCap(skill_t sk); extern int SkillCap(skill_t sk);
extern int AllianceAuto(void); /* flags that allied factions get automatically */ extern int AllianceAuto(void); /* flags that allied factions get automatically */

View File

@ -126,7 +126,7 @@ give_item(int want, const item_type * itype, unit * src, unit * dest, struct ord
handle_event(&src->attribs, "give", dest); handle_event(&src->attribs, "give", dest);
handle_event(&dest->attribs, "receive", src); handle_event(&dest->attribs, "receive", src);
#if defined(MUSEUM_MODULE) && defined(TODO) #if defined(MUSEUM_MODULE) && defined(TODO)
TODO: Einen Trigger benutzen! /* TODO: Einen Trigger für den museums-warden benutzen! */
if (a_find(dest->attribs, &at_warden)) { if (a_find(dest->attribs, &at_warden)) {
/* warden_add_give(src, dest, itype, n); */ /* warden_add_give(src, dest, itype, n); */
} }
@ -158,6 +158,10 @@ givemen(int n, unit * u, unit * u2, struct order * ord)
} else if (!u2 && u->race == new_race[RC_SNOTLING]) { } else if (!u2 && u->race == new_race[RC_SNOTLING]) {
/* Snotlings können nicht an Bauern übergeben werden. */ /* Snotlings können nicht an Bauern übergeben werden. */
error = 307; error = 307;
#endif
#ifdef HEROES
} else if (u2 && (fval(u, UFL_HERO)!=fval(u2, UFL_HERO))) {
error = 75;
#endif #endif
} else if ((u && unit_has_cursed_item(u)) || (u2 && unit_has_cursed_item(u2))) { } else if ((u && unit_has_cursed_item(u)) || (u2 && unit_has_cursed_item(u2))) {
error = 78; error = 78;
@ -279,6 +283,12 @@ giveunit(unit * u, unit * u2, order * ord)
return; return;
} }
#ifdef HEROES
if (fval(u, UFL_HERO)) {
cmistake(u, ord, 75, MSG_COMMERCE);
return;
}
#endif
if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) {
cmistake(u, ord, 74, MSG_COMMERCE); cmistake(u, ord, 74, MSG_COMMERCE);
return; return;

View File

@ -552,6 +552,8 @@ extern void init_resources(void);
extern const char* resname(resource_t res, int index); extern const char* resname(resource_t res, int index);
extern struct item_type *i_silver;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -2424,7 +2424,7 @@ magic(void)
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (get_keyword(ord) == K_CAST) { if (get_keyword(ord) == K_CAST) {
if (LongHunger() && fval(u, UFL_HUNGER)) { if (LongHunger(u)) {
cmistake(u, ord, 224, MSG_MAGIC); cmistake(u, ord, 224, MSG_MAGIC);
continue; continue;
} }

View File

@ -270,10 +270,10 @@ walkingcapacity(const struct unit * u)
n += personen * personcapacity(u); n += personen * personcapacity(u);
/* Goliathwasser */ /* Goliathwasser */
tmp = get_effect(u, oldpotiontype[P_STRONG]); tmp = get_effect(u, oldpotiontype[P_STRONG]);
n += min(u->number, tmp) * (HORSECAPACITY - personcapacity(u)); n += min(personen, tmp) * (HORSECAPACITY - personcapacity(u));
/* change_effect wird in ageing gemacht */ /* change_effect wird in ageing gemacht */
tmp = get_item(u, I_TROLLBELT); tmp = get_item(u, I_TROLLBELT);
n += min(tmp, u->number) * STRENGTHCAPACITY; n += min(personen, tmp) * STRENGTHCAPACITY;
return n; return n;
} }
@ -876,7 +876,7 @@ init_drive(void)
* doesn't seem to be an easy way to speed this up. */ * doesn't seem to be an easy way to speed this up. */
for(u=r->units; u; u=u->next) { for(u=r->units; u; u=u->next) {
if (get_keyword(u->thisorder) == K_DRIVE && !fval(u, UFL_LONGACTION) && !fval(u, UFL_HUNGER)) { if (get_keyword(u->thisorder) == K_DRIVE && !fval(u, UFL_LONGACTION) && !LongHunger(u)) {
boolean found = false; boolean found = false;
order * ord; order * ord;
@ -922,7 +922,7 @@ init_drive(void)
ut = getunit(r, u->faction); ut = getunit(r, u->faction);
if (ut==NULL) continue; if (ut==NULL) continue;
if (get_keyword(ut->thisorder) == K_DRIVE && !fval(ut, UFL_LONGACTION) && !fval(ut, UFL_HUNGER)) { if (get_keyword(ut->thisorder) == K_DRIVE && !fval(ut, UFL_LONGACTION) && !LongHunger(ut)) {
init_tokens(ut->thisorder); init_tokens(ut->thisorder);
skip_token(); skip_token();
if (getunit(r, ut->faction) == u) { if (getunit(r, ut->faction) == u) {
@ -1349,7 +1349,7 @@ travel(unit * u, region * next, int flucht, region_list ** routep)
if (ut) { if (ut) {
boolean found = false; boolean found = false;
if (get_keyword(ut->thisorder) == K_DRIVE if (get_keyword(ut->thisorder) == K_DRIVE
&& !fval(ut, UFL_LONGACTION) && !fval(ut, UFL_HUNGER)) { && !fval(ut, UFL_LONGACTION) && !LongHunger(ut)) {
init_tokens(ut->thisorder); init_tokens(ut->thisorder);
skip_token(); skip_token();
u2 = getunit(first, ut->faction); u2 = getunit(first, ut->faction);
@ -2201,7 +2201,7 @@ move_hunters(void)
break; break;
} }
if (!fval(u, UFL_LONGACTION) && !fval(u, UFL_HUNGER) && hunt(u)) { if (!fval(u, UFL_LONGACTION) && !LongHunger(u) && hunt(u)) {
up = &r->units; up = &r->units;
break; break;
} }
@ -2335,7 +2335,7 @@ follow_unit(void)
attrib * a; attrib * a;
order * ord; order * ord;
if (fval(u, UFL_LONGACTION) || fval(u, UFL_HUNGER)) continue; if (fval(u, UFL_LONGACTION) || LongHunger(u)) continue;
a = a_find(u->attribs, &at_follow); a = a_find(u->attribs, &at_follow);
for (ord=u->orders;ord;ord=ord->next) { for (ord=u->orders;ord;ord=ord->next) {
const struct locale * lang = u->faction->locale; const struct locale * lang = u->faction->locale;

View File

@ -261,6 +261,12 @@ bufunit(const faction * f, const unit * u, int indent, int mode)
} }
} }
#ifdef HEROES
if (fval(u, UFL_HERO) && (u->faction == f || omniscient(f))) {
scat(", ");
scat(LOC(f->locale, "hero"));
}
#endif
/* status */ /* status */
if (u->number && (u->faction == f || telepath_see || isbattle)) { if (u->number && (u->faction == f || telepath_see || isbattle)) {

View File

@ -49,6 +49,7 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#define FIND_FOREIGN_TEMP #define FIND_FOREIGN_TEMP
@ -1127,3 +1128,22 @@ unitlist_insert(struct unit_list **ul, struct unit *u)
*ul = rl2; *ul = rl2;
} }
#ifdef HEROES
int
maxheroes(const struct faction * f)
{
return (int)(log10(count_all(f) / 50.0) * 20);
}
int
countheroes(const struct faction * f)
{
const unit * u = f->units;
int n = 0;
while (u) {
if (fval(u, UFL_HERO)) n+= u->number;
u = u->nextF;
}
return n;
}
#endif

View File

@ -34,13 +34,14 @@ struct skill;
#define UFL_PARTEITARNUNG (1<<4) /* 16 */ #define UFL_PARTEITARNUNG (1<<4) /* 16 */
#define UFL_DISBELIEVES (1<<5) /* 32 */ #define UFL_DISBELIEVES (1<<5) /* 32 */
#define UFL_WARMTH (1<<6) /* 64 */ #define UFL_WARMTH (1<<6) /* 64 */
/* UFL_HERO, defined below (1<<7) */
#define UFL_MOVED (1<<8) #define UFL_MOVED (1<<8)
#define UFL_FOLLOWING (1<<9) #define UFL_FOLLOWING (1<<9)
#define UFL_FOLLOWED (1<<10) #define UFL_FOLLOWED (1<<10)
#define UFL_HUNGER (1<<11) /* kann im Folgemonat keinen langen Befehl #define UFL_HUNGER (1<<11) /* kann im Folgemonat keinen langen Befehl außer ARBEITE ausführen */
außer ARBEITE ausführen */
#define UFL_SIEGE (1<<12) /* speedup: belagert eine burg, siehe attribut */ #define UFL_SIEGE (1<<12) /* speedup: belagert eine burg, siehe attribut */
#define UFL_TARGET (1<<13) /* speedup: hat ein target, siehe attribut */ #define UFL_TARGET (1<<13) /* speedup: hat ein target, siehe attribut */
#define UFL_WERE (1<<14)
/* warning: von 512/1024 gewechslet, wegen konflikt mit NEW_FOLLOW */ /* warning: von 512/1024 gewechslet, wegen konflikt mit NEW_FOLLOW */
#define UFL_LOCKED (1<<16) /* Einheit kann keine Personen aufnehmen oder weggeben, nicht rekrutieren. */ #define UFL_LOCKED (1<<16) /* Einheit kann keine Personen aufnehmen oder weggeben, nicht rekrutieren. */
@ -52,10 +53,15 @@ au
#define UFL_TAKEALL (1<<25) /* Einheit nimmt alle Gegenstände an */ #define UFL_TAKEALL (1<<25) /* Einheit nimmt alle Gegenstände an */
#define UFL_WERE (1<<28)
/* Flags, die gespeichert werden sollen: */ /* Flags, die gespeichert werden sollen: */
#ifndef HEROES
#define UFL_SAVEMASK (UFL_NOAID | UFL_OWNER | UFL_PARTEITARNUNG | UFL_LOCKED | UFL_HUNGER | FFL_NOIDLEOUT | UFL_TAKEALL) #define UFL_SAVEMASK (UFL_NOAID | UFL_OWNER | UFL_PARTEITARNUNG | UFL_LOCKED | UFL_HUNGER | FFL_NOIDLEOUT | UFL_TAKEALL)
#else
# define UFL_HERO (1<<7)
# define UFL_SAVEMASK (UFL_NOAID | UFL_OWNER | UFL_PARTEITARNUNG | UFL_LOCKED | UFL_HUNGER | FFL_NOIDLEOUT | UFL_TAKEALL | UFL_HERO)
extern int maxheroes(const struct faction * f);
extern int countheroes(const struct faction * f);
#endif
typedef struct unit { typedef struct unit {
struct unit *next; /* needs to be first entry, for region's unitlist */ struct unit *next; /* needs to be first entry, for region's unitlist */

View File

@ -34,10 +34,14 @@
#define PEASANTS_DO_NOT_STARVE 0 #define PEASANTS_DO_NOT_STARVE 0
#define NEW_MIGRATION 1 #define NEW_MIGRATION 1
#define ASTRAL_HUNGER #define ASTRAL_HUNGER
#define NEWATSROI 0 #define NEWATSROI 0
#define MUSEUM_MODULE #define MUSEUM_MODULE
#define ARENA_MODULE #define ARENA_MODULE
#define WORMHOLE_MODULE #define WORMHOLE_MODULE
#define XECMD_MODULE #define XECMD_MODULE
#define NEW_DAEMONHUNGER_RULE
#define NEW_COMBATSKILLS_RULE
#define ROW_FACTOR 3 /* factor for combat row advancement rule */
#define HEROES

View File

@ -102,7 +102,6 @@ extern char * g_reportdir;
extern char * g_datadir; extern char * g_datadir;
extern char * g_basedir; extern char * g_basedir;
extern char * g_resourcedir; extern char * g_resourcedir;
extern item_type * i_silver;
extern boolean nonr; extern boolean nonr;
extern boolean nocr; extern boolean nocr;

View File

@ -108,7 +108,6 @@ extern "C" {
extern char * g_datadir; extern char * g_datadir;
extern char * g_basedir; extern char * g_basedir;
extern char * g_resourcedir; extern char * g_resourcedir;
extern item_type * i_silver;
extern boolean nonr; extern boolean nonr;
extern boolean nocr; extern boolean nocr;

View File

@ -2042,6 +2042,10 @@
<text locale="de">ALLIANZ</text> <text locale="de">ALLIANZ</text>
<text locale="en">ALLIANCE</text> <text locale="en">ALLIANCE</text>
</string> </string>
<string name="PROMOTION">
<text locale="de">BEFÖRDERUNG</text>
<text locale="en">PROMOTION</text>
</string>
<string name="PFLANZEN"> <string name="PFLANZEN">
<text locale="de">PFLANZEN</text> <text locale="de">PFLANZEN</text>
</string> </string>
@ -5899,4 +5903,14 @@
<text locale="en">unknown faction</text> <text locale="en">unknown faction</text>
</string> </string>
<string name="hero">
<text locale="de">Held</text>
<text locale="en">hero</text>
</string>
<string name="hero_p">
<text locale="de">Helden</text>
<text locale="en">heroes</text>
</string>
</strings> </strings>

View File

@ -6028,5 +6028,18 @@
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) können keine Helden erwählen."</text> <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) können keine Helden erwählen."</text>
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot be heroes."</text> <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot be heroes."</text>
</message> </message>
<message name="heroes_cost" section="errors">
<type>
<arg name="command" type="order"/>
<arg name="region" type="region"/>
<arg name="unit" type="unit"/>
<arg name="cost" type="int"/>
<arg name="have" type="int"/>
</type>
<text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nur $int($have) von $int($cost) benötigtem Silber."</text>
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit has $int($have) of $int($cost) silver required."</text>
</message>
</messages> </messages>