2001-01-25 10:37:55 +01:00
|
|
|
|
/* vi: set ts=2:
|
|
|
|
|
*
|
2001-12-10 01:13:39 +01:00
|
|
|
|
*
|
2003-07-29 11:48:03 +02:00
|
|
|
|
* Eressea PB(E)M host Copyright (C) 1998-2003
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* Christian Schlittchen (corwin@amber.kn-bremen.de)
|
|
|
|
|
* Katja Zedel (katze@felidae.kn-bremen.de)
|
|
|
|
|
* Henning Peters (faroul@beyond.kn-bremen.de)
|
|
|
|
|
* Enno Rehling (enno@eressea-pbem.de)
|
|
|
|
|
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
|
|
|
*
|
|
|
|
|
* based on:
|
|
|
|
|
*
|
|
|
|
|
* Atlantis v1.0 13 September 1993 Copyright 1993 by Russell Wallace
|
|
|
|
|
* Atlantis v1.7 Copyright 1996 by Alex Schr<EFBFBD>der
|
|
|
|
|
*
|
|
|
|
|
* This program may not be used, modified or distributed without
|
|
|
|
|
* prior permission by the authors of Eressea.
|
|
|
|
|
* This program may not be sold or used commercially without prior written
|
|
|
|
|
* permission from the authors.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include "eressea.h"
|
|
|
|
|
#include "randenc.h"
|
|
|
|
|
|
|
|
|
|
#include "economy.h"
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include "luck.h"
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#include "monster.h"
|
|
|
|
|
|
|
|
|
|
/* kernel includes */
|
|
|
|
|
#include <kernel/alchemy.h>
|
|
|
|
|
#include <kernel/battle.h>
|
|
|
|
|
#include <kernel/building.h>
|
|
|
|
|
#include <kernel/curse.h>
|
2005-10-02 22:28:44 +02:00
|
|
|
|
#include <kernel/equipment.h>
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#include <kernel/faction.h>
|
|
|
|
|
#include <kernel/item.h>
|
|
|
|
|
#include <kernel/karma.h>
|
|
|
|
|
#include <kernel/magic.h>
|
|
|
|
|
#include <kernel/message.h>
|
|
|
|
|
#include <kernel/movement.h>
|
|
|
|
|
#include <kernel/names.h>
|
|
|
|
|
#include <kernel/order.h>
|
|
|
|
|
#include <kernel/plane.h>
|
|
|
|
|
#include <kernel/pool.h>
|
|
|
|
|
#include <kernel/race.h>
|
|
|
|
|
#include <kernel/region.h>
|
|
|
|
|
#include <kernel/ship.h>
|
|
|
|
|
#include <kernel/skill.h>
|
2005-10-25 14:38:01 +02:00
|
|
|
|
#include <kernel/terrain.h>
|
|
|
|
|
#include <kernel/terrainid.h>
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#include <kernel/unit.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/racename.h>
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* util includes */
|
2007-06-20 02:34:02 +02:00
|
|
|
|
#include <util/attrib.h>
|
2006-02-19 23:43:56 +01:00
|
|
|
|
#include <util/rand.h>
|
2007-06-20 02:34:02 +02:00
|
|
|
|
#include <util/lists.h>
|
2001-05-20 23:47:56 +02:00
|
|
|
|
#include <util/message.h>
|
2006-02-19 23:43:56 +01:00
|
|
|
|
#include <util/rng.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
#include <attributes/iceberg.h>
|
2007-06-20 02:34:02 +02:00
|
|
|
|
extern struct attrib_type at_unitdissolve;
|
|
|
|
|
extern struct attrib_type at_orcification;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* In a->data.ca[1] steht der Prozentsatz mit dem sich die Einheit
|
|
|
|
|
* aufl<EFBFBD>st, in a->data.ca[0] kann angegeben werden, wohin die Personen
|
|
|
|
|
* verschwinden. Passiert bereits in der ersten Runde! */
|
|
|
|
|
static void
|
|
|
|
|
dissolve_units(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
int n;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
attrib * a = a_find(u->attribs, &at_unitdissolve);
|
|
|
|
|
if (a) {
|
2005-01-19 21:33:13 +01:00
|
|
|
|
const char * str = NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (u->age == 0 && a->data.ca[1] < 100) continue;
|
|
|
|
|
|
|
|
|
|
/* TODO: Durch einzelne Berechnung ersetzen */
|
|
|
|
|
if (a->data.ca[1] == 100) {
|
|
|
|
|
n = u->number;
|
|
|
|
|
} else {
|
|
|
|
|
n = 0;
|
|
|
|
|
for (i=0;i<u->number;i++) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int()%100 < a->data.ca[1]) n++;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* wenn keiner verschwindet, auch keine Meldung */
|
|
|
|
|
if (n == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-19 21:33:13 +01:00
|
|
|
|
scale_number(u, u->number - n);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
switch(a->data.ca[0]) {
|
|
|
|
|
case 1:
|
|
|
|
|
rsetpeasants(r, rpeasants(r) + n);
|
|
|
|
|
if (n == 1) {
|
2005-01-19 21:33:13 +01:00
|
|
|
|
str = "kehrte auf sein Feld zur<75>ck.";
|
|
|
|
|
} else {
|
|
|
|
|
str = "kehrten auf ihre Felder zur<75>ck.";
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2005-06-27 22:50:51 +02:00
|
|
|
|
if (r->land && !fval(r, RF_MALLORN)) {
|
|
|
|
|
rsettrees(r, 2, rtrees(r,2) + n);
|
2001-04-01 08:58:45 +02:00
|
|
|
|
if (n == 1) {
|
2005-01-19 21:33:13 +01:00
|
|
|
|
str = "wurde zum Baum.";
|
|
|
|
|
} else {
|
|
|
|
|
str = "wurden zu B<>umen.";
|
2001-04-01 08:58:45 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if(n == 1) {
|
2005-06-27 22:50:51 +02:00
|
|
|
|
str = "verfaulte.";
|
2001-04-01 08:58:45 +02:00
|
|
|
|
} else {
|
2005-06-27 22:50:51 +02:00
|
|
|
|
str = "verfaulten.";
|
2001-04-01 08:58:45 +02:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->race == new_race[RC_STONEGOLEM] || u->race == new_race[RC_IRONGOLEM]) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (n == 1) {
|
2005-01-19 21:33:13 +01:00
|
|
|
|
str = "zerfiel zu Staub.";
|
|
|
|
|
} else {
|
|
|
|
|
str = "zerfielen zu Staub.";
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
if (n == 1) {
|
2005-01-19 21:33:13 +01:00
|
|
|
|
str = "verschwand <20>ber Nacht.";
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}else{
|
2005-01-19 21:33:13 +01:00
|
|
|
|
str = "verschwanden <20>ber Nacht.";
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2005-01-19 21:33:13 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("dissolve_units",
|
|
|
|
|
"unit region number race action", u, r, n, u->race, str));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove_empty_units();
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-06 09:06:02 +01:00
|
|
|
|
static int
|
2005-10-09 21:52:21 +02:00
|
|
|
|
improve_all(faction * f, skill_t sk, int by_weeks)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2005-10-09 21:52:21 +02:00
|
|
|
|
unit *u;
|
|
|
|
|
boolean ret = by_weeks;
|
|
|
|
|
|
|
|
|
|
for (u = f->units; u; u = u->nextF) {
|
|
|
|
|
if (has_skill(u, sk)) {
|
|
|
|
|
int weeks = 0;
|
|
|
|
|
for (;weeks!=by_weeks;++weeks) {
|
|
|
|
|
learn_skill(u, sk, 1.0);
|
|
|
|
|
ret = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
find_manual(region * r, unit * u)
|
|
|
|
|
{
|
2007-06-26 11:32:28 +02:00
|
|
|
|
char zLocation[32];
|
|
|
|
|
char zBook[32];
|
2005-10-09 21:52:21 +02:00
|
|
|
|
skill_t skill = NOSKILL;
|
2007-06-26 11:32:28 +02:00
|
|
|
|
message * msg;
|
|
|
|
|
|
2006-02-19 23:43:56 +01:00
|
|
|
|
switch (rng_int() % 36) {
|
2005-10-09 21:52:21 +02:00
|
|
|
|
case 0:
|
|
|
|
|
skill = SK_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
case 4:
|
|
|
|
|
skill = SK_WEAPONSMITH;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
|
|
|
|
skill = SK_TACTICS;
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
case 8:
|
|
|
|
|
case 9:
|
|
|
|
|
case 10:
|
|
|
|
|
skill = SK_SHIPBUILDING;
|
|
|
|
|
break;
|
|
|
|
|
case 11:
|
|
|
|
|
case 12:
|
|
|
|
|
case 13:
|
|
|
|
|
case 14:
|
|
|
|
|
skill = SK_SAILING;
|
|
|
|
|
break;
|
|
|
|
|
case 15:
|
|
|
|
|
case 16:
|
|
|
|
|
case 17:
|
|
|
|
|
skill = SK_HERBALISM;
|
|
|
|
|
break;
|
|
|
|
|
case 18:
|
|
|
|
|
case 19:
|
|
|
|
|
skill = SK_ALCHEMY;
|
|
|
|
|
break;
|
|
|
|
|
case 20:
|
|
|
|
|
case 21:
|
|
|
|
|
case 22:
|
|
|
|
|
case 23:
|
|
|
|
|
skill = SK_BUILDING;
|
|
|
|
|
break;
|
|
|
|
|
case 24:
|
|
|
|
|
case 25:
|
|
|
|
|
case 26:
|
|
|
|
|
case 27:
|
|
|
|
|
skill = SK_ARMORER;
|
|
|
|
|
break;
|
|
|
|
|
case 28:
|
|
|
|
|
case 29:
|
|
|
|
|
case 30:
|
|
|
|
|
case 31:
|
|
|
|
|
skill = SK_MINING;
|
|
|
|
|
break;
|
|
|
|
|
case 32:
|
|
|
|
|
case 33:
|
|
|
|
|
case 34:
|
|
|
|
|
case 35:
|
|
|
|
|
skill = SK_ENTERTAINMENT;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-06-26 11:32:28 +02:00
|
|
|
|
|
2007-07-17 17:33:48 +02:00
|
|
|
|
snprintf(zLocation, sizeof(zLocation), "manual_location_%d", (int)(rng_int() % 4));
|
|
|
|
|
snprintf(zBook, sizeof(zLocation), "manual_title_%s", skillnames[skill]);
|
2007-06-26 11:32:28 +02:00
|
|
|
|
|
|
|
|
|
msg = msg_message("find_manual", "unit location book", u, zLocation, zBook);
|
|
|
|
|
r_addmessage(r, u->faction, msg);
|
|
|
|
|
msg_release(msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2005-10-09 21:52:21 +02:00
|
|
|
|
if (improve_all(u->faction, skill, 3) == 3) {
|
|
|
|
|
int i;
|
|
|
|
|
for (i=0;i!=9;++i) learn_skill(u, skill, 1.0);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-06 09:06:02 +01:00
|
|
|
|
static void
|
2007-06-26 11:32:28 +02:00
|
|
|
|
get_villagers(region * r, unit * u)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
unit *newunit;
|
2007-06-26 11:32:28 +02:00
|
|
|
|
message * msg = msg_message("encounter_villagers", "unit", u);
|
|
|
|
|
const xmlChar * name = LOC(u->faction->locale, "villagers");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2007-06-26 11:32:28 +02:00
|
|
|
|
r_addmessage(r, u->faction, msg);
|
|
|
|
|
msg_release(msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2007-06-26 11:32:28 +02:00
|
|
|
|
newunit = create_unit(r, u->faction, rng_int() % 20 + 3, u->faction->race, 0, name, u);
|
2005-04-30 19:07:46 +02:00
|
|
|
|
fset(newunit, UFL_ISNEW|UFL_MOVED);
|
2006-02-11 17:11:16 +01:00
|
|
|
|
equip_unit(newunit, get_equipment("random_villagers"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-06 09:06:02 +01:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
get_allies(region * r, unit * u)
|
|
|
|
|
{
|
|
|
|
|
unit *newunit = NULL;
|
2007-06-26 11:32:28 +02:00
|
|
|
|
const char * name;
|
|
|
|
|
const char * equip;
|
|
|
|
|
int number;
|
|
|
|
|
message * msg;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2007-06-26 11:32:28 +02:00
|
|
|
|
assert(u->number);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2007-06-26 11:32:28 +02:00
|
|
|
|
switch (rterrain(r)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case T_PLAIN:
|
|
|
|
|
if (!r_isforest(r)) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (get_money(u) / u->number < 100 + rng_int() % 200)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return;
|
2007-06-26 11:32:28 +02:00
|
|
|
|
name = "random_plain_men";
|
|
|
|
|
equip = "random_plain";
|
|
|
|
|
number = rng_int() % 8 + 2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
if (eff_skill(u, SK_LONGBOW, r) < 3
|
|
|
|
|
&& eff_skill(u, SK_HERBALISM, r) < 2
|
|
|
|
|
&& eff_skill(u, SK_MAGIC, r) < 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-06-26 11:32:28 +02:00
|
|
|
|
name = "random_forest_men";
|
|
|
|
|
equip = "random_forest";
|
|
|
|
|
number = rng_int() % 6 + 2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_SWAMP:
|
|
|
|
|
if (eff_skill(u, SK_OBSERVATION, r) <= 3) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-06-26 11:32:28 +02:00
|
|
|
|
name = "random_swamp_men";
|
|
|
|
|
equip = "random_swamp";
|
|
|
|
|
number = rng_int() % 6 + 2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_DESERT:
|
|
|
|
|
if (eff_skill(u, SK_RIDING, r) <= 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-06-26 11:32:28 +02:00
|
|
|
|
name = "random_desert_men";
|
|
|
|
|
equip = "random_desert";
|
|
|
|
|
number = rng_int() % 12 + 2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_HIGHLAND:
|
2005-10-02 19:35:25 +02:00
|
|
|
|
if (eff_skill(u, SK_MELEE, r) <= 1) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
2007-06-26 11:32:28 +02:00
|
|
|
|
name = "random_highland_men";
|
|
|
|
|
equip = "random_highland";
|
|
|
|
|
number = rng_int() % 8 + 2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_MOUNTAIN:
|
2007-06-26 11:32:28 +02:00
|
|
|
|
if (eff_skill(u, SK_MELEE, r) <= 1 || eff_skill(u, SK_TRADE, r) <= 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
name = "random_mountain_men";
|
|
|
|
|
equip = "random_mountain";
|
|
|
|
|
number = rng_int() % 6 + 2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_GLACIER:
|
2007-06-26 11:32:28 +02:00
|
|
|
|
if (eff_skill(u, SK_MELEE, r) <= 1 || eff_skill(u, SK_TRADE, r) <= 1) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
2007-06-26 11:32:28 +02:00
|
|
|
|
name = "random_glacier_men";
|
|
|
|
|
equip = "random_glacier";
|
|
|
|
|
number = rng_int() % 4 + 2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
2007-06-26 11:32:28 +02:00
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2007-06-26 11:32:28 +02:00
|
|
|
|
newunit = create_unit(r, u->faction, number, u->faction->race, 0, LOC(u->faction->locale, name), u);
|
|
|
|
|
equip_unit(newunit, get_equipment(equip));
|
2005-10-02 09:33:21 +02:00
|
|
|
|
|
2007-06-26 11:32:28 +02:00
|
|
|
|
u_setfaction(newunit, u->faction);
|
|
|
|
|
set_racename(&newunit->attribs, get_racename(u->attribs));
|
|
|
|
|
if(u->race->flags & RCF_SHAPESHIFT) {
|
|
|
|
|
newunit->irace = u->irace;
|
|
|
|
|
}
|
|
|
|
|
if (fval(u, UFL_PARTEITARNUNG)) fset(newunit, UFL_PARTEITARNUNG);
|
|
|
|
|
fset(newunit, UFL_ISNEW);
|
2005-10-02 09:33:21 +02:00
|
|
|
|
|
2007-06-26 11:32:28 +02:00
|
|
|
|
msg = msg_message("encounter_allies", "unit name", u, name);
|
|
|
|
|
r_addmessage(r, u->faction, msg);
|
|
|
|
|
msg_release(msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-02-06 09:06:02 +01:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
encounter(region * r, unit * u)
|
|
|
|
|
{
|
|
|
|
|
if (!fval(r, RF_ENCOUNTER)) return;
|
|
|
|
|
freset(r, RF_ENCOUNTER);
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int() % 100>=ENCCHANCE) return;
|
|
|
|
|
switch (rng_int() % 3) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case 0:
|
|
|
|
|
find_manual(r, u);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
2007-06-26 11:32:28 +02:00
|
|
|
|
get_villagers(r, u);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
get_allies(r, u);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
encounters(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
2005-10-25 14:38:01 +02:00
|
|
|
|
if (!fval(r->terrain, SEA_REGION) && fval(r, RF_ENCOUNTER)) {
|
2006-10-15 16:09:59 +02:00
|
|
|
|
int c = 0;
|
|
|
|
|
unit * u;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
c += u->number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (c > 0) {
|
2006-10-15 16:09:59 +02:00
|
|
|
|
int i = 0;
|
|
|
|
|
int n = rng_int() % c;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-15 16:09:59 +02:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2006-10-29 12:44:34 +01:00
|
|
|
|
if (i+u->number>n) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2006-10-15 16:09:59 +02:00
|
|
|
|
assert(u && u->number);
|
|
|
|
|
encounter(r, u);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-10-25 14:38:01 +02:00
|
|
|
|
static const terrain_type *
|
|
|
|
|
chaosterrain(void)
|
|
|
|
|
{
|
|
|
|
|
static const terrain_type ** types;
|
|
|
|
|
static int numtypes;
|
|
|
|
|
|
|
|
|
|
if (numtypes==0) {
|
|
|
|
|
const terrain_type * terrain;
|
|
|
|
|
for (terrain=terrains();terrain!=NULL;terrain=terrain->next) {
|
|
|
|
|
if (fval(terrain, LAND_REGION) && terrain->herbs) {
|
|
|
|
|
++numtypes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
types = malloc(sizeof(terrain_type)*numtypes);
|
|
|
|
|
numtypes = 0;
|
|
|
|
|
for (terrain=terrains();terrain!=NULL;terrain=terrain->next) {
|
|
|
|
|
if (fval(terrain, LAND_REGION) && terrain->herbs) {
|
|
|
|
|
types[numtypes++] = terrain;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-02-19 23:43:56 +01:00
|
|
|
|
return types[rng_int() % numtypes];
|
2005-10-25 14:38:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
chaos(region * r)
|
|
|
|
|
{
|
|
|
|
|
unit *u = NULL, *u2;
|
|
|
|
|
building *b, *b2;
|
|
|
|
|
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int() % 100 < 8) {
|
|
|
|
|
switch (rng_int() % 3) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case 0: /* Untote */
|
2005-10-25 14:38:01 +02:00
|
|
|
|
if (!fval(r->terrain, SEA_REGION)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
u = random_unit(r);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u && playerrace(u->race)) {
|
2007-06-26 11:32:28 +02:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u));
|
2001-02-10 15:18:01 +01:00
|
|
|
|
u_setfaction(u, findfaction(MONSTER_FACTION));
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u->race = new_race[RC_GHOUL];
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 1: /* Drachen */
|
|
|
|
|
if (random_unit(r)) {
|
|
|
|
|
int mfac = 0;
|
2006-02-19 23:43:56 +01:00
|
|
|
|
switch (rng_int() % 3) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case 0:
|
|
|
|
|
mfac = 100;
|
2006-02-19 23:43:56 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), rng_int() % 8 + 1, new_race[RC_FIREDRAGON]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
mfac = 500;
|
2006-02-19 23:43:56 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), rng_int() % 4 + 1, new_race[RC_DRAGON]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
mfac = 1000;
|
2006-02-19 23:43:56 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), rng_int() % 2 + 1, new_race[RC_WYRM]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (mfac) set_money(u, u->number * (rng_int() % mfac));
|
2005-04-30 19:07:46 +02:00
|
|
|
|
fset(u, UFL_ISNEW|UFL_MOVED);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
case 2: /* Terrainver<65>nderung */
|
2005-10-25 14:38:01 +02:00
|
|
|
|
if (!fval(r->terrain, FORBIDDEN_REGION)) {
|
|
|
|
|
if (!fval(r->terrain, SEA_REGION)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
direction_t dir;
|
|
|
|
|
for (dir=0;dir!=MAXDIRECTIONS;++dir) {
|
2005-10-25 14:38:01 +02:00
|
|
|
|
region * rn = rconnect(r, dir);
|
|
|
|
|
if (rn && fval(rn->terrain, SEA_REGION)) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
if (dir!=MAXDIRECTIONS) {
|
|
|
|
|
ship * sh = r->ships;
|
|
|
|
|
while (sh) {
|
|
|
|
|
ship * nsh = sh->next;
|
|
|
|
|
damage_ship(sh, 0.50);
|
2004-05-31 18:21:03 +02:00
|
|
|
|
if (sh->damage >= sh->size * DAMAGE_SCALE) destroy_ship(sh);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sh = nsh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u;) {
|
|
|
|
|
u2 = u->next;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->race != new_race[RC_SPELL] && u->ship == 0) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_number(u, 0);
|
|
|
|
|
}
|
|
|
|
|
u = u2;
|
|
|
|
|
}
|
2005-01-19 21:33:13 +01:00
|
|
|
|
ADDMSG(&r->msgs, msg_message("tidalwave", "region", r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (b = rbuildings(r); b;) {
|
|
|
|
|
b2 = b->next;
|
|
|
|
|
destroy_building(b);
|
|
|
|
|
b = b2;
|
|
|
|
|
}
|
|
|
|
|
terraform(r, T_OCEAN);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
direction_t dir;
|
|
|
|
|
for (dir=0;dir!=MAXDIRECTIONS;++dir) {
|
2005-10-25 14:38:01 +02:00
|
|
|
|
region * rn = rconnect(r, dir);
|
|
|
|
|
if (rn && fval(rn->terrain, SEA_REGION)) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
if (dir!=MAXDIRECTIONS) {
|
2005-10-25 14:38:01 +02:00
|
|
|
|
terraform_region(r, chaosterrain());
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-31 03:07:07 +02:00
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
nb_armor(const unit *u, int index)
|
|
|
|
|
{
|
|
|
|
|
const item * itm;
|
|
|
|
|
int av = 0;
|
|
|
|
|
int s = 0, a = 0;
|
|
|
|
|
|
|
|
|
|
if (!(u->race->battle_flags & BF_EQUIPMENT)) return 0;
|
|
|
|
|
|
|
|
|
|
/* Normale R<>stung */
|
|
|
|
|
|
|
|
|
|
for (itm=u->items;itm;itm=itm->next) {
|
|
|
|
|
const armor_type * atype = itm->type->rtype->atype;
|
|
|
|
|
if (atype!=NULL) {
|
|
|
|
|
int * schutz = &a;
|
|
|
|
|
if (atype->flags & ATF_SHIELD) schutz = &s;
|
|
|
|
|
if (*schutz <= index) {
|
|
|
|
|
*schutz += itm->number;
|
|
|
|
|
if (*schutz > index) {
|
|
|
|
|
av += atype->prot;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return av;
|
|
|
|
|
}
|
|
|
|
|
|
2004-10-19 21:59:37 +02:00
|
|
|
|
static int
|
2005-07-31 03:07:07 +02:00
|
|
|
|
damage_unit(unit *u, const char *dam, boolean physical, boolean magic)
|
2004-10-19 21:59:37 +02:00
|
|
|
|
{
|
|
|
|
|
int *hp = malloc(u->number * sizeof(int));
|
|
|
|
|
int h;
|
|
|
|
|
int i, dead = 0, hp_rem = 0, heiltrank;
|
2006-10-15 16:09:59 +02:00
|
|
|
|
double magres = magic_resistance(u);
|
2004-10-19 21:59:37 +02:00
|
|
|
|
|
2006-10-15 16:09:59 +02:00
|
|
|
|
assert(u->number);
|
2006-03-24 08:35:51 +01:00
|
|
|
|
if (fval(u->race, RCF_ILLUSIONARY) || u->race == new_race[RC_SPELL]) {
|
2005-12-28 22:07:01 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2004-10-19 21:59:37 +02:00
|
|
|
|
h = u->hp/u->number;
|
|
|
|
|
/* HP verteilen */
|
|
|
|
|
for (i=0; i<u->number; i++) hp[i] = h;
|
|
|
|
|
h = u->hp - (u->number * h);
|
|
|
|
|
for (i=0; i<h; i++) hp[i]++;
|
|
|
|
|
|
|
|
|
|
/* Schaden */
|
|
|
|
|
for (i=0; i<u->number; i++) {
|
|
|
|
|
int damage = dice_rand(dam);
|
2006-10-15 16:09:59 +02:00
|
|
|
|
if (magic) damage = (int)(damage * (1.0 - magres));
|
2005-07-31 03:07:07 +02:00
|
|
|
|
if (physical) damage -= nb_armor(u, i);
|
2004-10-19 21:59:37 +02:00
|
|
|
|
hp[i] -= damage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Auswirkungen */
|
|
|
|
|
for (i=0; i<u->number; i++) {
|
|
|
|
|
if (hp[i] <= 0){
|
|
|
|
|
heiltrank = 0;
|
|
|
|
|
|
|
|
|
|
/* Sieben Leben */
|
|
|
|
|
if (old_race(u->race) == RC_CAT && (chance(1.0 / 7))) {
|
|
|
|
|
hp[i] = u->hp/u->number;
|
|
|
|
|
hp_rem += hp[i];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Heiltrank */
|
|
|
|
|
if (get_effect(u, oldpotiontype[P_HEAL]) > 0) {
|
|
|
|
|
change_effect(u, oldpotiontype[P_HEAL], -1);
|
|
|
|
|
heiltrank = 1;
|
2005-10-31 23:34:45 +01:00
|
|
|
|
} else if (i_get(u->items, oldpotiontype[P_HEAL]->itype) > 0) {
|
2004-10-19 21:59:37 +02:00
|
|
|
|
i_change(&u->items, oldpotiontype[P_HEAL]->itype, -1);
|
|
|
|
|
change_effect(u, oldpotiontype[P_HEAL], 3);
|
|
|
|
|
heiltrank = 1;
|
|
|
|
|
}
|
|
|
|
|
if (heiltrank && (chance(0.50))) {
|
|
|
|
|
hp[i] = u->hp/u->number;
|
|
|
|
|
hp_rem += hp[i];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dead++;
|
|
|
|
|
} else {
|
|
|
|
|
hp_rem += hp[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scale_number(u, u->number - dead);
|
|
|
|
|
u->hp = hp_rem;
|
|
|
|
|
|
|
|
|
|
free(hp);
|
|
|
|
|
|
|
|
|
|
return dead;
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
2001-12-10 01:13:39 +01:00
|
|
|
|
drown(region *r)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2006-10-09 00:15:49 +02:00
|
|
|
|
if (fval(r->terrain, SEA_REGION)) {
|
|
|
|
|
unit ** up = up=&r->units;
|
|
|
|
|
while (*up) {
|
|
|
|
|
unit *u = *up;
|
2006-02-17 23:59:03 +01:00
|
|
|
|
#ifdef KARMA_MODULE
|
|
|
|
|
int amphibian_level = fspecial(u->faction, FS_AMPHIBIAN);
|
|
|
|
|
#else
|
|
|
|
|
int amphibian_level = 0;
|
|
|
|
|
#endif
|
2006-10-09 00:15:49 +02:00
|
|
|
|
if (u->ship || u->race == new_race[RC_SPELL] || u->number==0) {
|
|
|
|
|
up=&u->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-09 00:15:49 +02:00
|
|
|
|
if (amphibian_level) {
|
|
|
|
|
int dead = damage_unit(u, "5d1", false, false);
|
|
|
|
|
if (dead) {
|
2006-01-08 12:33:10 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_dead",
|
|
|
|
|
"amount unit region", dead, u, r));
|
2006-10-09 00:15:49 +02:00
|
|
|
|
} else {
|
2006-01-08 12:33:10 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("drown_amphibian_nodead",
|
|
|
|
|
"unit region",u, r));
|
2006-10-09 00:15:49 +02:00
|
|
|
|
}
|
2005-07-02 00:54:14 +02:00
|
|
|
|
} else if (!(canswim(u) || canfly(u))) {
|
2006-10-09 00:15:49 +02:00
|
|
|
|
scale_number(u, 0);
|
2006-01-08 12:33:10 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r));
|
2006-10-09 00:15:49 +02:00
|
|
|
|
}
|
|
|
|
|
if (*up==u) up=&u->next;
|
|
|
|
|
}
|
|
|
|
|
remove_empty_units_in_region(r);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
region *
|
|
|
|
|
rrandneighbour(region *r)
|
|
|
|
|
{
|
|
|
|
|
direction_t i;
|
|
|
|
|
region *rc = NULL;
|
|
|
|
|
int rr, c = 0;
|
|
|
|
|
|
|
|
|
|
/* Nachsehen, wieviele Regionen in Frage kommen */
|
|
|
|
|
|
|
|
|
|
for (i = 0; i != MAXDIRECTIONS; i++) {
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
/* Zuf<75>llig eine ausw<73>hlen */
|
|
|
|
|
|
2006-02-19 23:43:56 +01:00
|
|
|
|
rr = rng_int() % c;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Durchz<68>hlen */
|
|
|
|
|
|
|
|
|
|
c = -1;
|
|
|
|
|
for (i = 0; i != MAXDIRECTIONS; i++) {
|
|
|
|
|
rc = rconnect(r, i);
|
|
|
|
|
c++;
|
|
|
|
|
if (c == rr) break;
|
|
|
|
|
}
|
|
|
|
|
assert(i!=MAXDIRECTIONS);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
volcano_outbreak(region *r)
|
|
|
|
|
{
|
2006-10-07 22:48:41 +02:00
|
|
|
|
attrib *a;
|
|
|
|
|
region *rn;
|
|
|
|
|
unit *u, **up;
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
for (u=r->units; u; u=u->next) {
|
|
|
|
|
f = u->faction;
|
2007-06-20 02:34:02 +02:00
|
|
|
|
freset(f, FFL_SELECT);
|
2006-10-07 22:48:41 +02:00
|
|
|
|
}
|
|
|
|
|
rn = rrandneighbour(r);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
/* Vulkan-Region verw<72>sten */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
rsettrees(r, 2, 0);
|
|
|
|
|
rsettrees(r, 1, 0);
|
|
|
|
|
rsettrees(r, 0, 0);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
a = a_find(r->attribs, &at_reduceproduction);
|
|
|
|
|
if (!a) a = a_add(&r->attribs, a_new(&at_reduceproduction));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
/* Produktion vierteln ... */
|
|
|
|
|
a->data.sa[0] = 25;
|
|
|
|
|
/* F<>r 6-17 Runden */
|
|
|
|
|
a->data.sa[1] = (short)(a->data.sa[1] + 6 + rng_int()%12);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
/* Personen bekommen 4W10 Punkte Schaden. */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
for (up=&r->units; *up;) {
|
|
|
|
|
unit * u = *up;
|
2006-10-15 16:09:59 +02:00
|
|
|
|
if (u->number) {
|
|
|
|
|
int dead = damage_unit(u, "4d10", true, false);
|
|
|
|
|
if (dead) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("volcano_dead",
|
|
|
|
|
"unit region dead", u, r, dead));
|
|
|
|
|
}
|
2007-06-20 02:34:02 +02:00
|
|
|
|
if (!fval(u->faction, FFL_SELECT)) {
|
|
|
|
|
fset(u->faction, FFL_SELECT);
|
2006-10-15 16:09:59 +02:00
|
|
|
|
if (rn) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("volcanooutbreak",
|
|
|
|
|
"regionv regionn", r, rn));
|
|
|
|
|
} else {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("volcanooutbreaknn",
|
|
|
|
|
"region", r));
|
|
|
|
|
}
|
2006-10-07 22:48:41 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (u==*up) up=&u->next;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
remove_empty_units_in_region(r);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
/* Zuf<75>llige Nachbarregion verw<72>sten */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
if (rn) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
rsettrees(r, 2, 0);
|
|
|
|
|
rsettrees(r, 1, 0);
|
|
|
|
|
rsettrees(r, 0, 0);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
a = a_find(rn->attribs, &at_reduceproduction);
|
|
|
|
|
if (!a) a = a_add(&rn->attribs, a_new(&at_reduceproduction));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
/* Produktion vierteln ... */
|
|
|
|
|
a->data.sa[0] = 25;
|
|
|
|
|
/* F<>r 6-17 Runden */
|
|
|
|
|
a->data.sa[1] = (short)(a->data.sa[1] + 6 + rng_int()%12);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-07 22:48:41 +02:00
|
|
|
|
/* Personen bekommen 3W10 Punkte Schaden. */
|
|
|
|
|
for (up=&rn->units; *up;) {
|
|
|
|
|
unit * u = *up;
|
2006-10-15 16:09:59 +02:00
|
|
|
|
if (u->number) {
|
|
|
|
|
int dead = damage_unit(u, "3d10", true, false);
|
|
|
|
|
if (dead) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("volcano_dead",
|
|
|
|
|
"unit region dead", u, r, dead));
|
|
|
|
|
}
|
2006-10-07 22:48:41 +02:00
|
|
|
|
}
|
|
|
|
|
if (u==*up) up=&u->next;
|
|
|
|
|
}
|
|
|
|
|
remove_empty_units_in_region(rn);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
static void
|
|
|
|
|
melt_iceberg(region *r)
|
|
|
|
|
{
|
|
|
|
|
attrib *a;
|
|
|
|
|
unit *u;
|
|
|
|
|
building *b, *b2;
|
|
|
|
|
|
2007-06-20 02:34:02 +02:00
|
|
|
|
for (u=r->units; u; u=u->next) freset(u->faction, FFL_SELECT);
|
|
|
|
|
for (u=r->units; u; u=u->next) if (!fval(u->faction, FFL_SELECT)) {
|
|
|
|
|
fset(u->faction, FFL_SELECT);
|
2005-09-03 10:54:19 +02:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("iceberg_melt", "region", r));
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* driftrichtung l<>schen */
|
|
|
|
|
a = a_find(r->attribs, &at_iceberg);
|
|
|
|
|
if (a) a_remove(&r->attribs, a);
|
|
|
|
|
|
|
|
|
|
/* Geb<65>ude l<>schen */
|
|
|
|
|
for (b = rbuildings(r); b; b = b2) {
|
|
|
|
|
b2 = b->next;
|
|
|
|
|
destroy_building(b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* in Ozean wandeln */
|
2002-03-10 13:34:49 +01:00
|
|
|
|
terraform(r, T_OCEAN);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
/* Einheiten, die nicht schwimmen k<>nnen oder in Schiffen sind,
|
|
|
|
|
* ertrinken */
|
|
|
|
|
drown(r);
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
move_iceberg(region *r)
|
|
|
|
|
{
|
|
|
|
|
attrib *a;
|
|
|
|
|
direction_t dir;
|
|
|
|
|
region *rc;
|
|
|
|
|
|
|
|
|
|
a = a_find(r->attribs, &at_iceberg);
|
|
|
|
|
if (!a) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
dir = (direction_t)(rng_int()%MAXDIRECTIONS);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
a = a_add(&r->attribs, make_iceberg(dir));
|
|
|
|
|
} else {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int()%100 < 20) {
|
|
|
|
|
dir = (direction_t)(rng_int()%MAXDIRECTIONS);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
a->data.i = dir;
|
|
|
|
|
} else {
|
|
|
|
|
dir = (direction_t)a->data.i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = rconnect(r, dir);
|
|
|
|
|
|
2005-10-25 14:38:01 +02:00
|
|
|
|
if (rc && !fval(rc->terrain, ARCTIC_REGION)) {
|
|
|
|
|
if (fval(rc->terrain, SEA_REGION)) { /* Eisberg treibt */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
ship *sh, *shn;
|
|
|
|
|
unit *u;
|
2005-06-10 00:10:35 +02:00
|
|
|
|
short x, y;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
|
2007-06-20 02:34:02 +02:00
|
|
|
|
for (u=r->units; u; u=u->next) freset(u->faction, FFL_SELECT);
|
|
|
|
|
for (u=r->units; u; u=u->next) if (!fval(u->faction, FFL_SELECT)) {
|
|
|
|
|
fset(u->faction, FFL_SELECT);
|
2006-01-08 12:33:10 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("iceberg_drift",
|
|
|
|
|
"region dir", r, dir));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
x = r->x;
|
|
|
|
|
y = r->y;
|
|
|
|
|
|
|
|
|
|
runhash(r);
|
|
|
|
|
runhash(rc);
|
|
|
|
|
r->x = rc->x;
|
|
|
|
|
r->y = rc->y;
|
|
|
|
|
rc->x = x;
|
|
|
|
|
rc->y = y;
|
|
|
|
|
rhash(rc);
|
|
|
|
|
rhash(r);
|
|
|
|
|
|
|
|
|
|
/* rc ist der Ozean (Ex-Eisberg), r der Eisberg (Ex-Ozean) */
|
|
|
|
|
|
|
|
|
|
/* Schiffe aus dem Zielozean werden in den Eisberg transferiert
|
|
|
|
|
* und nehmen Schaden. */
|
|
|
|
|
|
2007-06-20 02:34:02 +02:00
|
|
|
|
for (sh = r->ships; sh; sh=sh->next) freset(sh, SF_SELECT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (sh = r->ships; sh; sh = sh->next) {
|
|
|
|
|
/* Meldung an Kapit<69>n */
|
|
|
|
|
damage_ship(sh, 0.10);
|
2007-06-20 02:34:02 +02:00
|
|
|
|
fset(sh, SF_SELECT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Personen, Schiffe und Geb<65>ude verschieben */
|
|
|
|
|
while (rc->buildings) {
|
2002-07-21 11:04:07 +02:00
|
|
|
|
rc->buildings->region = r;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
translist(&rc->buildings, &r->buildings, rc->buildings);
|
|
|
|
|
}
|
|
|
|
|
while (rc->ships) {
|
2007-06-20 02:34:02 +02:00
|
|
|
|
fset(rc->ships, SF_SELECT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
damage_ship(rc->ships, 0.10);
|
|
|
|
|
move_ship(rc->ships, rc, r, NULL);
|
|
|
|
|
}
|
|
|
|
|
while (rc->units) {
|
|
|
|
|
building * b = rc->units->building;
|
|
|
|
|
u = rc->units;
|
|
|
|
|
move_unit(rc->units, r, NULL);
|
|
|
|
|
u->building = b; /* move_unit macht ein leave() */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Besch<63>digte Schiffe k<>nnen sinken */
|
|
|
|
|
|
|
|
|
|
for (sh = r->ships; sh;) {
|
|
|
|
|
shn = sh->next;
|
2007-06-20 02:34:02 +02:00
|
|
|
|
if (fval(sh, SF_SELECT)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
u = captain(sh, r);
|
|
|
|
|
if (sh->damage>=sh->size * DAMAGE_SCALE) {
|
2006-01-08 12:33:10 +01:00
|
|
|
|
if (u!=NULL) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg_des",
|
|
|
|
|
"ship", sh));
|
|
|
|
|
}
|
2004-05-31 18:21:03 +02:00
|
|
|
|
destroy_ship(sh);
|
2006-01-08 12:33:10 +01:00
|
|
|
|
} else if (u!=NULL) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg",
|
|
|
|
|
"ship", sh));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sh = shn;
|
|
|
|
|
}
|
|
|
|
|
|
2006-02-19 23:43:56 +01:00
|
|
|
|
} else if (rng_int()%100 < 20) { /* Eisberg bleibt als Gletscher liegen */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
unit *u;
|
|
|
|
|
|
|
|
|
|
rsetterrain(r, T_GLACIER);
|
|
|
|
|
a_remove(&r->attribs, a);
|
|
|
|
|
|
2007-06-20 02:34:02 +02:00
|
|
|
|
for (u=r->units; u; u=u->next) freset(u->faction, FFL_SELECT);
|
|
|
|
|
for (u=r->units; u; u=u->next) if (!fval(u->faction, FFL_SELECT)) {
|
|
|
|
|
fset(u->faction, FFL_SELECT);
|
2006-01-08 12:33:10 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("iceberg_land", "region", r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-26 22:51:19 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
move_icebergs(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
2005-09-03 10:54:19 +02:00
|
|
|
|
for (r=regions; r; r=r->next) {
|
2007-06-20 02:34:02 +02:00
|
|
|
|
if (rterrain(r) == T_ICEBERG && !fval(r, RF_SELECT)) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
int select = rng_int() % 10;
|
2005-09-03 10:54:19 +02:00
|
|
|
|
if (select < 4) {
|
|
|
|
|
/* 4% chance */
|
2007-06-20 02:34:02 +02:00
|
|
|
|
fset(r, RF_SELECT);
|
2005-09-03 10:54:19 +02:00
|
|
|
|
melt_iceberg(r);
|
|
|
|
|
} else if (select<64) {
|
|
|
|
|
/* 60% chance */
|
2007-06-20 02:34:02 +02:00
|
|
|
|
fset(r, RF_SELECT);
|
2005-09-03 10:54:19 +02:00
|
|
|
|
move_iceberg(r);
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
create_icebergs(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
2005-09-03 10:54:19 +02:00
|
|
|
|
for (r=regions; r; r=r->next) {
|
|
|
|
|
if (rterrain(r) == T_ICEBERG_SLEEP && chance(0.05)) {
|
|
|
|
|
boolean has_ocean_neighbour = false;
|
|
|
|
|
direction_t dir;
|
|
|
|
|
region *rc;
|
|
|
|
|
unit *u;
|
|
|
|
|
|
2007-06-20 02:34:02 +02:00
|
|
|
|
freset(r, RF_SELECT);
|
2005-09-03 10:54:19 +02:00
|
|
|
|
for (dir=0; dir < MAXDIRECTIONS; dir++) {
|
|
|
|
|
rc = rconnect(r, dir);
|
2005-10-25 14:38:01 +02:00
|
|
|
|
if (rc && fval(rc->terrain, SEA_REGION)) {
|
2005-09-03 10:54:19 +02:00
|
|
|
|
has_ocean_neighbour = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!has_ocean_neighbour) continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2005-09-03 10:54:19 +02:00
|
|
|
|
rsetterrain(r, T_ICEBERG);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2007-06-20 02:34:02 +02:00
|
|
|
|
fset(r, RF_SELECT);
|
2005-09-03 10:54:19 +02:00
|
|
|
|
move_iceberg(r);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2005-09-03 10:54:19 +02:00
|
|
|
|
for (u=r->units; u; u=u->next) {
|
2007-06-20 02:34:02 +02:00
|
|
|
|
freset(u->faction, FFL_SELECT);
|
2005-09-03 10:54:19 +02:00
|
|
|
|
}
|
|
|
|
|
for (u=r->units; u; u=u->next) {
|
2007-06-20 02:34:02 +02:00
|
|
|
|
if (!fval(u->faction, FFL_SELECT)) {
|
|
|
|
|
fset(u->faction, FFL_SELECT);
|
2005-09-03 10:54:19 +02:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("iceberg_create", "region", r));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-26 22:51:19 +02:00
|
|
|
|
static void
|
2001-12-10 01:13:39 +01:00
|
|
|
|
godcurse(void)
|
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
region *r;
|
|
|
|
|
|
2005-10-25 14:38:01 +02:00
|
|
|
|
for (r=regions; r; r=r->next) {
|
|
|
|
|
if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
unit * u;
|
|
|
|
|
for(u=r->units; u; u=u->next) {
|
|
|
|
|
skill * sv = u->skills;
|
|
|
|
|
while (sv!=u->skills+u->skill_size) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
int weeks = 1+rng_int()%3;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
reduce_skill(u, sv, weeks);
|
|
|
|
|
++sv;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-10-25 14:38:01 +02:00
|
|
|
|
if (fval(r->terrain, SEA_REGION)) {
|
|
|
|
|
ship *sh;
|
|
|
|
|
for (sh = r->ships; sh;) {
|
|
|
|
|
ship *shn = sh->next;
|
|
|
|
|
damage_ship(sh, 0.10);
|
|
|
|
|
if (sh->damage>=sh->size * DAMAGE_SCALE) {
|
|
|
|
|
unit * u = shipowner(sh);
|
|
|
|
|
if (u) ADDMSG(&u->faction->msgs,
|
|
|
|
|
msg_message("godcurse_destroy_ship", "ship", sh));
|
|
|
|
|
destroy_ship(sh);
|
|
|
|
|
}
|
|
|
|
|
sh = shn;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-10-25 14:38:01 +02:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2005-04-30 19:07:46 +02:00
|
|
|
|
static unit *
|
2004-06-21 18:45:27 +02:00
|
|
|
|
split_unit(region * r, unit *u)
|
|
|
|
|
{
|
|
|
|
|
unit *u2 = createunit(r, u->faction, 0, u->race);
|
|
|
|
|
int newsize = u->number/2;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_string(&u2->name, u->name);
|
|
|
|
|
set_string(&u2->display, u->display);
|
|
|
|
|
transfermen(u, u2, newsize);
|
2005-04-30 19:07:46 +02:00
|
|
|
|
return u2;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_split(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
|
|
|
|
|
for(r=regions;r;r=r->next) {
|
|
|
|
|
for(u=r->units;u;u=u->next) {
|
|
|
|
|
if(u->faction->no == MONSTER_FACTION) {
|
|
|
|
|
if(u->number > u->race->splitsize) {
|
2005-04-30 19:07:46 +02:00
|
|
|
|
unit * u2 = split_unit(r, u);
|
|
|
|
|
fset(u2, UFL_ISNEW|UFL_MOVED);
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-26 22:51:19 +02:00
|
|
|
|
/** handles the "orcish" curse that makes units grow like old orks
|
|
|
|
|
* This would probably be better handled in an age-function for the curse,
|
|
|
|
|
* but it's now being called by randomevents()
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
orc_growth(void)
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2005-06-12 15:30:59 +02:00
|
|
|
|
static boolean init = false;
|
2005-10-16 23:08:22 +02:00
|
|
|
|
static const curse_type *ct_orcish = 0;
|
|
|
|
|
curse *c = 0;
|
2005-06-12 15:30:59 +02:00
|
|
|
|
if (!init) {
|
|
|
|
|
init = true;
|
2005-10-16 23:08:22 +02:00
|
|
|
|
ct_orcish = ct_find("orcish");
|
2005-06-12 15:30:59 +02:00
|
|
|
|
}
|
2005-10-16 23:08:22 +02:00
|
|
|
|
if (ct_orcish) c = get_curse(u->attribs, ct_orcish);
|
2005-03-06 13:46:55 +01:00
|
|
|
|
|
|
|
|
|
if (c && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY) && !fval(u, UFL_HERO)) {
|
2004-06-26 22:51:19 +02:00
|
|
|
|
int n;
|
|
|
|
|
int increase = 0;
|
|
|
|
|
int num = get_cursedmen(u, c);
|
|
|
|
|
int prob = curse_geteffect(c);
|
|
|
|
|
|
|
|
|
|
for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int() % 100 < prob) {
|
2004-06-26 22:51:19 +02:00
|
|
|
|
++increase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (increase) {
|
2005-03-06 14:26:02 +01:00
|
|
|
|
unit * u2 = create_unit(r, u->faction, increase, u->race, 0, NULL, u);
|
2005-03-06 13:46:55 +01:00
|
|
|
|
transfermen(u2, u, u2->number);
|
2004-06-26 22:51:19 +02:00
|
|
|
|
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("orcgrowth",
|
|
|
|
|
"unit amount race", u, increase, u->race));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Talente von D<>monen verschieben sich.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
demon_skillchanges(void)
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit * u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (u->race == new_race[RC_DAEMON]) {
|
|
|
|
|
skill * sv = u->skills;
|
|
|
|
|
while (sv!=u->skills+u->skill_size) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (sv->level>0 && rng_int() % 100 < 25) {
|
|
|
|
|
int weeks = 1+rng_int()%3;
|
|
|
|
|
if (rng_int() % 100 < 40) {
|
2004-06-26 22:51:19 +02:00
|
|
|
|
reduce_skill(u, sv, weeks);
|
|
|
|
|
} else {
|
|
|
|
|
while (weeks--) learn_skill(u, sv->id, 1.0);
|
|
|
|
|
}
|
|
|
|
|
if (sv->old>sv->level) {
|
2007-03-11 21:52:09 +01:00
|
|
|
|
if (!quiet) {
|
|
|
|
|
log_printf("%s dropped from %u to %u:%u in %s\n",
|
|
|
|
|
unitname(u), sv->old, sv->level, sv->weeks, skillname(sv->id, NULL));
|
|
|
|
|
}
|
2004-06-26 22:51:19 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++sv;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Eisberge entstehen und bewegen sich.
|
|
|
|
|
* Einheiten die im Wasser landen, ertrinken.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
icebergs(void)
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
create_icebergs();
|
|
|
|
|
move_icebergs();
|
|
|
|
|
for (r=regions; r; r=r->next) {
|
|
|
|
|
drown(r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
randomevents(void)
|
|
|
|
|
{
|
2006-02-17 23:59:03 +01:00
|
|
|
|
#ifdef KARMA_MODULE
|
2002-04-12 14:46:16 +02:00
|
|
|
|
faction *f;
|
2006-02-17 23:59:03 +01:00
|
|
|
|
#endif /* KARMA_MODULE */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
region *r;
|
|
|
|
|
building *b, *b2;
|
2001-05-20 23:47:56 +02:00
|
|
|
|
unit *u;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-26 22:51:19 +02:00
|
|
|
|
icebergs();
|
|
|
|
|
godcurse();
|
|
|
|
|
orc_growth();
|
|
|
|
|
demon_skillchanges();
|
2003-07-29 11:48:03 +02:00
|
|
|
|
|
2006-02-10 20:48:43 +01:00
|
|
|
|
/* Orkifizierte Regionen mutieren und mutieren zur<75>ck */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-02-10 20:48:43 +01:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (fval(r, RF_ORCIFIED)) {
|
|
|
|
|
direction_t dir;
|
|
|
|
|
double probability = 0.0;
|
|
|
|
|
for (dir = 0; dir < MAXDIRECTIONS; dir++) {
|
|
|
|
|
region *rc = rconnect(r, dir);
|
|
|
|
|
if (rc && rpeasants(rc) > 0 && !fval(rc, RF_ORCIFIED)) probability += 0.02;
|
|
|
|
|
}
|
|
|
|
|
if (chance(probability)) {
|
|
|
|
|
ADDMSG(&r->msgs, msg_message("deorcified", "region", r));
|
|
|
|
|
freset(r, RF_ORCIFIED);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
attrib *a = a_find(r->attribs, &at_orcification);
|
|
|
|
|
if (a!=NULL) {
|
|
|
|
|
double probability = 0.0;
|
|
|
|
|
if (rpeasants(r) <= 0) continue;
|
|
|
|
|
probability = a->data.i/(double)rpeasants(r);
|
|
|
|
|
if (chance(probability)) {
|
|
|
|
|
fset(r, RF_ORCIFIED);
|
|
|
|
|
a_remove(&r->attribs, a);
|
|
|
|
|
ADDMSG(&r->msgs, msg_message("orcified", "region", r));
|
|
|
|
|
} else {
|
|
|
|
|
a->data.i -= max(10,a->data.i/10);
|
|
|
|
|
if (a->data.i <= 0) a_remove(&r->attribs, a);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-02-10 20:48:43 +01:00
|
|
|
|
/* Vulkane qualmen, brechen aus ... */
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (rterrain(r)==T_VOLCANO_SMOKING && a_find(r->attribs, &at_reduceproduction)) {
|
|
|
|
|
ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r));
|
|
|
|
|
rsetterrain(r, T_VOLCANO);
|
|
|
|
|
} else switch(rterrain(r)) {
|
|
|
|
|
case T_VOLCANO:
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int()%100 < 4) {
|
2006-02-10 20:48:43 +01:00
|
|
|
|
ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r));
|
|
|
|
|
rsetterrain(r, T_VOLCANO_SMOKING);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case T_VOLCANO_SMOKING:
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int()%100 < 12) {
|
2006-02-10 20:48:43 +01:00
|
|
|
|
ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r));
|
|
|
|
|
rsetterrain(r, T_VOLCANO);
|
2006-02-19 23:43:56 +01:00
|
|
|
|
} else if (rng_int()%100 < 8) {
|
2006-02-10 20:48:43 +01:00
|
|
|
|
volcano_outbreak(r);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-02-10 20:48:43 +01:00
|
|
|
|
/* Monumente zerfallen, Schiffe verfaulen */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-02-10 20:48:43 +01:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (b = rbuildings(r); b; b = b2) {
|
|
|
|
|
b2 = b->next;
|
|
|
|
|
if (fval(b->type, BTF_DECAY) && !buildingowner(r, b)) {
|
|
|
|
|
b->size -= max(1, (b->size * 20) / 100);
|
|
|
|
|
if (b->size == 0) {
|
|
|
|
|
destroy_building(b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2005-11-26 12:00:20 +01:00
|
|
|
|
/* monster-einheiten desertieren */
|
2006-02-10 20:48:43 +01:00
|
|
|
|
for (r = regions; r; r=r->next) {
|
|
|
|
|
for (u=r->units; u; u=u->next) {
|
2006-10-09 00:15:49 +02:00
|
|
|
|
if (u->faction && u->faction->no != MONSTER_FACTION
|
2006-02-10 20:48:43 +01:00
|
|
|
|
&& (u->race->flags & RCF_DESERT)) {
|
|
|
|
|
if (fval(u, UFL_ISNEW)) continue;
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (rng_int()%100 < 5) {
|
2006-02-10 20:48:43 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("desertion",
|
|
|
|
|
"unit region", u, r));
|
|
|
|
|
u_setfaction(u, findfaction(MONSTER_FACTION));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-11-26 12:00:20 +01:00
|
|
|
|
|
2006-02-17 23:59:03 +01:00
|
|
|
|
#ifdef KARMA_MODULE
|
2005-11-26 12:00:20 +01:00
|
|
|
|
/* lycanthropen werden werw<72>lfe */
|
2006-02-10 20:48:43 +01:00
|
|
|
|
for (f = factions; f; f=f->next) {
|
2006-10-09 00:15:49 +02:00
|
|
|
|
if (f->alive) {
|
|
|
|
|
int level = fspecial(f, FS_LYCANTROPE);
|
|
|
|
|
if (level > 0) {
|
|
|
|
|
for(u = f->units; u; u=u->nextF) {
|
|
|
|
|
if (rng_int()%100 < 2*level) {
|
|
|
|
|
ADDMSG(&u->faction->msgs,
|
|
|
|
|
msg_message("becomewere", "unit region", u, u->region));
|
|
|
|
|
fset(u, UFL_WERE);
|
|
|
|
|
}
|
2006-02-10 20:48:43 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-02-17 23:59:03 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2006-10-09 00:15:49 +02:00
|
|
|
|
/* Chaos */
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
int i;
|
|
|
|
|
if (fval(r, RF_CHAOTIC)) {
|
|
|
|
|
chaos(r);
|
|
|
|
|
}
|
|
|
|
|
i = chaoscount(r);
|
|
|
|
|
if (!i) continue;
|
|
|
|
|
chaoscounts(r, -(int) (i * ((double) (rng_int() % 10)) / 100.0));
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifdef HERBS_ROT
|
2006-10-09 00:15:49 +02:00
|
|
|
|
/* Kr<4B>uter verrotten */
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u=u->next) {
|
|
|
|
|
item **itmp = &u->items, *hbag = *i_find(&u->items, olditemtype[I_SACK_OF_CONSERVATION]);
|
|
|
|
|
int rot_chance = HERBROTCHANCE;
|
|
|
|
|
|
|
|
|
|
if (hbag) rot_chance = (HERBROTCHANCE*2)/5;
|
|
|
|
|
|
|
|
|
|
while (*itmp) {
|
|
|
|
|
item * itm = *itmp;
|
|
|
|
|
int n = itm->number;
|
|
|
|
|
double k = n*rot_chance/100.0;
|
2006-02-10 20:48:43 +01:00
|
|
|
|
if (fval(itm->type, ITF_HERB)) {
|
|
|
|
|
double nv = normalvariate(k, k/4);
|
|
|
|
|
int inv = (int)nv;
|
|
|
|
|
int delta = min(n, inv);
|
|
|
|
|
i_change(itmp, itm->type, -delta);
|
|
|
|
|
}
|
2006-10-09 00:15:49 +02:00
|
|
|
|
if (itm==*itmp) itmp=&itm->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#endif
|
2006-10-09 00:15:49 +02:00
|
|
|
|
|
|
|
|
|
dissolve_units();
|
|
|
|
|
check_split();
|
2006-02-17 23:59:03 +01:00
|
|
|
|
#ifdef KARMA_MODULE
|
2006-10-09 00:15:49 +02:00
|
|
|
|
check_luck();
|
2006-02-17 23:59:03 +01:00
|
|
|
|
#endif /* KARMA_MODULE */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|