- spawning new dragons and undead is now optional (lua function)

- battle-effect on peasants is configurable (by XML param)
This commit is contained in:
Enno Rehling 2005-11-26 11:00:20 +00:00
parent 7f0b8f98d1
commit 531115b392
10 changed files with 212 additions and 174 deletions

View File

@ -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));
}
}
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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",

View File

@ -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

View File

@ -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));
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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"

View File

@ -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 */