diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c index bc2a7f4b8..a7ad4f8c8 100644 --- a/src/common/gamecode/monster.c +++ b/src/common/gamecode/monster.c @@ -1038,3 +1038,157 @@ plan_monsters(void) } pathfinder_cleanup(); } + +static double +chaosfactor(region * r) +{ + attrib * a = a_find(r->attribs, &at_chaoscount); + if (!a) return 0; + return ((double) a->data.i / 1000.0); +} + +static int +nrand(int start, int sub) +{ + int res = 0; + + do { + if (rand() % 100 < start) + res++; + start -= sub; + } while (start > 0); + + return res; +} + +/** Drachen und Seeschlangen können entstehen */ +void +spawn_dragons(void) +{ + region * r; + + for (r = regions; r; r = r->next) { + unit * u; + message * msg; + + if (fval(r->terrain, SEA_REGION) && rand()%10000 < 1) { + u = createunit(r, findfaction(MONSTER_FACTION), 1, new_race[RC_SEASERPENT]); + fset(u, UFL_ISNEW|UFL_MOVED); + set_level(u, SK_MAGIC, 4); + set_level(u, SK_OBSERVATION, 3); + set_level(u, SK_STEALTH, 2); + set_level(u, SK_AUSDAUER, 1); + set_string(&u->name, "Seeschlange"); + } + + if ((rterrain(r) == T_GLACIER || r->terrain == newterrain(T_SWAMP) || rterrain(r) == T_DESERT) && rand() % 10000 < (5 + 100 * chaosfactor(r))) + { + if (chance(0.80)) { + u = createunit(r, findfaction(MONSTER_FACTION), nrand(60, 20) + 1, new_race[RC_FIREDRAGON]); + } else { + u = createunit(r, findfaction(MONSTER_FACTION), nrand(30, 20) + 1, new_race[RC_DRAGON]); + } + fset(u, UFL_ISNEW|UFL_MOVED); + + set_money(u, u->number * (rand() % 500 + 100)); + set_level(u, SK_MAGIC, 4); + set_level(u, SK_OBSERVATION, 1+rand()%3); + set_level(u, SK_STEALTH, 1); + set_level(u, SK_AUSDAUER, 1); + log_printf("%d %s in %s.\n", u->number, + LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL)); + + name_unit(u); + + /* add message to the region */ + ADDMSG(&r->msgs, + msg_message("sighting", "region race number", + NULL, u->race, u->number)); + /* create new message to add to units */ + msg = msg_message("sighting", "region race number", + u->region, u->race, u->number); + for (u=r->units;u;u=u->next) freset(u->faction, FL_DH); + for (u=r->units;u;u=u->next) { + faction * f = u->faction; + if (!fval(f, FL_DH)) { + add_message(&f->msgs, msg); + fset(f, FL_DH); + } + } + msg_release(msg); + } + } +} + +/** Untote können entstehen */ +void +spawn_undead(void) +{ + region * r; + + for (r = regions; r; r = r->next) { + int unburied = deathcount(r); + + if(is_cursed(r->attribs, C_HOLYGROUND, 0)) continue; + + /* Chance 0.1% * chaosfactor */ + if (r->land && unburied > r->land->peasants / 20 && rand() % 10000 < (100 + 100 * chaosfactor(r))) { + unit * u; + /* es ist sinnfrei, wenn irgendwo im Wald 3er-Einheiten Untote entstehen. + * Lieber sammeln lassen, bis sie mindestens 5% der Bevölkerung sind, und + * dann erst auferstehen. */ + int undead = unburied / (rand() % 2 + 1); + const race * rc = NULL; + int i; + if (r->age<100) undead = undead * 100 / r->age; /* newbie-regionen kriegen weniger ab */ + + if (!undead || r->age < 20) continue; + + switch(rand()%3) { + case 0: + rc = new_race[RC_SKELETON]; break; + case 1: + rc = new_race[RC_ZOMBIE]; break; + default: + rc = new_race[RC_GHOUL]; break; + } + + u = createunit(r, findfaction(MONSTER_FACTION), undead, rc); + fset(u, UFL_ISNEW|UFL_MOVED); + if ((rc == new_race[RC_SKELETON] || rc == new_race[RC_ZOMBIE]) && rand()%10 < 4) { + equip_unit(u, get_equipment("rising_undead")); + } + + for (i=0;i < MAXSKILLS;i++) { + if (rc->bonus[i] >= 1) { + set_level(u, (skill_t)i, 1); + } + } + u->hp = unit_max_hp(u) * u->number; + + deathcounts(r, -undead); + name_unit(u); + + log_printf("%d %s in %s.\n", u->number, + LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL)); + + { + message * msg = msg_message("undeadrise", "region", r); + add_message(&r->msgs, msg); + for (u=r->units;u;u=u->next) freset(u->faction, FL_DH); + for (u=r->units;u;u=u->next) { + if (fval(u->faction, FL_DH)) continue; + fset(u->faction, FL_DH); + add_message(&u->faction->msgs, msg); + } + msg_release(msg); + } + } else { + int i = deathcount(r); + if (i) { + /* Gräber verwittern, 3% der Untoten finden die ewige Ruhe */ + deathcounts(r, (int)(-i*0.03)); + } + } + } +} diff --git a/src/common/gamecode/monster.h b/src/common/gamecode/monster.h index e13c84d84..ab9295a53 100644 --- a/src/common/gamecode/monster.h +++ b/src/common/gamecode/monster.h @@ -33,6 +33,9 @@ void monsters_kill_peasants(void); void plan_monsters(void); struct unit *random_unit(const struct region * r); +extern void spawn_undead(void); +extern void spawn_dragons(void); + #ifdef __cplusplus } #endif diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c index 7211e4ab2..bea9f7402 100644 --- a/src/common/gamecode/randenc.c +++ b/src/common/gamecode/randenc.c @@ -69,20 +69,6 @@ extern attrib_type at_unitdissolve; extern attrib_type at_orcification; -int -nrand(int start, int sub) -{ - int res = 0; - - do { - if (rand() % 100 < start) - res++; - start -= sub; - } while (start > 0); - - return res; -} - /* In a->data.ca[1] steht der Prozentsatz mit dem sich die Einheit * auflöst, in a->data.ca[0] kann angegeben werden, wohin die Personen * verschwinden. Passiert bereits in der ersten Runde! */ @@ -602,14 +588,6 @@ chaos(region * r) } } -double -chaosfactor(region * r) -{ - attrib * a = a_find(r->attribs, &at_chaoscount); - if (!a) return 0; - return ((double) a->data.i / 1000.0); -} - static int nb_armor(const unit *u, int index) @@ -1362,128 +1340,7 @@ randomevents(void) } } - /* Drachen und Seeschlangen können entstehen */ - - printf("\n"); - - for (r = regions; r; r = r->next) { - unit * u; - message * msg; - if (fval(r->terrain, SEA_REGION) && rand()%10000 < 1) { - u = createunit(r, findfaction(MONSTER_FACTION), 1, new_race[RC_SEASERPENT]); - fset(u, UFL_ISNEW|UFL_MOVED); - set_level(u, SK_MAGIC, 4); - set_level(u, SK_OBSERVATION, 3); - set_level(u, SK_STEALTH, 2); - set_level(u, SK_AUSDAUER, 1); - set_string(&u->name, "Seeschlange"); - } - - if ((rterrain(r) == T_GLACIER || r->terrain == newterrain(T_SWAMP) || rterrain(r) == T_DESERT) && rand() % 10000 < (5 + 100 * chaosfactor(r))) - { - if (chance(0.80)) { - u = createunit(r, findfaction(MONSTER_FACTION), nrand(60, 20) + 1, new_race[RC_FIREDRAGON]); - } else { - u = createunit(r, findfaction(MONSTER_FACTION), nrand(30, 20) + 1, new_race[RC_DRAGON]); - } - fset(u, UFL_ISNEW|UFL_MOVED); - - set_money(u, u->number * (rand() % 500 + 100)); - set_level(u, SK_MAGIC, 4); - set_level(u, SK_OBSERVATION, 1+rand()%3); - set_level(u, SK_STEALTH, 1); - set_level(u, SK_AUSDAUER, 1); - log_printf("%d %s in %s.\n", u->number, - LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL)); - - name_unit(u); - - /* add message to the region */ - ADDMSG(&r->msgs, - msg_message("sighting", "region race number", - NULL, u->race, u->number)); - /* create new message to add to units */ - msg = msg_message("sighting", "region race number", - u->region, u->race, u->number); - for (u=r->units;u;u=u->next) freset(u->faction, FL_DH); - for (u=r->units;u;u=u->next) { - faction * f = u->faction; - if (!fval(f, FL_DH)) { - add_message(&f->msgs, msg); - fset(f, FL_DH); - } - } - msg_release(msg); - } - } - - /* Untote können entstehen */ - - for (r = regions; r; r = r->next) { - int unburied = deathcount(r); - - if(is_cursed(r->attribs, C_HOLYGROUND, 0)) continue; - - /* Chance 0.1% * chaosfactor */ - if (r->land && unburied > r->land->peasants / 20 && rand() % 10000 < (100 + 100 * chaosfactor(r))) { - /* es ist sinnfrei, wenn irgendwo im Wald 3er-Einheiten Untote entstehen. - * Lieber sammeln lassen, bis sie mindestens 5% der Bevölkerung sind, und - * dann erst auferstehen. */ - int undead = unburied / (rand() % 2 + 1); - const race * rc = NULL; - int i; - if (r->age<100) undead = undead * 100 / r->age; /* newbie-regionen kriegen weniger ab */ - - if (!undead || r->age < 20) continue; - - switch(rand()%3) { - case 0: - rc = new_race[RC_SKELETON]; break; - case 1: - rc = new_race[RC_ZOMBIE]; break; - default: - rc = new_race[RC_GHOUL]; break; - } - - u = createunit(r, findfaction(MONSTER_FACTION), undead, rc); - fset(u, UFL_ISNEW|UFL_MOVED); - if ((rc == new_race[RC_SKELETON] || rc == new_race[RC_ZOMBIE]) && rand()%10 < 4) { - equip_unit(u, get_equipment("rising_undead")); - } - - for (i=0;i < MAXSKILLS;i++) { - if (rc->bonus[i] >= 1) { - set_level(u, (skill_t)i, 1); - } - } - u->hp = unit_max_hp(u) * u->number; - - deathcounts(r, -undead); - name_unit(u); - - log_printf("%d %s in %s.\n", u->number, - LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL)); - - { - message * msg = msg_message("undeadrise", "region", r); - add_message(&r->msgs, msg); - for (u=r->units;u;u=u->next) freset(u->faction, FL_DH); - for (u=r->units;u;u=u->next) { - if (fval(u->faction, FL_DH)) continue; - fset(u->faction, FL_DH); - add_message(&u->faction->msgs, msg); - } - msg_release(msg); - } - } else { - int i = deathcount(r); - if (i) { - /* Gräber verwittern, 3% der Untoten finden die ewige Ruhe */ - deathcounts(r, (int)(-i*0.03)); - } - } - } - + /* monster-einheiten desertieren */ for (r = regions; r; r=r->next) { for (u=r->units; u; u=u->next) { if (u->faction->no != MONSTER_FACTION @@ -1497,7 +1354,8 @@ randomevents(void) } } } - + + /* lycanthropen werden werwölfe */ for (f = factions; f; f=f->next) { int level = fspecial(f, FS_LYCANTROPE); if(level > 0) { diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index 4ae599abd..db1d99403 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -2285,6 +2285,28 @@ seematrix(const faction * f, const side * s) return true; } +static double +PopulationDamage(void) +{ + static double value = -1.0; + if (value<0) { + const char * str = get_param(global.parameters, "battle.populationdamage"); + value = str?atof(str):BATTLE_KILLS_PEASANTS; + } + return value; +} + + +static void +battle_effects(battle * b, int dead_players) +{ + region * r = b->region; + int dead_peasants = min(rpeasants(r), (int)(dead_players*PopulationDamage())); + deathcounts(r, dead_peasants + dead_players); + chaoscounts(r, dead_peasants / 2); + rsetpeasants(r, rpeasants(r) - dead_peasants); +} + static void aftermath(battle * b) { @@ -2294,9 +2316,8 @@ aftermath(battle * b) side *s; cvector *fighters = &b->fighters; void **fi; - int is = 0; + int dead_players = 0; bfaction * bf; - int dead_peasants; boolean battle_was_relevant = (boolean)(b->turn+(b->has_tactics_turn?1:0)>2); #ifdef TROLLSAVE @@ -2481,7 +2502,7 @@ aftermath(battle * b) if (playerrace(du->race)) { /* tote im kampf werden zu regionsuntoten: * for each of them, a peasant will die as well */ - is += dead; + dead_players += dead; } if (du->hp < du->number) { log_error(("%s has less hitpoints (%u) than people (%u)\n", @@ -2492,10 +2513,8 @@ aftermath(battle * b) s->alive+=s->healed; assert(snumber==s->flee+s->alive+s->dead); } cv_next(s); - dead_peasants = min(rpeasants(r), (is*BATTLE_KILLS_PEASANTS)/100); - deathcounts(r, dead_peasants + is); - chaoscounts(r, dead_peasants / 2); - rsetpeasants(r, rpeasants(r) - dead_peasants); + + battle_effects(b, dead_players); cv_foreach(s, b->sides) { message * seen = msg_message("battle::army_report", diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index 4e02823a1..4c7401e3e 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -232,18 +232,6 @@ extern void read_laen(struct region * r, int laen); #define DMRISE 10 #define DMRISEHAFEN 20 -/* Vermehrungsrate Bauern in 1/10000. - * Evt. Berechnungsfehler, reale Vermehrungsraten scheinen höher. */ -#if REDUCED_PEASANTGROWTH == 1 -#define PEASANTGROWTH 10 -#define BATTLE_KILLS_PEASANTS 20 -#define PEASANTLUCK 10 -#else -#define PEASANTGROWTH 100 -#define BATTLE_KILLS_PEASANTS 100 -#define PEASANTLUCK 1 -#endif - /* Vermehrung trotz 90% Auslastung */ #define PEASANTFORCE 75 diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index e03757cec..d274075be 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -1007,11 +1007,7 @@ terraform_region(region * r, const terrain_type * terrain) if (!fval(r, RF_CHAOTIC)) { int peasants; -#if REDUCED_PEASANTGROWTH == 1 peasants = (maxworkingpeasants(r) * (20+dice_rand("6d10")))/100; -#else - peasants = MAXPEASANTS_PER_AREA * (rand() % (terrain->size / MAXPEASANTS_PER_AREA / 2)); -#endif rsetpeasants(r, max(100, peasants)); rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL)+1) + rand() % 5)); } diff --git a/src/common/settings-eressea.h b/src/common/settings-eressea.h index 200cee927..928a0dd88 100644 --- a/src/common/settings-eressea.h +++ b/src/common/settings-eressea.h @@ -17,7 +17,6 @@ #define ENTERTAINFRACTION 20 #define IMMUN_GEGEN_ANGRIFF 8 #define RESOURCE_CONVERSION 1 -#define REDUCED_PEASANTGROWTH 1 #define RACE_ADJUSTMENTS 1 #define TEACHDIFFERENCE 2 #define PEASANT_ADJUSTMENT 1 @@ -30,6 +29,13 @@ #define NEW_MIGRATION 1 #define ASTRAL_HUNGER #define NEWATSROI 0 + +/* Vermehrungsrate Bauern in 1/10000. +* Evt. Berechnungsfehler, reale Vermehrungsraten scheinen höher. */ +#define PEASANTGROWTH 10 +#define BATTLE_KILLS_PEASANTS 20 +#define PEASANTLUCK 10 + #define HUNGER_REDUCES_SKILL /* Hunger reduziert den Talentwert auf die Hälfte */ diff --git a/src/common/settings-tutorial.h b/src/common/settings-tutorial.h index b3e33f4f0..6a20f0aff 100644 --- a/src/common/settings-tutorial.h +++ b/src/common/settings-tutorial.h @@ -17,7 +17,6 @@ #define ENTERTAINFRACTION 20 #define IMMUN_GEGEN_ANGRIFF 8 #define RESOURCE_CONVERSION 1 -#define REDUCED_PEASANTGROWTH 1 #define RACE_ADJUSTMENTS 1 #define TEACHDIFFERENCE 2 #define PEASANT_ADJUSTMENT 1 @@ -30,6 +29,13 @@ #define NEW_MIGRATION 1 #define ASTRAL_HUNGER #define NEWATSROI 0 + +/* Vermehrungsrate Bauern in 1/10000. +* Evt. Berechnungsfehler, reale Vermehrungsraten scheinen höher. */ +#define PEASANTGROWTH 10 +#define BATTLE_KILLS_PEASANTS 20 +#define PEASANTLUCK 10 + #define HUNGER_REDUCES_SKILL /* Hunger reduziert den Talentwert auf die Hälfte */ diff --git a/src/common/settings-vinyambar-3.h b/src/common/settings-vinyambar-3.h index bac99249f..d1f93164d 100644 --- a/src/common/settings-vinyambar-3.h +++ b/src/common/settings-vinyambar-3.h @@ -17,7 +17,6 @@ #define ENTERTAINFRACTION 20 #define IMMUN_GEGEN_ANGRIFF 8 #define RESOURCE_CONVERSION 1 -#define REDUCED_PEASANTGROWTH 1 #define RACE_ADJUSTMENTS 1 #define TEACHDIFFERENCE 2 #define PEASANT_ADJUSTMENT 1 @@ -30,9 +29,13 @@ #define PEASANTS_DO_NOT_STARVE 0 #define NEW_MIGRATION 1 +/* Vermehrungsrate Bauern in 1/10000. +* Evt. Berechnungsfehler, reale Vermehrungsraten scheinen höher. */ +#define PEASANTGROWTH 10 +#define BATTLE_KILLS_PEASANTS 20 +#define PEASANTLUCK 10 + #if NEWATSROI == 1 #define ATSBONUS 2 #define ROIBONUS 4 #endif - -#define MAILITPATH "/usr/sbin:$HOME/bin:/bin:/usr/bin:/usr/local/bin" diff --git a/src/common/settings-wdw.h b/src/common/settings-wdw.h index a2fcc1153..b1bd1cb83 100644 --- a/src/common/settings-wdw.h +++ b/src/common/settings-wdw.h @@ -17,7 +17,6 @@ #define ENTERTAINFRACTION 20 #define IMMUN_GEGEN_ANGRIFF 8 #define RESOURCE_CONVERSION 1 -#define REDUCED_PEASANTGROWTH 1 #define RACE_ADJUSTMENTS 1 #define TEACHDIFFERENCE 2 #define PEASANT_ADJUSTMENT 1 @@ -30,6 +29,12 @@ #define NEW_MIGRATION 1 #define ASTRAL_HUNGER +/* Vermehrungsrate Bauern in 1/10000. +* Evt. Berechnungsfehler, reale Vermehrungsraten scheinen höher. */ +#define PEASANTGROWTH 10 +#define BATTLE_KILLS_PEASANTS 20 +#define PEASANTLUCK 10 + #define HUNGER_REDUCES_SKILL /* Hunger reduziert den Talentwert auf die Hälfte */