2001-01-25 10:37:55 +01:00
|
|
|
|
/* vi: set ts=2:
|
|
|
|
|
*
|
2001-12-10 01:13:39 +01:00
|
|
|
|
*
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* Eressea PB(E)M host Copyright (C) 1998-2000
|
|
|
|
|
* 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 "unit.h"
|
|
|
|
|
#include "faction.h"
|
|
|
|
|
#include "alchemy.h"
|
|
|
|
|
#include "item.h"
|
|
|
|
|
#include "plane.h"
|
|
|
|
|
#include "economy.h"
|
|
|
|
|
#include "building.h"
|
|
|
|
|
#include "magic.h"
|
|
|
|
|
#include "message.h"
|
|
|
|
|
#include "race.h"
|
|
|
|
|
#include "monster.h"
|
|
|
|
|
#include "creation.h"
|
|
|
|
|
#include "names.h"
|
|
|
|
|
#include "pool.h"
|
|
|
|
|
#include "movement.h"
|
|
|
|
|
#include "curse.h"
|
|
|
|
|
#include "region.h"
|
|
|
|
|
#include "skill.h"
|
|
|
|
|
#include "karma.h"
|
|
|
|
|
#include "ship.h"
|
|
|
|
|
#include "battle.h"
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include "luck.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 */
|
|
|
|
|
#include <rand.h>
|
2001-05-20 23:47:56 +02:00
|
|
|
|
#include <util/message.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>
|
|
|
|
|
extern attrib_type at_unitdissolve;
|
2001-01-27 20:30:07 +01:00
|
|
|
|
extern attrib_type at_orcification;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
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<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) {
|
|
|
|
|
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++) {
|
|
|
|
|
if (rand()%100 < a->data.ca[1]) n++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* wenn keiner verschwindet, auch keine Meldung */
|
|
|
|
|
if (n == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scale_number(u,u->number - n);
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "%s in %s: %d %s ", unitname(u), regionid(r),
|
2001-12-10 01:13:39 +01:00
|
|
|
|
n, LOC(default_locale, rc_name(u->race, n!=1)));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
switch(a->data.ca[0]) {
|
|
|
|
|
case 1:
|
|
|
|
|
rsetpeasants(r, rpeasants(r) + n);
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
scat("kehrte auf sein Feld zur<75>ck.");
|
|
|
|
|
}else{
|
|
|
|
|
scat("kehrten auf ihre Felder zur<75>ck.");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2001-04-01 08:58:45 +02:00
|
|
|
|
if(r->land) {
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rsettrees(r, 2, rtrees(r,2) + n);
|
|
|
|
|
#else
|
2001-04-01 08:58:45 +02:00
|
|
|
|
rsettrees(r, rtrees(r) + n);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-04-01 08:58:45 +02:00
|
|
|
|
if (n == 1) {
|
|
|
|
|
scat("wurde zum Baum.");
|
|
|
|
|
}else{
|
|
|
|
|
scat("wurden zu B<>umen.");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if(n == 1) {
|
|
|
|
|
scat("verfaulte in der feuchten Seeluft.");
|
|
|
|
|
} else {
|
|
|
|
|
scat("verfaulten in der feuchten Seeluft.");
|
|
|
|
|
}
|
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) {
|
|
|
|
|
scat("zerfiel zu Staub.");
|
|
|
|
|
}else{
|
|
|
|
|
scat("zerfielen zu Staub.");
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
scat("verschwand <20>ber Nacht.");
|
|
|
|
|
}else{
|
|
|
|
|
scat("verschwanden <20>ber Nacht.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
addmessage(r, u->faction, buf, MSG_EVENT, ML_INFO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove_empty_units();
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-06 09:06:02 +01:00
|
|
|
|
static int
|
2002-02-15 17:13:30 +01:00
|
|
|
|
improve_all(faction * f, skill_t sk, int weeks)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
int n = 0;
|
|
|
|
|
region *last = lastregion(f);
|
|
|
|
|
|
|
|
|
|
for (r = firstregion(f); r != last; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2002-03-03 19:13:08 +01:00
|
|
|
|
if (u->faction == f && has_skill(u, sk)) {
|
2002-02-15 17:13:30 +01:00
|
|
|
|
for (n=0;n!=weeks;++n) {
|
|
|
|
|
learn_skill(u, sk, 1.0);
|
2002-02-06 09:06:02 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
find_manual(region * r, unit * u)
|
|
|
|
|
{
|
|
|
|
|
skill_t skill = NOSKILL;
|
|
|
|
|
sprintf(buf, "%s stolper%c bei der Erforschung der Region <20>ber ",
|
|
|
|
|
unitname(u), "nt"[u->number == 1]);
|
|
|
|
|
|
|
|
|
|
switch (rand() % 4) {
|
|
|
|
|
case 0:
|
|
|
|
|
scat("die Ruine eines alten Tempels");
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
scat("eine alte Burgruine");
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
scat("ein zerfallenes Bauernhaus");
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
scat("eine Leiche am Wegesrand");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scat(". Bei der Durchsuchung ");
|
|
|
|
|
if (u->number == 1) {
|
|
|
|
|
scat("st<EFBFBD><EFBFBD>t");
|
|
|
|
|
} else {
|
|
|
|
|
scat("sto<EFBFBD>en");
|
|
|
|
|
}
|
|
|
|
|
scat(" sie auf das zerfledderte Exemplar eines alten Buches, betitelt ");
|
|
|
|
|
|
|
|
|
|
switch (rand() % 36) {
|
|
|
|
|
case 0:
|
|
|
|
|
scat("\'Magie der Elemente\'");
|
|
|
|
|
skill = SK_MAGIC;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
case 4:
|
|
|
|
|
scat("\'Schwerter, Armbr<62>ste, Langb<67>gen\'");
|
|
|
|
|
skill = SK_WEAPONSMITH;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
|
|
|
|
scat("\'Gorms Almanach der Rationellen Kriegsf<73>hrung\'");
|
|
|
|
|
skill = SK_TACTICS;
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
case 8:
|
|
|
|
|
case 9:
|
|
|
|
|
case 10:
|
|
|
|
|
scat("\'Katamarane, Koggen, Karavellen\'");
|
|
|
|
|
skill = SK_SHIPBUILDING;
|
|
|
|
|
break;
|
|
|
|
|
case 11:
|
|
|
|
|
case 12:
|
|
|
|
|
case 13:
|
|
|
|
|
case 14:
|
|
|
|
|
scat("\'Wege der Sterne\'");
|
|
|
|
|
skill = SK_SAILING;
|
|
|
|
|
break;
|
|
|
|
|
case 15:
|
|
|
|
|
case 16:
|
|
|
|
|
case 17:
|
|
|
|
|
scat("\'Nadishahs Kleine Gift- und Kr<4B>uterkunde\'");
|
|
|
|
|
skill = SK_HERBALISM;
|
|
|
|
|
break;
|
|
|
|
|
case 18:
|
|
|
|
|
case 19:
|
|
|
|
|
scat("\'Mandricks Kompendium der Alchemie\'");
|
|
|
|
|
skill = SK_ALCHEMY;
|
|
|
|
|
break;
|
|
|
|
|
case 20:
|
|
|
|
|
case 21:
|
|
|
|
|
case 22:
|
|
|
|
|
case 23:
|
|
|
|
|
scat("\'Die Konstruktion der Burgen und Schl<68>sser von Zentralandune\'");
|
|
|
|
|
skill = SK_BUILDING;
|
|
|
|
|
break;
|
|
|
|
|
case 24:
|
|
|
|
|
case 25:
|
|
|
|
|
case 26:
|
|
|
|
|
case 27:
|
|
|
|
|
scat("\'Die Esse\'");
|
|
|
|
|
skill = SK_ARMORER;
|
|
|
|
|
break;
|
|
|
|
|
case 28:
|
|
|
|
|
case 29:
|
|
|
|
|
case 30:
|
|
|
|
|
case 31:
|
|
|
|
|
scat("\'<EFBFBD>ber die Gewinnung von Erzen\'");
|
|
|
|
|
skill = SK_MINING;
|
|
|
|
|
break;
|
|
|
|
|
case 32:
|
|
|
|
|
case 33:
|
|
|
|
|
case 34:
|
|
|
|
|
case 35:
|
|
|
|
|
scat("\'Barinions Lieder, eine Einf<6E>hrung f<>r Unbedarfte\'");
|
|
|
|
|
skill = SK_ENTERTAINMENT;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scat(". Der Wissensschub ist enorm.");
|
|
|
|
|
addmessage(r, u->faction, buf, MSG_EVENT, ML_IMPORTANT);
|
|
|
|
|
|
2002-02-15 17:13:30 +01:00
|
|
|
|
if (improve_all(u->faction, skill, 3) == 0) {
|
|
|
|
|
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
|
2001-01-25 10:37:55 +01:00
|
|
|
|
get_unit(region * r, unit * u)
|
|
|
|
|
{
|
|
|
|
|
unit *newunit;
|
|
|
|
|
sprintf(buf, "%s entdeck%s ein kleines Dorf. Die meisten H<>user "
|
|
|
|
|
"wurden durch einen <20>ber die Ufer getretenen Flu<6C> zerst<73>rt. Eine "
|
|
|
|
|
"Gruppe der verzweifelten Menschen schlie<69>t sich deiner Partei an.",
|
|
|
|
|
unitname(u), "en\0t" + (3 - 3 * (u->number == 1)));
|
|
|
|
|
|
|
|
|
|
addmessage(r, u->faction, buf, MSG_EVENT, ML_IMPORTANT);
|
|
|
|
|
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 20 + 3, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "Dorfbewohner");
|
|
|
|
|
set_money(newunit, (rand() % 26 + 10) * newunit->number);
|
2002-03-11 22:20:31 +01:00
|
|
|
|
fset(newunit, UFL_ISNEW);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (fval(u, FL_PARTEITARNUNG)) fset(newunit, FL_PARTEITARNUNG);
|
|
|
|
|
switch (rand() % 4) {
|
|
|
|
|
case 0:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_MINING, 1);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
case 1:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_LUMBERJACK, 1);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_CARTMAKER, 1);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
case 3:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_QUARRYING, 1);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
set_item(newunit, I_WAGON, rand() % 2);
|
|
|
|
|
set_item(newunit, I_HORSE, min(get_item(newunit, I_WAGON) * 2, rand() % 5));
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
switch (rterrain(r)) {
|
|
|
|
|
|
|
|
|
|
case T_PLAIN:
|
|
|
|
|
if (!r_isforest(r)) {
|
|
|
|
|
if (get_money(u) / u->number < 100 + rand() % 200)
|
|
|
|
|
return;
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 8 + 2, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "S<EFBFBD>ldner");
|
|
|
|
|
set_money(newunit, (rand() % 80 + 20) * newunit->number);
|
|
|
|
|
|
|
|
|
|
switch (rand() % 4) {
|
|
|
|
|
case 0:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_SWORD, 1+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_SWORD, newunit->number);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_SPEAR, 1+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_SPEAR, newunit->number);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_CROSSBOW, 1+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_CROSSBOW, newunit->number);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_LONGBOW, 1+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_LONGBOW, newunit->number);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (rand() % 100 < 40) {
|
|
|
|
|
set_item(newunit, I_CHAIN_MAIL, rand() % (newunit->number + 1));
|
|
|
|
|
}
|
|
|
|
|
if (rand() % 100 < 30) {
|
|
|
|
|
set_item(newunit, I_HORSE, newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_RIDING, 1+rand()%3);
|
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;
|
|
|
|
|
}
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 6 + 2, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "Waldbewohner");
|
|
|
|
|
set_money(newunit, (rand() % 20 + 10) * newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_LONGBOW, 2+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_LONGBOW, newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_OBSERVATION, 2+rand()%2);
|
|
|
|
|
set_level(newunit, SK_STEALTH, 1+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rand() % 100 < 20) {
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_HERBALISM, 1+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_SWAMP:
|
|
|
|
|
if (eff_skill(u, SK_OBSERVATION, r) <= 3) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 6 + 2, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "Sumpfbewohner");
|
|
|
|
|
set_money(newunit, (rand() % 20 + 10) * newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_SPEAR, 2+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_SPEAR, newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_STEALTH, 2+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_DESERT:
|
|
|
|
|
if (eff_skill(u, SK_RIDING, r) <= 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 12 + 2, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "Berber");
|
|
|
|
|
set_money(newunit, (rand() % 30 + 20) * newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_SWORD, 1+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_SWORD, newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_TRADE, 1+rand()%3);
|
|
|
|
|
set_level(newunit, SK_RIDING, 2+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_HORSE, newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_HORSE_TRAINING, 2+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_HIGHLAND:
|
|
|
|
|
if (eff_skill(u, SK_SWORD, r) <= 1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 8 + 2, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "Hochlandbarbaren");
|
|
|
|
|
set_money(newunit, (rand() % 10 + 20) * newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_SWORD, 1+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_SWORD, newunit->number);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_MOUNTAIN:
|
|
|
|
|
if (eff_skill(u, SK_SWORD, r) <= 1
|
|
|
|
|
|| eff_skill(u, SK_TRADE, r) <= 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 6 + 2, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "Bergbewohner");
|
|
|
|
|
set_money(newunit, (rand() % 40 + 60) * newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_SWORD, 2+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_SWORD, newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_ARMORER, 2+rand()%2);
|
|
|
|
|
set_level(newunit, SK_TRADE, 1+rand()%3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rand() % 100 < 60) {
|
|
|
|
|
set_item(newunit, I_PLATE_ARMOR, newunit->number);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case T_GLACIER:
|
|
|
|
|
if (eff_skill(u, SK_SWORD, r) <= 1
|
|
|
|
|
|| eff_skill(u, SK_TRADE, r) <= 1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
newunit = createunit(r, u->faction, rand() % 4 + 2, u->faction->race);
|
|
|
|
|
set_string(&newunit->name, "Eisleute");
|
|
|
|
|
set_money(newunit, (rand() % 20 + 20) * newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_SWORD, 2+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(newunit, I_SWORD, newunit->number);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(newunit, SK_ARMORER, 2+rand()%2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-10 15:07:29 +01:00
|
|
|
|
u_setfaction(newunit, u->faction);
|
- 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
|
|
|
|
set_racename(&newunit->attribs, get_racename(u->attribs));
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(u->race->flags & RCF_SHAPESHIFT) {
|
- 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
|
|
|
|
newunit->irace = u->irace;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (fval(u, FL_PARTEITARNUNG)) fset(newunit, FL_PARTEITARNUNG);
|
2002-03-11 22:20:31 +01:00
|
|
|
|
fset(u, UFL_ISNEW);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
sprintf(buf, "Pl<EFBFBD>tzlich stolper%c %s <20>ber einige %s. Nach kurzem "
|
|
|
|
|
"Z<EFBFBD>gern entschlie<69>en sich die %s, sich Deiner Partei anzuschlie<69>en.",
|
|
|
|
|
u->number == 1 ? 't' : 'n', unitname(u), newunit->name, newunit->name);
|
|
|
|
|
|
|
|
|
|
addmessage(r, u->faction, buf, MSG_EVENT, ML_IMPORTANT);
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
if (rand() % 100>=ENCCHANCE) return;
|
|
|
|
|
switch (rand() % 3) {
|
|
|
|
|
case 0:
|
|
|
|
|
find_manual(r, u);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
get_unit(r, u);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
get_allies(r, u);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
encounters(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
int n;
|
|
|
|
|
int c;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (rterrain(r) != T_OCEAN && fval(r, RF_ENCOUNTER)) {
|
|
|
|
|
c = 0;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
c += u->number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (c > 0) {
|
|
|
|
|
n = rand() % c;
|
|
|
|
|
u = r->units;
|
|
|
|
|
|
|
|
|
|
for (i = u->number; i < n; i += u->number) {
|
|
|
|
|
u = u->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
encounter(r, u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
chaos(region * r)
|
|
|
|
|
{
|
|
|
|
|
unit *u = NULL, *u2;
|
|
|
|
|
building *b, *b2;
|
|
|
|
|
|
|
|
|
|
if (rand() % 100 < 8) {
|
|
|
|
|
switch (rand() % 3) {
|
|
|
|
|
case 0: /* Untote */
|
|
|
|
|
if (rterrain(r) != T_OCEAN) {
|
|
|
|
|
u = random_unit(r);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u && playerrace(u->race)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sprintf(buf, "%s scheint von einer seltsamen Krankheit befallen.",
|
|
|
|
|
unitname(u));
|
|
|
|
|
addmessage(0, u->faction, buf, MSG_EVENT, ML_IMPORTANT);
|
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;
|
|
|
|
|
switch (rand() % 3) {
|
|
|
|
|
case 0:
|
|
|
|
|
mfac = 100;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), rand() % 8 + 1, new_race[RC_FIREDRAGON]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (u->number == 1) {
|
|
|
|
|
set_string(&u->name, "Feuerdrache");
|
|
|
|
|
} else {
|
|
|
|
|
set_string(&u->name, "Feuerdrachen");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
mfac = 500;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), rand() % 4 + 1, new_race[RC_DRAGON]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (u->number == 1) {
|
|
|
|
|
set_string(&u->name, "Drache");
|
|
|
|
|
} else {
|
|
|
|
|
set_string(&u->name, "Drachen");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
mfac = 1000;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), rand() % 2 + 1, new_race[RC_WYRM]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (u->number == 1) {
|
|
|
|
|
set_string(&u->name, "Wyrm");
|
|
|
|
|
} else {
|
|
|
|
|
set_string(&u->name, "Wyrme");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (mfac) set_money(u, u->number * (rand() % mfac));
|
|
|
|
|
guard(u, GUARD_ALL);
|
|
|
|
|
}
|
|
|
|
|
case 2: /* Terrainver<65>nderung */
|
2001-04-22 20:14:07 +02:00
|
|
|
|
if (!(terrain[rterrain(r)].flags & FORBIDDEN_LAND)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rterrain(r) != T_OCEAN) {
|
|
|
|
|
direction_t dir;
|
|
|
|
|
for (dir=0;dir!=MAXDIRECTIONS;++dir) {
|
|
|
|
|
if (rconnect(r, dir) && rterrain(rconnect(r, dir)) == T_OCEAN) break;
|
|
|
|
|
}
|
|
|
|
|
if (dir!=MAXDIRECTIONS) {
|
|
|
|
|
ship * sh = r->ships;
|
|
|
|
|
while (sh) {
|
|
|
|
|
ship * nsh = sh->next;
|
|
|
|
|
damage_ship(sh, 0.50);
|
|
|
|
|
if (sh->damage >= sh->size * DAMAGE_SCALE) destroy_ship(sh, r);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
sprintf(buf, "Ein gewaltige Flutwelle verschlingt %s und "
|
|
|
|
|
"alle Bewohner.", regionid(r));
|
|
|
|
|
addmessage(r, 0, buf, MSG_EVENT, ML_IMPORTANT);
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
if (rconnect(r, dir) && rterrain(rconnect(r, dir)) != T_OCEAN) break;
|
|
|
|
|
}
|
|
|
|
|
if (dir!=MAXDIRECTIONS) {
|
|
|
|
|
switch (rand() % 8) {
|
|
|
|
|
case 0:
|
|
|
|
|
terraform(r, T_PLAIN);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
terraform(r, T_HIGHLAND);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
terraform(r, T_MOUNTAIN);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
terraform(r, T_GLACIER);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
terraform(r, T_DESERT);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
terraform(r, T_SWAMP);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
chaosfactor(region * r)
|
|
|
|
|
{
|
|
|
|
|
attrib * a = a_find(r->attribs, &at_chaoscount);
|
|
|
|
|
if (!a) return 0;
|
|
|
|
|
return ((double) a->data.i / 1000.0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2001-12-10 01:13:39 +01:00
|
|
|
|
drown(region *r)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (rterrain(r) == T_OCEAN) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
unit ** up = up=&r->units;
|
|
|
|
|
while (*up) {
|
|
|
|
|
unit *u = *up;
|
|
|
|
|
int amphibian_level = fspecial(u->faction, FS_AMPHIBIAN);
|
|
|
|
|
|
2002-01-27 11:40:40 +01:00
|
|
|
|
if (u->ship || u->race == new_race[RC_SPELL]) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
up=&u->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (amphibian_level) {
|
|
|
|
|
int dead = damage_unit(u, "5d1", false, false);
|
|
|
|
|
if (dead) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"drown_amphibian_dead%d:amount%u:unit%r:region",dead, u, r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"drown_amphibian_nodead%u:unit%r:region",u, r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
} else if (!canswim(u)) {
|
|
|
|
|
scale_number(u, 0);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"drown%u:unit%r:region", u, r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
if (*up==u) up=&u->next;
|
|
|
|
|
}
|
|
|
|
|
remove_empty_units_in_region(r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
|
|
|
|
|
rr = rand() % c;
|
|
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
|
{
|
|
|
|
|
attrib *a;
|
|
|
|
|
region *rn;
|
|
|
|
|
unit *u, **up;
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
for (u=r->units; u; u=u->next) {
|
|
|
|
|
f = u->faction;
|
|
|
|
|
freset(f, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
rn = rrandneighbour(r);
|
|
|
|
|
|
|
|
|
|
/* Vulkan-Region verw<72>sten */
|
|
|
|
|
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rsettrees(r, 2, 0);
|
|
|
|
|
rsettrees(r, 1, 0);
|
|
|
|
|
rsettrees(r, 0, 0);
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsettrees(r, 0);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
a = a_find(r->attribs, &at_reduceproduction);
|
|
|
|
|
if (!a) a = a_add(&r->attribs, a_new(&at_reduceproduction));
|
|
|
|
|
|
|
|
|
|
/* Produktion vierteln ... */
|
|
|
|
|
a->data.sa[0] = 25;
|
|
|
|
|
/* F<>r 6-17 Runden */
|
|
|
|
|
a->data.sa[1] = (short)(a->data.sa[1] + 6 + rand()%12);
|
|
|
|
|
|
|
|
|
|
/* Personen bekommen 4W10 Punkte Schaden. */
|
|
|
|
|
|
|
|
|
|
for (up=&r->units; *up;) {
|
|
|
|
|
unit * u = *up;
|
2002-03-11 01:06:14 +01:00
|
|
|
|
int dead = damage_unit(u, "4d10", true, false);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (dead) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"volcano_dead%u:unit%r:region%i:dead", u, r, dead));
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u->faction, FL_DH)) {
|
|
|
|
|
fset(u->faction, FL_DH);
|
|
|
|
|
if (rn) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"volcanooutbreak%r:regionv%r:regionn", r, rn));
|
|
|
|
|
} else {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"volcanooutbreaknn%r:region", r));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (u==*up) up=&u->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove_empty_units_in_region(r);
|
|
|
|
|
|
|
|
|
|
/* Zuf<75>llige Nachbarregion verw<72>sten */
|
|
|
|
|
|
|
|
|
|
if (rn) {
|
|
|
|
|
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rsettrees(r, 2, 0);
|
|
|
|
|
rsettrees(r, 1, 0);
|
|
|
|
|
rsettrees(r, 0, 0);
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsettrees(r, 0);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
a = a_add(&rn->attribs, a_new(&at_reduceproduction));
|
|
|
|
|
if (!a) a = a_add(&r->attribs, a_new(&at_reduceproduction));
|
|
|
|
|
|
|
|
|
|
/* Produktion vierteln ... */
|
|
|
|
|
a->data.sa[0] = 25;
|
|
|
|
|
/* F<>r 6-17 Runden */
|
|
|
|
|
a->data.sa[1] = (short)(a->data.sa[1] + 6 + rand()%12);
|
|
|
|
|
|
|
|
|
|
/* Personen bekommen 3W10 Punkte Schaden. */
|
|
|
|
|
for (up=&rn->units; *up;) {
|
|
|
|
|
unit * u = *up;
|
2002-03-11 01:06:14 +01:00
|
|
|
|
int dead = damage_unit(u, "3d10", true, false);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (dead) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"volcano_dead%u:unit%r:region%i:dead", u, rn, dead));
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u->faction, FL_DH)) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"volcano_dead%u:unit%r:region%i:dead", u, r, dead));
|
|
|
|
|
fset(u->faction, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
if (u==*up) up=&u->next;
|
|
|
|
|
}
|
|
|
|
|
remove_empty_units_in_region(rn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
static void
|
|
|
|
|
melt_iceberg(region *r)
|
|
|
|
|
{
|
|
|
|
|
attrib *a;
|
|
|
|
|
unit *u;
|
|
|
|
|
building *b, *b2;
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
fset(u->faction, FL_DH);
|
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"iceberg_melt%r:region", r));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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) {
|
|
|
|
|
dir = (direction_t)(rand()%MAXDIRECTIONS);
|
|
|
|
|
a = a_add(&r->attribs, make_iceberg(dir));
|
|
|
|
|
} else {
|
|
|
|
|
if (rand()%100 < 20) {
|
|
|
|
|
dir = (direction_t)(rand()%MAXDIRECTIONS);
|
|
|
|
|
a->data.i = dir;
|
|
|
|
|
} else {
|
|
|
|
|
dir = (direction_t)a->data.i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = rconnect(r, dir);
|
|
|
|
|
|
|
|
|
|
if (rc && rterrain(rc) != T_GLACIER && rterrain(rc) != T_ICEBERG
|
|
|
|
|
&& rterrain(rc) != T_ICEBERG_SLEEP) {
|
|
|
|
|
if (rterrain(rc) == T_OCEAN) { /* Eisberg treibt */
|
|
|
|
|
ship *sh, *shn;
|
|
|
|
|
unit *u;
|
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
fset(u->faction, FL_DH);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"iceberg_drift%r:region%d:dir", r, dir));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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. */
|
|
|
|
|
|
|
|
|
|
for (sh = r->ships; sh; sh=sh->next) freset(sh, FL_DH);
|
|
|
|
|
|
|
|
|
|
for (sh = r->ships; sh; sh = sh->next) {
|
|
|
|
|
/* Meldung an Kapit<69>n */
|
|
|
|
|
damage_ship(sh, 0.10);
|
|
|
|
|
fset(sh, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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) {
|
|
|
|
|
fset(rc->ships, FL_DH);
|
|
|
|
|
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;
|
|
|
|
|
if (fval(sh, FL_DH)) {
|
|
|
|
|
u = captain(sh, r);
|
|
|
|
|
if (sh->damage>=sh->size * DAMAGE_SCALE) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u) ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"overrun_by_iceberg_des%h:ship", sh));
|
|
|
|
|
destroy_ship(sh, r);
|
|
|
|
|
} else {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u) ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"overrun_by_iceberg%h:ship", sh));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sh = shn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if (rand()%100 < 20) { /* Eisberg bleibt als Gletscher liegen */
|
|
|
|
|
unit *u;
|
|
|
|
|
|
|
|
|
|
rsetterrain(r, T_GLACIER);
|
|
|
|
|
a_remove(&r->attribs, a);
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
fset(u->faction, FL_DH);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-01-25 10:37:55 +01:00
|
|
|
|
"iceberg_land%r:region", r));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
move_icebergs(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
for (r=regions; r; r=r->next) if (rterrain(r) == T_ICEBERG && !fval(r, RF_DH)) {
|
|
|
|
|
if (rand()%100 < 60) {
|
|
|
|
|
fset(r, RF_DH);
|
|
|
|
|
move_iceberg(r);
|
|
|
|
|
} else if (rand()%100 < 10){
|
|
|
|
|
fset(r, RF_DH);
|
|
|
|
|
melt_iceberg(r);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
create_icebergs(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
|
|
|
|
for (r=regions; r; r=r->next) if (rterrain(r) == T_ICEBERG_SLEEP && rand()%100 < 5) {
|
|
|
|
|
boolean has_ocean_neighbour = false;
|
|
|
|
|
direction_t dir;
|
|
|
|
|
region *rc;
|
|
|
|
|
unit *u;
|
|
|
|
|
|
|
|
|
|
for (dir=0; dir < MAXDIRECTIONS; dir++) {
|
|
|
|
|
rc = rconnect(r, dir);
|
|
|
|
|
if (rc && rterrain(rc) == T_OCEAN) {
|
|
|
|
|
has_ocean_neighbour = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!has_ocean_neighbour) continue;
|
|
|
|
|
|
|
|
|
|
rsetterrain(r, T_ICEBERG);
|
|
|
|
|
|
|
|
|
|
fset(r, RF_DH);
|
|
|
|
|
move_iceberg(r);
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
|
fset(u->faction, FL_DH);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("iceberg_create", "region", r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
void
|
|
|
|
|
godcurse(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
ship *sh, *shn;
|
|
|
|
|
|
|
|
|
|
for(r=regions; r; r=r->next) {
|
|
|
|
|
if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
|
|
|
|
|
unit * u;
|
|
|
|
|
for(u=r->units; u; u=u->next) {
|
2002-02-15 17:13:30 +01:00
|
|
|
|
skill * sv = u->skills;
|
|
|
|
|
while (sv!=u->skills+u->skill_size) {
|
|
|
|
|
int weeks = 1+rand()%3;
|
2002-02-22 20:41:20 +01:00
|
|
|
|
reduce_skill(u, sv, weeks);
|
2002-02-15 17:13:30 +01:00
|
|
|
|
++sv;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-02 22:36:12 +02:00
|
|
|
|
if (rterrain(r) == T_OCEAN) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
for (sh = r->ships; sh;) {
|
|
|
|
|
shn = sh->next;
|
|
|
|
|
damage_ship(sh, 0.10);
|
|
|
|
|
if (sh->damage>=sh->size * DAMAGE_SCALE) {
|
|
|
|
|
unit * u = shipowner(r, sh);
|
|
|
|
|
if (u) ADDMSG(&u->faction->msgs,
|
|
|
|
|
msg_message("godcurse_destroy_ship", "ship", sh));
|
|
|
|
|
destroy_ship(sh, r);
|
|
|
|
|
}
|
|
|
|
|
sh = shn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
randomevents(void)
|
|
|
|
|
{
|
2002-04-12 14:46:16 +02:00
|
|
|
|
faction *f;
|
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
|
|
|
|
|
|
|
|
|
/* Eiseberge */
|
|
|
|
|
for (r=regions; r; r=r->next) freset(r, RF_DH);
|
|
|
|
|
create_icebergs();
|
|
|
|
|
move_icebergs();
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
godcurse();
|
|
|
|
|
|
|
|
|
|
for (r=regions; r; r=r->next) {
|
|
|
|
|
drown(r);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-04-07 10:31:20 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2002-05-01 21:08:32 +02:00
|
|
|
|
curse *c = get_curse(u->attribs, ct_find("orcish"));
|
2002-04-27 22:09:44 +02:00
|
|
|
|
if (c && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) {
|
2002-04-07 10:39:20 +02:00
|
|
|
|
int n;
|
2002-04-07 10:31:20 +02:00
|
|
|
|
int increase = 0;
|
2002-04-27 22:09:44 +02:00
|
|
|
|
int num = get_cursedmen(u, c);
|
2002-05-01 21:08:32 +02:00
|
|
|
|
int prob = curse_geteffect(c);
|
2002-04-07 10:31:20 +02:00
|
|
|
|
|
|
|
|
|
for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) {
|
|
|
|
|
if (rand() % 100 < prob) {
|
|
|
|
|
++increase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (increase) {
|
|
|
|
|
set_number(u, u->number + increase);
|
|
|
|
|
|
|
|
|
|
u->hp += unit_max_hp(u) * increase;
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("orcgrowth",
|
|
|
|
|
"unit amount race", u, increase, u->race));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-02-10 17:04:39 +01:00
|
|
|
|
|
2002-02-10 18:56:03 +01:00
|
|
|
|
#if RACE_ADJUSTMENTS == 0
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Orks vermehren sich */
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
2001-12-10 01:13:39 +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
|
|
|
|
plane * p = rplane(r);
|
|
|
|
|
/* there is a flag for planes without orc growth: */
|
|
|
|
|
if (p && (p->flags & PFL_NOORCGROWTH)) continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2002-04-07 10:31:20 +02:00
|
|
|
|
if ( (u->race == new_race[RC_ORC])
|
2002-03-03 19:13:08 +01:00
|
|
|
|
&& !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) {
|
2002-04-07 10:39:20 +02:00
|
|
|
|
int n;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int increase = 0;
|
2002-04-07 10:31:20 +02:00
|
|
|
|
int num = u->number;
|
|
|
|
|
int prob = 5;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) {
|
|
|
|
|
if (rand() % 100 < prob) {
|
|
|
|
|
++increase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (increase) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->race == new_race[RC_ORC]) {
|
2002-02-06 09:06:02 +01:00
|
|
|
|
int i;
|
|
|
|
|
struct orcskills {
|
|
|
|
|
skill_t skill;
|
|
|
|
|
int level;
|
|
|
|
|
} skills [] = {
|
|
|
|
|
{ SK_SWORD, 1 }, { SK_SPEAR, 1 }, { SK_TACTICS, 0 },
|
|
|
|
|
{ SK_LONGBOW, 0 }, { SK_CROSSBOW, 0 }, { SK_CATAPULT, 0 },
|
|
|
|
|
{ SK_AUSDAUER, 0 }, { NOSKILL, 0 }
|
|
|
|
|
};
|
|
|
|
|
for (i=0;skills[i].skill!=NOSKILL;++i) {
|
2002-03-03 19:13:08 +01:00
|
|
|
|
int k = get_level(u, skills[i].skill);
|
2002-02-06 09:06:02 +01:00
|
|
|
|
change_skill(u, skills[i].skill, increase * max(k, s));
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set_number(u, u->number + increase);
|
|
|
|
|
|
|
|
|
|
u->hp += unit_max_hp(u) * increase;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("orcgrowth",
|
|
|
|
|
"unit amount race", u, increase, u->race));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-02-10 17:04:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2003-06-15 02:01:21 +02:00
|
|
|
|
/* Talentverschiebung: Talente von D<>monen verschieben sich */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->race == new_race[RC_DAEMON]) {
|
2003-03-24 23:42:41 +01:00
|
|
|
|
skill * sv = u->skills;
|
2002-02-15 17:13:30 +01:00
|
|
|
|
while (sv!=u->skills+u->skill_size) {
|
2002-03-11 01:06:14 +01:00
|
|
|
|
if (sv->level>0 && rand() % 100 < 25) {
|
|
|
|
|
int weeks = 1+rand()%3;
|
2002-10-08 08:46:03 +02:00
|
|
|
|
if (rand() % 100 < 40) {
|
|
|
|
|
reduce_skill(u, sv, weeks);
|
|
|
|
|
} else {
|
|
|
|
|
while (weeks--) learn_skill(u, sv->id, 1.0);
|
|
|
|
|
}
|
2003-03-24 23:42:41 +01:00
|
|
|
|
if (sv->old>sv->level) {
|
|
|
|
|
log_printf("%s dropped from %u to %u:%u in %s\n",
|
|
|
|
|
unitname(u), sv->old, sv->level,
|
|
|
|
|
sv->weeks, skillname(sv->id, NULL));
|
|
|
|
|
}
|
2002-02-15 17:13:30 +01:00
|
|
|
|
}
|
|
|
|
|
++sv;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
2002-02-06 09:06:02 +01:00
|
|
|
|
#if !RACE_ADJUSTMENTS
|
|
|
|
|
/* Elfen generieren Wald */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (r->land && !fval(r, RF_MALLORN)) {
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2002-02-06 09:06:02 +01:00
|
|
|
|
int trees = rtrees(r, 2);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int trees = rtrees(r);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int maxgen = (production(r) * MAXPEASANTS_PER_AREA)/8;
|
|
|
|
|
for (u = r->units; u && maxgen > 0; u = u->next) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->race == new_race[RC_ELF]) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (n = u->number; n && maxgen > 0; n--) {
|
|
|
|
|
if (rand() % 1000 < 15) { /* 1.5% Chance */
|
|
|
|
|
trees++;
|
|
|
|
|
}
|
|
|
|
|
maxgen--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rsettrees(r, 2, trees);
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsettrees(r, trees);
|
2002-02-06 09:06:02 +01:00
|
|
|
|
#endif /* GROWING_TREES */
|
|
|
|
|
} /* !RACE_ADJUSTMENTS */
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (u=r->units; u; u=u->next) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (!(u->race->ec_flags & NOGIVE)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
struct building * b = inside_building(u);
|
|
|
|
|
const struct building_type * btype = b?b->type:NULL;
|
2002-03-27 22:49:27 +01:00
|
|
|
|
if (btype == bt_find("blessedstonecircle")) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int n, c = 0;
|
|
|
|
|
for (n=0; n<u->number; n++) if (rand()%100 < 2) {
|
|
|
|
|
change_item(u, I_UNICORN, 1);
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
if (c) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, new_message(u->faction,
|
2001-04-13 16:39:57 +02:00
|
|
|
|
"scunicorn%u:unit%i:amount%X:type",u,c,
|
|
|
|
|
olditemtype[I_UNICORN]->rtype));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Orkifizierte Regionen mutieren und mutieren zur<75>ck */
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (fval(r, RF_ORCIFIED)) {
|
|
|
|
|
direction_t dir;
|
|
|
|
|
int chance = 0;
|
|
|
|
|
for (dir = 0; dir < MAXDIRECTIONS; dir++) {
|
|
|
|
|
region *rc = rconnect(r, dir);
|
|
|
|
|
if (rc && rpeasants(rc) > 0 && !fval(rc, RF_ORCIFIED)) chance += 2;
|
|
|
|
|
}
|
|
|
|
|
if (rand()%100 < chance) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&r->msgs, msg_message("deorcified", "region", r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
freset(r, RF_ORCIFIED);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
attrib *a = a_find(r->attribs, &at_orcification);
|
|
|
|
|
if (a!=NULL) {
|
|
|
|
|
int chance = 0;
|
|
|
|
|
if (rpeasants(r) <= 0) continue;
|
|
|
|
|
chance = (a->data.i*100)/rpeasants(r);
|
|
|
|
|
if (rand()%100 < chance) {
|
|
|
|
|
fset(r, RF_ORCIFIED);
|
|
|
|
|
a_remove(&r->attribs, a);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
ADDMSG(&r->msgs, msg_message("orcified", "region", r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
|
|
|
|
a->data.i -= max(10,a->data.i/10);
|
|
|
|
|
if (a->data.i <= 0) a_remove(&r->attribs, a);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Vulkane qualmen, brechen aus ... */
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
2002-10-20 10:54:37 +02:00
|
|
|
|
if (rterrain(r)==T_VOLCANO_SMOKING && a_find(r->attribs, &at_reduceproduction)) {
|
2002-10-13 13:08:04 +02:00
|
|
|
|
ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r));
|
|
|
|
|
rsetterrain(r, T_VOLCANO);
|
|
|
|
|
} else switch(rterrain(r)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case T_VOLCANO:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (rand()%100 < 4) {
|
|
|
|
|
ADDMSG(&r->msgs, msg_message("volcanostartsmoke", "region", r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsetterrain(r, T_VOLCANO_SMOKING);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case T_VOLCANO_SMOKING:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (rand()%100 < 12) {
|
|
|
|
|
ADDMSG(&r->msgs, msg_message("volcanostopsmoke", "region", r));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsetterrain(r, T_VOLCANO);
|
|
|
|
|
} else if (rand()%100 < 8) {
|
|
|
|
|
volcano_outbreak(r);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Monumente zerfallen, Schiffe verfaulen */
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Drachen und Seeschlangen k<>nnen entstehen */
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit * u;
|
2003-06-18 13:27:04 +02:00
|
|
|
|
message * msg;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rterrain(r) == T_OCEAN && rand()%10000 < 1) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), 1, new_race[RC_SEASERPENT]);
|
2002-02-10 14:23:30 +01:00
|
|
|
|
set_level(u, SK_MAGIC, 4);
|
|
|
|
|
set_level(u, SK_OBSERVATION, 3);
|
|
|
|
|
set_level(u, SK_STEALTH, 2);
|
|
|
|
|
set_level(u, SK_AUSDAUER, 1);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_string(&u->name, "Seeschlange");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((rterrain(r) == T_GLACIER
|
|
|
|
|
|| rterrain(r) == T_SWAMP || rterrain(r) == T_DESERT)
|
|
|
|
|
&& rand() % 10000 < (5 + 100 * chaosfactor(r))) {
|
|
|
|
|
|
|
|
|
|
switch (rand() % 10) {
|
|
|
|
|
case 0:
|
|
|
|
|
case 1:
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
case 4:
|
|
|
|
|
case 5:
|
|
|
|
|
case 6:
|
|
|
|
|
case 7:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), nrand(60, 20) + 1, new_race[RC_FIREDRAGON]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), nrand(30, 20) + 1, new_race[RC_DRAGON]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set_money(u, u->number * (rand() % 500 + 100));
|
2002-02-10 14:23:30 +01:00
|
|
|
|
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);
|
2001-04-14 14:11:45 +02:00
|
|
|
|
log_printf("%d %s in %s.\n", u->number,
|
2001-12-10 01:13:39 +01:00
|
|
|
|
LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL));
|
2001-04-14 14:11:45 +02:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
name_unit(u);
|
|
|
|
|
set_string(&u->lastorder, "WARTEN");
|
2003-06-18 13:27:04 +02:00
|
|
|
|
/* 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",
|
|
|
|
|
NULL, u->race, u->number);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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)) {
|
2003-06-18 13:27:04 +02:00
|
|
|
|
add_message(&f->msgs, msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fset(f, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-06-18 13:27:04 +02:00
|
|
|
|
msg_release(msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Untote k<>nnen entstehen */
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
2001-02-02 09:40:49 +01:00
|
|
|
|
int unburied = deathcount(r);
|
2001-01-31 18:40:53 +01:00
|
|
|
|
|
|
|
|
|
if(is_cursed(r->attribs, C_HOLYGROUND, 0)) continue;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Chance 0.1% * chaosfactor */
|
2001-02-10 11:40:12 +01:00
|
|
|
|
if (r->land && unburied > r->land->peasants / 20 && rand() % 10000 < (100 + 100 * chaosfactor(r))) {
|
- 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
|
|
|
|
/* es ist sinnfrei, wenn irgendwo im Wald 3er-Einheiten Untote entstehen.
|
2001-02-10 11:40:12 +01:00
|
|
|
|
* Lieber sammeln lassen, bis sie mindestens 5% der Bev<EFBFBD>lkerung sind, und
|
|
|
|
|
* dann erst auferstehen. */
|
2001-02-02 09:40:49 +01:00
|
|
|
|
int undead = unburied / (rand() % 2 + 1);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
const race * rc;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int i;
|
|
|
|
|
|
2001-02-02 09:40:49 +01:00
|
|
|
|
if (!undead || r->age < 20) continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
switch(rand()%3) {
|
|
|
|
|
case 0:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rc = new_race[RC_SKELETON]; break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case 1:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rc = new_race[RC_ZOMBIE]; break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
default:
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rc = new_race[RC_GHOUL]; break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION), undead, rc);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if ((rc == new_race[RC_SKELETON] || rc == new_race[RC_ZOMBIE]) && rand()%10 < 4) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_item(u, I_RUSTY_SWORD, undead);
|
|
|
|
|
if (rand()%10 < 3) {
|
|
|
|
|
set_item(u, I_RUSTY_SHIELD, undead);
|
|
|
|
|
}
|
|
|
|
|
if (rand()%10 < 2) {
|
|
|
|
|
set_item(u, I_RUSTY_CHAIN_MAIL, undead);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i=0;i < MAXSKILLS;i++) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (rc->bonus[i] >= 1) {
|
2002-04-14 12:35:00 +02:00
|
|
|
|
set_level(u, (skill_t)i, 1);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
u->hp = unit_max_hp(u) * u->number;
|
|
|
|
|
|
|
|
|
|
deathcounts(r, -undead);
|
|
|
|
|
set_string(&u->lastorder, "WARTEN");
|
|
|
|
|
name_unit(u);
|
|
|
|
|
|
2001-04-14 14:11:45 +02:00
|
|
|
|
log_printf("%d %s in %s.\n", u->number,
|
2001-12-10 01:13:39 +01:00
|
|
|
|
LOC(default_locale, rc_name(u->race, u->number!=1)), regionname(r, NULL));
|
2001-04-14 14:11:45 +02:00
|
|
|
|
|
2001-05-20 23:47:56 +02:00
|
|
|
|
{
|
|
|
|
|
message * msg = msg_message("undeadrise", "region amount", r, undead);
|
|
|
|
|
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);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2001-02-02 09:40:49 +01:00
|
|
|
|
int i = deathcount(r);
|
|
|
|
|
if (i) {
|
|
|
|
|
/* Gr<47>ber verwittern, 3% der Untoten finden die ewige Ruhe */
|
2001-05-20 23:47:56 +02:00
|
|
|
|
deathcounts(r, (int)(-i*0.03));
|
2001-02-02 09:40:49 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r=r->next) {
|
|
|
|
|
for (u=r->units; u; u=u->next) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->faction->no != MONSTER_FACTION
|
|
|
|
|
&& (u->race->flags & RCF_DESERT)) {
|
2002-03-11 22:20:31 +01:00
|
|
|
|
if (fval(u, UFL_ISNEW)) continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rand()%100 < 5) {
|
2002-01-01 21:51:18 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("desertion",
|
|
|
|
|
"unit region", u, r));
|
2001-02-10 15:07:29 +01:00
|
|
|
|
u_setfaction(u, findfaction(MONSTER_FACTION));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-12 14:46:16 +02:00
|
|
|
|
|
|
|
|
|
for (f = factions; f; f=f->next) {
|
|
|
|
|
int level = fspecial(f, FS_LYCANTROPE);
|
|
|
|
|
if(level > 0) {
|
|
|
|
|
for(u = f->units; u; u=u->nextF) {
|
|
|
|
|
if(rand()%100 < 2*level) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("becomewere",
|
|
|
|
|
"unit region", u, u->region));
|
|
|
|
|
fset(u, UFL_WERE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Fr<46>hling, die B<>ume schlagen aus. */
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (fval(r, RF_CHAOTIC) ||(r->x >= -13 && r->x <= -6 && r->y >= 50 && r->y <= 57)) {
|
|
|
|
|
if (woodcount(r) >= 40 && rand()%100 < 33) {
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
int trees = rtrees(r,2);
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int trees = rtrees(r);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int treemen = rand()%(max(50,trees)/3);
|
2001-05-20 23:47:56 +02:00
|
|
|
|
struct message * msg;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
treemen = max(25, treemen);
|
|
|
|
|
woodcounts(r, -40);
|
|
|
|
|
trees = max(0, trees-treemen);
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rsettrees(r, 2, trees);
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsettrees(r, trees);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
|
|
|
|
u = createunit(r, findfaction(MONSTER_FACTION),treemen, new_race[RC_TREEMAN]);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_string(&u->lastorder, "WARTEN");
|
|
|
|
|
/* guard(u, GUARD_ALL); kein auto-guard! erst in monster.c! */
|
2002-02-15 17:13:30 +01:00
|
|
|
|
|
|
|
|
|
set_level(u, SK_OBSERVATION, 2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (u->number == 1)
|
|
|
|
|
set_string(&u->name, "Ein w<>tender Ent");
|
|
|
|
|
else
|
|
|
|
|
set_string(&u->name, "W<EFBFBD>tende Ents");
|
|
|
|
|
|
2001-04-14 14:11:45 +02:00
|
|
|
|
log_printf("%d Ents in %s.\n", u->number, regionname(r, NULL));
|
|
|
|
|
|
2001-05-20 23:47:56 +02:00
|
|
|
|
msg = msg_message("entrise", "region amount", r, u->number);
|
|
|
|
|
add_message(&r->msgs, msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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);
|
2001-05-20 23:47:56 +02:00
|
|
|
|
add_message(&u->faction->msgs, msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2001-05-20 23:47:56 +02:00
|
|
|
|
msg_release(msg);
|
2001-01-25 10:37:55 +01: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) (rand() % 10)) / 100.0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HERBS_ROT
|
|
|
|
|
/* 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;
|
|
|
|
|
const herb_type * htype = resource2herb(itm->type->rtype);
|
|
|
|
|
int n = itm->number;
|
|
|
|
|
double k = n*rot_chance/100.0;
|
|
|
|
|
if (htype!=NULL) {
|
|
|
|
|
n = (int)(min(n, normalvariate(k, k/4)));
|
|
|
|
|
i_change(itmp, itm->type, -n);
|
|
|
|
|
}
|
|
|
|
|
if (itm==*itmp) itmp=&itm->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dissolve_units();
|
|
|
|
|
check_split();
|
2001-12-10 01:13:39 +01:00
|
|
|
|
check_luck();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#if NEW_LAEN
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void growlaen(void) {
|
|
|
|
|
region *r;
|
|
|
|
|
regionlist *Berge=NULL, *rl;
|
|
|
|
|
unit *u;
|
|
|
|
|
int b=0, Laen, z, add;
|
|
|
|
|
short *add_laen;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (!fval(r, RF_CHAOTIC) &&
|
|
|
|
|
rterrain(r) == T_MOUNTAIN)
|
|
|
|
|
{
|
2002-01-09 09:20:33 +01:00
|
|
|
|
add_regionlist(&Berge,r);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
b++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_laen=(short *)malloc(b*sizeof(short));
|
|
|
|
|
memset(add_laen, 0, b*sizeof(short));
|
|
|
|
|
|
|
|
|
|
Laen=b*MAXLAENPERTURN/14; /* Anzahl Berge * MAXLAENPERTURN/2 * Chance pro Berg */
|
|
|
|
|
|
|
|
|
|
while(Laen) { /* Laenverteilung <20>ber alle Berge */
|
|
|
|
|
z = rand()%b;
|
|
|
|
|
add = min(10 + rand() % 30, Laen);
|
|
|
|
|
add_laen[z] = (short)(add_laen[z]+add);
|
|
|
|
|
Laen -= add;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
z=0;
|
|
|
|
|
for (rl=Berge; rl; rl=rl->next, z++) {
|
|
|
|
|
region * r = rl->region;
|
|
|
|
|
if (add_laen[z]>0) {
|
|
|
|
|
if (a_find(rl->region->attribs, &at_laen))
|
|
|
|
|
rsetlaen(rl->region, add_laen[z]+rlaen(rl->region));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
attrib *a=a_new(&at_laen);
|
2001-05-20 23:47:56 +02:00
|
|
|
|
struct message * msg = NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
a_add(&rl->region->attribs, a);
|
|
|
|
|
rsetlaen(rl->region, add_laen[z]);
|
|
|
|
|
|
|
|
|
|
/* Meldungen generieren */
|
|
|
|
|
for (u=r->units;u;u=u->next) freset(u->faction, FL_DH);
|
|
|
|
|
for (u = r->units; u; u = u->next ) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (!fval(u->faction, FL_DH) && eff_skill(u, SK_MINING, rl->region) >= olditemtype[I_LAEN]->minskill)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2001-05-20 23:47:56 +02:00
|
|
|
|
if (!msg) msg = msg_message("unveileog", "unit region", u, rl->region);
|
|
|
|
|
r_addmessage(rl->region, u->faction, msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fset(u->faction, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-05-20 23:47:56 +02:00
|
|
|
|
if (msg) msg_release(msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(add_laen);
|
|
|
|
|
free_regionlist(Berge);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|