2001-01-25 10:37:55 +01:00
|
|
|
|
/* vi: set ts=2:
|
|
|
|
|
*
|
2001-04-16 16:34:19 +02: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>
|
2001-01-30 21:02:06 +01:00
|
|
|
|
#include <eressea.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "laws.h"
|
|
|
|
|
|
2001-02-10 23:02:10 +01:00
|
|
|
|
#include <modules/gmcmd.h>
|
2001-04-26 19:41:06 +02:00
|
|
|
|
#include <modules/infocmd.h>
|
2001-01-30 21:02:06 +01:00
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
/* gamecode includes */
|
|
|
|
|
#include "creation.h"
|
|
|
|
|
#include "economy.h"
|
|
|
|
|
#include "monster.h"
|
|
|
|
|
#include "randenc.h"
|
|
|
|
|
#include "study.h"
|
|
|
|
|
|
2001-01-30 21:02:06 +01:00
|
|
|
|
/* kernel includes */
|
2001-02-03 14:45:35 +01:00
|
|
|
|
#include <alchemy.h>
|
2001-01-30 21:02:06 +01:00
|
|
|
|
#include <border.h>
|
|
|
|
|
#include <faction.h>
|
2001-02-03 14:45:35 +01:00
|
|
|
|
#include <item.h>
|
|
|
|
|
#include <magic.h>
|
2001-01-30 21:02:06 +01:00
|
|
|
|
#include <message.h>
|
2001-02-03 14:45:35 +01:00
|
|
|
|
#include <save.h>
|
|
|
|
|
#include <ship.h>
|
|
|
|
|
#include <skill.h>
|
- 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
|
|
|
|
#include <movement.h>
|
|
|
|
|
#include <spy.h>
|
|
|
|
|
#include <race.h>
|
|
|
|
|
#include <battle.h>
|
|
|
|
|
#include <region.h>
|
|
|
|
|
#include <unit.h>
|
|
|
|
|
#include <plane.h>
|
|
|
|
|
#include <karma.h>
|
|
|
|
|
#include <pool.h>
|
|
|
|
|
#include <building.h>
|
|
|
|
|
#include <group.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include <race.h>
|
|
|
|
|
#include <resources.h>
|
2001-04-29 21:27:42 +02:00
|
|
|
|
#ifdef USE_UGROUPS
|
|
|
|
|
# include <ugroup.h>
|
|
|
|
|
#endif
|
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
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/racename.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include <attributes/raceprefix.h>
|
|
|
|
|
#include <attributes/synonym.h>
|
- 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
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* util includes */
|
|
|
|
|
#include <event.h>
|
|
|
|
|
#include <base36.h>
|
2001-01-30 21:02:06 +01:00
|
|
|
|
#include <goodies.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include <rand.h>
|
2002-03-03 11:51:24 +01:00
|
|
|
|
#include <sql.h>
|
2001-05-20 23:47:56 +02:00
|
|
|
|
#include <util/message.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-04-27 21:40:31 +02:00
|
|
|
|
#include <modules/xecmd.h>
|
|
|
|
|
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef AT_OPTION
|
2001-02-28 19:25:25 +01:00
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/option.h>
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#endif
|
2001-02-28 19:25:25 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* libc includes */
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <assert.h>
|
2001-02-03 14:45:35 +01:00
|
|
|
|
#include <ctype.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-04-14 14:11:45 +02:00
|
|
|
|
#include <attributes/otherfaction.h>
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* - external symbols ------------------------------------------ */
|
|
|
|
|
extern int dropouts[2];
|
|
|
|
|
extern int * age;
|
|
|
|
|
/* - exported global symbols ----------------------------------- */
|
|
|
|
|
boolean nobattle = false;
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
destroyfaction(faction * f)
|
|
|
|
|
{
|
2001-04-14 14:11:45 +02:00
|
|
|
|
region *rc;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
unit *u;
|
|
|
|
|
faction *ff;
|
|
|
|
|
|
|
|
|
|
if( !f->alive ) return;
|
|
|
|
|
|
|
|
|
|
for (u=f->units;u;u=u->nextF) {
|
|
|
|
|
region * r = u->region;
|
|
|
|
|
unit * au;
|
|
|
|
|
int number = 0;
|
|
|
|
|
struct friend {
|
|
|
|
|
struct friend * next;
|
|
|
|
|
int number;
|
|
|
|
|
faction * faction;
|
|
|
|
|
unit * unit;
|
|
|
|
|
} * friends = NULL;
|
|
|
|
|
for (au=r->units;au;au=au->next) if (au->faction!=f) {
|
|
|
|
|
if (allied(u, au->faction, HELP_ALL)) {
|
|
|
|
|
struct friend * nf, ** fr = &friends;
|
|
|
|
|
|
|
|
|
|
while (*fr && (*fr)->faction->no<au->faction->no) fr = &(*fr)->next;
|
|
|
|
|
nf = *fr;
|
|
|
|
|
if (nf==NULL || nf->faction!=au->faction) {
|
|
|
|
|
nf = calloc(sizeof(struct friend), 1);
|
|
|
|
|
nf->next = *fr;
|
|
|
|
|
nf->faction = au->faction;
|
|
|
|
|
nf->unit = au;
|
|
|
|
|
*fr = nf;
|
|
|
|
|
}
|
|
|
|
|
nf->number += au->number;
|
|
|
|
|
number += au->number;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (friends && number) {
|
|
|
|
|
struct friend * nf = friends;
|
|
|
|
|
while (nf) {
|
|
|
|
|
unit * u2 = nf->unit;
|
2002-02-19 21:41:20 +01:00
|
|
|
|
#ifdef NEW_ITEMS
|
2002-02-21 08:36:34 +01:00
|
|
|
|
item * itm = u->items;
|
|
|
|
|
while(itm){
|
|
|
|
|
const item_type * itype = itm->type;
|
|
|
|
|
item * itn = itm->next;
|
2002-02-19 21:41:20 +01:00
|
|
|
|
int n = itm->number;
|
|
|
|
|
n = n * nf->number / number;
|
2002-02-21 08:36:34 +01:00
|
|
|
|
if (n>0) {
|
|
|
|
|
i_change(&u->items, itype, -n);
|
|
|
|
|
i_change(&u2->items, itype, n);
|
|
|
|
|
}
|
|
|
|
|
itm = itn;
|
2002-02-19 21:41:20 +01:00
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
resource_t res;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (res = 0; res <= R_SILVER; ++res) {
|
|
|
|
|
int n = get_resource(u, res);
|
|
|
|
|
if (n<=0) continue;
|
|
|
|
|
n = n * nf->number / number;
|
|
|
|
|
if (n<=0) continue;
|
|
|
|
|
change_resource(u, res, -n);
|
|
|
|
|
change_resource(u2, res, n);
|
|
|
|
|
}
|
2002-02-19 21:41:20 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
number -= nf->number;
|
|
|
|
|
nf = nf->next;
|
|
|
|
|
free(friends);
|
|
|
|
|
friends = nf;
|
|
|
|
|
}
|
|
|
|
|
friends = NULL;
|
2002-02-19 21:41:20 +01:00
|
|
|
|
}
|
|
|
|
|
if (rterrain(r) != T_OCEAN && !!playerrace(u->race)) {
|
|
|
|
|
const race * rc = u->race;
|
|
|
|
|
int p = rpeasants(u->region);
|
|
|
|
|
int m = rmoney(u->region);
|
|
|
|
|
int h = rhorses(u->region);
|
|
|
|
|
|
|
|
|
|
/* Personen gehen nur an die Bauern, wenn sie auch von dort
|
|
|
|
|
* stammen */
|
|
|
|
|
if ((rc->ec_flags & ECF_REC_UNLIMITED)==0) {
|
|
|
|
|
if (rc->ec_flags & ECF_REC_HORSES) { /* Zentauren an die Pferde */
|
|
|
|
|
h += u->number;
|
|
|
|
|
} else if (rc == new_race[RC_URUK]){ /* Orks z<>hlen nur zur H<>lfte */
|
|
|
|
|
p += u->number/2;
|
|
|
|
|
} else {
|
|
|
|
|
p += u->number;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2002-02-19 21:41:20 +01:00
|
|
|
|
m += get_money(u);
|
|
|
|
|
h += get_item(u, I_HORSE);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsetpeasants(r, p);
|
|
|
|
|
rsethorses(r, h);
|
|
|
|
|
rsetmoney(r, m);
|
2002-02-19 21:41:20 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
set_number(u, 0);
|
|
|
|
|
}
|
|
|
|
|
f->alive = 0;
|
2002-02-16 16:16:31 +01:00
|
|
|
|
/* no way! f->units = NULL; */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
handle_event(&f->attribs, "destroy", f);
|
|
|
|
|
for (ff = factions; ff; ff = ff->next) {
|
|
|
|
|
group *g;
|
|
|
|
|
ally *sf, *sfn;
|
|
|
|
|
|
|
|
|
|
/* Alle HELFE f<>r die Partei l<>schen */
|
|
|
|
|
for (sf = ff->allies; sf; sf = sf->next) {
|
|
|
|
|
if (sf->faction == f) {
|
|
|
|
|
removelist(&ff->allies, sf);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(g=ff->groups; g; g=g->next) {
|
|
|
|
|
for (sf = g->allies; sf;) {
|
|
|
|
|
sfn = sf->next;
|
|
|
|
|
if (sf->faction == f) {
|
|
|
|
|
removelist(&g->allies, sf);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sf = sfn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-04-14 14:11:45 +02:00
|
|
|
|
|
|
|
|
|
/* units of other factions that were disguised as this faction
|
|
|
|
|
* have their disguise replaced by ordinary faction hiding. */
|
|
|
|
|
for(rc=regions; rc; rc=rc->next) {
|
|
|
|
|
for(u=rc->units; u; u=u->next) {
|
|
|
|
|
attrib *a = a_find(u->attribs, &at_otherfaction);
|
|
|
|
|
if(!a) continue;
|
2002-03-24 10:40:50 +01:00
|
|
|
|
if (get_otherfaction(a) == f) {
|
2001-04-14 14:11:45 +02:00
|
|
|
|
a_removeall(&u->attribs, &at_otherfaction);
|
|
|
|
|
fset(u, FL_PARTEITARNUNG);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-13 11:42:56 +01:00
|
|
|
|
static void
|
2001-12-10 01:13:39 +01:00
|
|
|
|
restart(unit *u, const race * rc)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2002-04-16 09:17:36 +02:00
|
|
|
|
faction *f = addplayer(u->region, u->faction->email, u->faction->passw, rc, u->faction->locale)->faction;
|
2002-01-13 11:42:56 +01:00
|
|
|
|
unit * nu = f->units;
|
|
|
|
|
strlist ** o=&u->orders;
|
|
|
|
|
|
2002-03-24 12:24:57 +01:00
|
|
|
|
fset(f, FFL_RESTART);
|
2002-03-03 11:51:24 +01:00
|
|
|
|
fprintf(sqlstream, "UPDATE subscriptions set faction='%s' where faction"
|
2002-04-20 22:07:35 +02:00
|
|
|
|
"='%s' and game=%d;\n", itoa36(u->faction->no), itoa36(f->no), GAME_ID);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
f->magiegebiet = u->faction->magiegebiet;
|
2001-04-14 15:10:52 +02:00
|
|
|
|
f->options = u->faction->options;
|
2002-01-13 11:42:56 +01:00
|
|
|
|
freestrlist(nu->orders);
|
|
|
|
|
nu->orders = u->orders;
|
|
|
|
|
u->orders = NULL;
|
|
|
|
|
while (*o) {
|
|
|
|
|
strlist * S = *o;
|
|
|
|
|
if (igetkeyword(S->s, u->faction->locale) == K_RESTART) {
|
|
|
|
|
*o = S->next;
|
|
|
|
|
S->next = NULL;
|
|
|
|
|
freestrlist(S);
|
|
|
|
|
} else {
|
|
|
|
|
o = &S->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
destroyfaction(u->faction);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
checkorders(void)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
puts(" - Warne sp<73>te Spieler...");
|
|
|
|
|
for (f = factions; f; f = f->next)
|
2002-03-03 11:51:24 +01:00
|
|
|
|
if (f->no!=MONSTER_FACTION && turn - f->lastorders == NMRTIMEOUT - 1)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
addstrlist(&f->mistakes,
|
|
|
|
|
"Bitte sende die Befehle n<>chste Runde ein, "
|
|
|
|
|
"wenn du weiterspielen m<>chtest.");
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
is_monstrous(unit * u)
|
|
|
|
|
{
|
2001-12-10 01:13:39 +01:00
|
|
|
|
return (boolean) (u->faction->no == MONSTER_FACTION || !playerrace(u->race));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
get_food(region *r)
|
|
|
|
|
{
|
|
|
|
|
unit *u;
|
|
|
|
|
|
2001-03-04 19:41:27 +01:00
|
|
|
|
/* 1. Versorgung von eigenen Einheiten. Das vorhandene Silber
|
|
|
|
|
* wird zun<EFBFBD>chst so auf die Einheiten aufgeteilt, dass idealerweise
|
|
|
|
|
* jede Einheit genug Silber f<EFBFBD>r ihren Unterhalt hat. */
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
int need = lifestyle(u);
|
|
|
|
|
|
|
|
|
|
/* Erstmal zur<75>cksetzen */
|
|
|
|
|
freset(u, FL_HUNGER);
|
|
|
|
|
|
|
|
|
|
need -= get_money(u);
|
|
|
|
|
if (need > 0) {
|
|
|
|
|
unit *v;
|
|
|
|
|
|
|
|
|
|
for (v = r->units; need && v; v = v->next)
|
2001-03-04 19:41:27 +01:00
|
|
|
|
if (v->faction == u->faction && !is_monstrous(v)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int give = get_money(v) - lifestyle(v);
|
|
|
|
|
give = max(0, give);
|
|
|
|
|
give = min(need, give);
|
|
|
|
|
if (give) {
|
|
|
|
|
change_money(v, -give);
|
|
|
|
|
change_money(u, give);
|
|
|
|
|
need -= give;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-04 19:41:27 +01:00
|
|
|
|
/* 2. Versorgung durch Fremde. Das Silber alliierter Einheiten wird
|
|
|
|
|
* entsprechend verteilt. */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
int need = lifestyle(u);
|
|
|
|
|
|
|
|
|
|
need -= max(0, get_money(u));
|
|
|
|
|
|
|
|
|
|
if (need > 0) {
|
|
|
|
|
unit *v;
|
|
|
|
|
|
|
|
|
|
for (v = r->units; need && v; v = v->next)
|
|
|
|
|
if (v->faction != u->faction && allied(v, u->faction, HELP_MONEY)
|
2001-03-04 19:41:27 +01:00
|
|
|
|
&& !is_monstrous(v)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int give = lifestyle(v);
|
|
|
|
|
give = max(0, get_money(v) - give);
|
|
|
|
|
give = min(need, give);
|
|
|
|
|
|
|
|
|
|
if (give) {
|
|
|
|
|
change_money(v, -give);
|
|
|
|
|
change_money(u, give);
|
|
|
|
|
need -= give;
|
|
|
|
|
add_spende(v->faction, u->faction, give, r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Die Einheit hat nicht genug Geld zusammengekratzt und
|
|
|
|
|
* nimmt Schaden: */
|
|
|
|
|
|
|
|
|
|
if (need) hunger(u, need);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 3. Von den <20>berlebenden das Geld abziehen: */
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
int need = min(get_money(u), lifestyle(u));
|
|
|
|
|
change_money(u, -need);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
live(region * r)
|
|
|
|
|
{
|
|
|
|
|
unit *u, *un;
|
|
|
|
|
|
|
|
|
|
get_food(r);
|
|
|
|
|
|
|
|
|
|
for (u = r->units; u; u = un) {
|
|
|
|
|
/* IUW: age_unit() kann u l<>schen, u->next ist dann
|
|
|
|
|
* undefiniert, also m<EFBFBD>ssen wir hier schon das n<EFBFBD>chste
|
|
|
|
|
* Element bestimmen */
|
|
|
|
|
un = u->next;
|
|
|
|
|
|
|
|
|
|
if (!is_monstrous(u)) {
|
2002-02-15 17:13:30 +01:00
|
|
|
|
int effect = get_effect(u, oldpotiontype[P_FOOL]);
|
|
|
|
|
if (effect > 0) { /* Trank "Dumpfbackenbrot" */
|
|
|
|
|
skill * sv = u->skills, * sb = NULL;
|
|
|
|
|
while (sv!=u->skills+u->skill_size) {
|
|
|
|
|
if (sb==NULL || skill_compare(sv, sb)>0) {
|
|
|
|
|
sb = sv;
|
|
|
|
|
}
|
|
|
|
|
++sv;
|
|
|
|
|
} /* bestes Talent raussuchen */
|
|
|
|
|
if (sb!=NULL) {
|
|
|
|
|
int weeks = min(effect, u->number);
|
2002-02-22 20:41:20 +01:00
|
|
|
|
reduce_skill(u, sb, weeks);
|
2002-02-03 13:56:15 +01:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("dumbeffect",
|
2002-02-15 17:13:30 +01:00
|
|
|
|
"unit weeks skill", u, weeks, (skill_t)sb->id));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} /* sonst Gl<47>ck gehabt: wer nix wei<65>, kann nix vergessen... */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
age_unit(r, u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This procedure calculates the number of emigrating peasants for the given
|
|
|
|
|
* region r. There are two incentives for peasants to emigrate:
|
|
|
|
|
* 1) They prefer the less crowded areas.
|
|
|
|
|
* Example: mountains, 700 peasants (max 1000), 70% inhabited
|
|
|
|
|
* plain, 5000 peasants (max 10000), 50% inhabited
|
|
|
|
|
* 700*(PEASANTSWANDER_WEIGHT/100)*((70-50)/100) peasants wander
|
|
|
|
|
* from mountains to plain.
|
|
|
|
|
* Effect : peasents will leave densely populated regions.
|
|
|
|
|
* 2) Peasants prefer richer neighbour regions.
|
|
|
|
|
* Example: region A, 700 peasants, wealth $10500, $15 per head
|
|
|
|
|
* region B, 2500 peasants, wealth $25000, $10 per head
|
|
|
|
|
* Some peasants will emigrate from B to A because $15 > $10
|
|
|
|
|
* exactly: 2500*(PEASANTSGREED_WEIGHT1/100)*((15-10)/100)
|
|
|
|
|
* Not taken in consideration:
|
|
|
|
|
* - movement because of monsters.
|
|
|
|
|
* - movement because of wars
|
|
|
|
|
* - movement because of low loyalty relating to present parties.
|
|
|
|
|
*/
|
|
|
|
|
|
2002-02-24 20:29:21 +01:00
|
|
|
|
#if NEW_MIGRATION == 1
|
|
|
|
|
|
|
|
|
|
/* Arbeitsversion */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
calculate_emigration(region *r)
|
|
|
|
|
{
|
|
|
|
|
direction_t i;
|
|
|
|
|
int overpopulation = rpeasants(r) - maxworkingpeasants(r);
|
2002-03-03 15:53:59 +01:00
|
|
|
|
int weight[MAXDIRECTIONS], weightall;
|
2002-02-24 20:29:21 +01:00
|
|
|
|
|
2002-04-27 22:09:44 +02:00
|
|
|
|
/* Bauern wandern nur bei <20>berbev<65>lkerung, sonst gar nicht */
|
2002-03-03 15:53:59 +01:00
|
|
|
|
if(overpopulation <= 0) return;
|
|
|
|
|
|
|
|
|
|
weightall = 0;
|
2002-02-24 20:29:21 +01:00
|
|
|
|
|
|
|
|
|
for (i = 0; i != MAXDIRECTIONS; i++) {
|
|
|
|
|
region *rc = rconnect(r,i);
|
|
|
|
|
int w;
|
|
|
|
|
|
2002-03-03 15:53:59 +01:00
|
|
|
|
if (rc == NULL || rterrain(rc) == T_OCEAN) {
|
2002-02-24 20:29:21 +01:00
|
|
|
|
w = 0;
|
|
|
|
|
} else {
|
|
|
|
|
w = rpeasants(rc) - maxworkingpeasants(rc);
|
2002-03-24 09:09:39 +01:00
|
|
|
|
w = max(0,w);
|
2002-03-02 16:26:45 +01:00
|
|
|
|
if(rterrain(rc) == T_VOLCANO || rterrain(rc) == T_VOLCANO_SMOKING) {
|
|
|
|
|
w = w/10;
|
|
|
|
|
}
|
2002-02-24 20:29:21 +01:00
|
|
|
|
}
|
|
|
|
|
weight[i] = w;
|
|
|
|
|
weightall += w;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-03 15:53:59 +01:00
|
|
|
|
if (weightall !=0 ) for (i = 0; i != MAXDIRECTIONS; i++) {
|
|
|
|
|
region *rc;
|
|
|
|
|
if((rc = rconnect(r,i)) != NULL) {
|
|
|
|
|
int wandering_peasants = (overpopulation * weight[i])/weightall;
|
|
|
|
|
if (wandering_peasants > 0) {
|
|
|
|
|
r->land->newpeasants -= wandering_peasants;
|
|
|
|
|
rc->land->newpeasants += wandering_peasants;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-02-24 20:29:21 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
calculate_emigration(region *r)
|
|
|
|
|
{
|
2001-04-08 19:36:50 +02:00
|
|
|
|
direction_t i, j;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int maxpeasants_here;
|
|
|
|
|
int maxpeasants[MAXDIRECTIONS];
|
|
|
|
|
double wfactor, gfactor;
|
|
|
|
|
|
|
|
|
|
/* Vermeidung von DivByZero */
|
|
|
|
|
maxpeasants_here = max(maxworkingpeasants(r),1);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i != MAXDIRECTIONS; i++) {
|
|
|
|
|
region *c = rconnect(r, i);
|
|
|
|
|
if (c && rterrain(c) != T_OCEAN) {
|
|
|
|
|
maxpeasants[i] = maxworkingpeasants(c);
|
|
|
|
|
} else maxpeasants[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* calculate emigration for all directions independently */
|
|
|
|
|
|
|
|
|
|
for (i = 0; i != MAXDIRECTIONS; i++) {
|
|
|
|
|
region * c = rconnect(r, i);
|
|
|
|
|
if (!c) continue;
|
|
|
|
|
if (fval(r, RF_ORCIFIED)==fval(c, RF_ORCIFIED)) {
|
|
|
|
|
if (landregion(rterrain(c)) && landregion(rterrain(r))) {
|
|
|
|
|
int wandering_peasants;
|
2001-04-08 19:36:50 +02:00
|
|
|
|
double vfactor;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* First let's calculate the peasants who wander off to less inhabited
|
|
|
|
|
* regions. wfactor indicates the difference of population denity.
|
|
|
|
|
* Never let more than PEASANTSWANDER_WEIGHT per cent wander off in one
|
|
|
|
|
* direction. */
|
|
|
|
|
wfactor = ((double) rpeasants(r) / maxpeasants_here -
|
|
|
|
|
((double) rpeasants(c) / maxpeasants[i]));
|
|
|
|
|
wfactor = max(wfactor, 0);
|
|
|
|
|
wfactor = min(wfactor, 1);
|
|
|
|
|
|
|
|
|
|
/* Now let's handle the greedy peasants. gfactor indicates the
|
|
|
|
|
* difference of per-head-wealth. Never let more than
|
|
|
|
|
* PEASANTSGREED_WEIGHT per cent wander off in one direction. */
|
|
|
|
|
gfactor = (((double) rmoney(c) / max(rpeasants(c), 1)) -
|
|
|
|
|
((double) rmoney(r) / max(rpeasants(r), 1))) / 500;
|
|
|
|
|
gfactor = max(gfactor, 0);
|
|
|
|
|
gfactor = min(gfactor, 1);
|
|
|
|
|
|
2001-04-08 19:36:50 +02:00
|
|
|
|
/* This calculates the influence of volcanos on peasant
|
|
|
|
|
* migration. */
|
|
|
|
|
|
2002-02-18 23:09:46 +01:00
|
|
|
|
if(rterrain(c) == T_VOLCANO || rterrain(c) == T_VOLCANO_SMOKING) {
|
|
|
|
|
vfactor = 0.10;
|
2001-04-08 19:36:50 +02:00
|
|
|
|
} else {
|
|
|
|
|
vfactor = 1.00;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(j=0; j != MAXDIRECTIONS; j++) {
|
|
|
|
|
region *rv = rconnect(c, j);
|
2002-02-18 23:09:46 +01:00
|
|
|
|
if(rv && (rterrain(rv) == T_VOLCANO || rterrain(rv) == T_VOLCANO_SMOKING)) {
|
2001-04-08 19:36:50 +02:00
|
|
|
|
vfactor *= 0.5;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-24 20:29:21 +01:00
|
|
|
|
wandering_peasants = (int) (rpeasants(r) * (gfactor+wfactor)
|
2001-04-08 19:36:50 +02:00
|
|
|
|
* vfactor * PEASANTSWANDER_WEIGHT / 100.0);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
r->land->newpeasants -= wandering_peasants;
|
|
|
|
|
c->land->newpeasants += wandering_peasants;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-02-24 20:29:21 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
peasants(region * r)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
int glueck;
|
2002-01-27 14:08:47 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Das Geld, da<64> die Bauern erwirtschaftet haben unter expandwork, gibt
|
|
|
|
|
* den Bauern genug f<EFBFBD>r 11 Bauern pro Ebene ohne Wald. Der Wald
|
|
|
|
|
* breitet sich nicht in Gebiete aus, die bebaut werden. */
|
|
|
|
|
|
2002-03-06 21:18:37 +01:00
|
|
|
|
int peasants, n, i, satiated, money;
|
2002-03-02 16:26:45 +01:00
|
|
|
|
#if PEASANTS_DO_NOT_STARVE == 0
|
2002-03-06 21:18:37 +01:00
|
|
|
|
int dead;
|
2002-03-02 16:26:45 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
attrib * a;
|
|
|
|
|
|
|
|
|
|
/* Bauern vermehren sich */
|
|
|
|
|
|
|
|
|
|
/* Bis zu 1000 Bauern k<>nnen Zwillinge bekommen oder 1000 Bauern
|
|
|
|
|
* wollen nicht! */
|
|
|
|
|
|
|
|
|
|
a = a_find(r->attribs, &at_peasantluck);
|
|
|
|
|
if (!a) {
|
|
|
|
|
glueck = 0;
|
|
|
|
|
} else {
|
|
|
|
|
glueck = a->data.i * 1000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
peasants = rpeasants(r);
|
|
|
|
|
|
|
|
|
|
for (n = peasants; n; n--) {
|
|
|
|
|
if (glueck >= 0) { /* Sonst keine Vermehrung */
|
2002-02-03 13:56:15 +01:00
|
|
|
|
if (rand() % 10000 < PEASANTGROWTH) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if ((float) peasants
|
|
|
|
|
/ ((float) production(r) * MAXPEASANTS_PER_AREA)
|
|
|
|
|
< 0.9 || rand() % 100 < PEASANTFORCE) {
|
|
|
|
|
peasants++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
glueck++;
|
|
|
|
|
|
|
|
|
|
if (glueck > 0) { /* Doppelvermehrung */
|
2002-01-27 14:08:47 +01:00
|
|
|
|
for(i=0; i<PEASANTLUCK; i++) {
|
|
|
|
|
if (rand() % 10000 < PEASANTGROWTH)
|
|
|
|
|
peasants++;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
glueck--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Alle werden satt, oder halt soviele f<>r die es auch Geld gibt */
|
|
|
|
|
|
|
|
|
|
money = rmoney(r);
|
|
|
|
|
satiated = min(peasants, money / MAINTENANCE);
|
|
|
|
|
rsetmoney(r, money - satiated * MAINTENANCE);
|
|
|
|
|
|
|
|
|
|
/* Von denjenigen, die nicht satt geworden sind, verhungert der
|
|
|
|
|
* Gro<EFBFBD>teil. dead kann nie gr<EFBFBD><EFBFBD>er als rpeasants(r) - satiated werden,
|
|
|
|
|
* so dass rpeasants(r) >= 0 bleiben mu<EFBFBD>. */
|
|
|
|
|
|
|
|
|
|
/* Es verhungert maximal die unterern<72>hrten Bev<65>lkerung. */
|
|
|
|
|
|
2002-03-03 23:23:14 +01:00
|
|
|
|
#if PEASANTS_DO_NOT_STARVE == 0
|
2001-01-25 10:37:55 +01:00
|
|
|
|
dead = 0;
|
|
|
|
|
for (n = min((peasants - satiated), rpeasants(r)); n; n--)
|
|
|
|
|
if (rand() % 100 > STARVATION_SURVIVAL)
|
|
|
|
|
dead++;
|
|
|
|
|
|
|
|
|
|
if(dead > 0) {
|
2001-05-20 23:47:56 +02:00
|
|
|
|
message * msg = add_message(&r->msgs, msg_message("phunger", "dead", dead));
|
|
|
|
|
msg_release(msg);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
peasants -= dead;
|
|
|
|
|
}
|
2002-02-24 20:32:48 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsetpeasants(r, peasants);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
typedef struct migration {
|
|
|
|
|
struct migration * next;
|
|
|
|
|
region * r;
|
|
|
|
|
int horses;
|
|
|
|
|
int trees;
|
|
|
|
|
} migration;
|
|
|
|
|
|
|
|
|
|
#define MSIZE 1023
|
|
|
|
|
migration * migrants[MSIZE];
|
|
|
|
|
migration * free_migrants;
|
|
|
|
|
|
|
|
|
|
static migration *
|
|
|
|
|
get_migrants(region * r)
|
|
|
|
|
{
|
|
|
|
|
int key = region_hashkey(r);
|
|
|
|
|
int index = key % MSIZE;
|
|
|
|
|
migration * m = migrants[index];
|
|
|
|
|
while (m && m->r != r)
|
|
|
|
|
m = m->next;
|
|
|
|
|
if (m == NULL) {
|
|
|
|
|
/* Es gibt noch keine Migration. Also eine erzeugen
|
|
|
|
|
*/
|
|
|
|
|
m = free_migrants;
|
|
|
|
|
if (!m) m = calloc(1, sizeof(migration));
|
|
|
|
|
else {
|
|
|
|
|
free_migrants = free_migrants->next;
|
|
|
|
|
m->horses = 0;
|
|
|
|
|
m->trees = 0;
|
|
|
|
|
}
|
|
|
|
|
m->r = r;
|
|
|
|
|
m->next = migrants[index];
|
|
|
|
|
migrants[index] = m;
|
|
|
|
|
}
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
migrate(region * r)
|
|
|
|
|
{
|
|
|
|
|
int key = region_hashkey(r);
|
|
|
|
|
int index = key % MSIZE;
|
|
|
|
|
migration ** hp = &migrants[index];
|
|
|
|
|
fset(r, RF_MIGRATION);
|
|
|
|
|
while (*hp && (*hp)->r != r) hp = &(*hp)->next;
|
|
|
|
|
if (*hp) {
|
|
|
|
|
migration * m = *hp;
|
|
|
|
|
rsethorses(r, rhorses(r) + m->horses);
|
|
|
|
|
/* Was macht das denn hier?
|
|
|
|
|
* Baumwanderung wird in trees() gemacht.
|
|
|
|
|
* wer fragt das? Die Baumwanderung war abh<EFBFBD>ngig von der
|
|
|
|
|
* Auswertungsreihenfolge der regionen,
|
|
|
|
|
* das hatte ich ge<EFBFBD>ndert. jemand hat es wieder gel<EFBFBD>scht, toll.
|
|
|
|
|
* ich habe es wieder aktiviert, mu<EFBFBD> getestet werden.
|
|
|
|
|
*/
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES == 0
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsettrees(r, rtrees(r) + m->trees);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
*hp = m->next;
|
|
|
|
|
m->next = free_migrants;
|
|
|
|
|
free_migrants = m;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
horses(region * r)
|
|
|
|
|
{
|
2001-12-10 01:13:39 +01:00
|
|
|
|
int horses, maxhorses;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
direction_t n;
|
|
|
|
|
|
|
|
|
|
/* Logistisches Wachstum, Optimum bei halbem Maximalbesatz. */
|
2001-12-10 01:13:39 +01:00
|
|
|
|
maxhorses = maxworkingpeasants(r)/10;
|
|
|
|
|
maxhorses = max(0, maxhorses);
|
|
|
|
|
horses = rhorses(r);
|
|
|
|
|
if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
|
|
|
|
|
rsethorses(r, (int)(horses*0.9));
|
2002-05-01 21:08:32 +02:00
|
|
|
|
} else if (maxhorses > 0) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
int i;
|
2002-05-01 21:08:32 +02:00
|
|
|
|
int growth = (int)((RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses-horses))/maxhorses);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
if(a_find(r->attribs, &at_horseluck)) growth *= 2;
|
|
|
|
|
/* printf("Horses: <%d> %d -> ", growth, horses); */
|
|
|
|
|
for(i = 0; i < horses; i++) {
|
|
|
|
|
if(rand()%10000 < growth) horses++;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* printf("%d\n", horses); */
|
|
|
|
|
rsethorses(r, horses);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Pferde wandern in Nachbarregionen.
|
|
|
|
|
* Falls die Nachbarregion noch berechnet
|
|
|
|
|
* werden mu<EFBFBD>, wird eine migration-Struktur gebildet,
|
|
|
|
|
* die dann erst in die Berechnung der Nachbarstruktur einflie<EFBFBD>t.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
for(n = 0; n != MAXDIRECTIONS; n++) {
|
|
|
|
|
region * r2 = rconnect(r, n);
|
|
|
|
|
if(r2 && (terrain[r2->terrain].flags & WALK_INTO)) {
|
|
|
|
|
int pt = (rhorses(r) * HORSEMOVE)/100;
|
|
|
|
|
pt = (int)normalvariate(pt, pt/4.0);
|
|
|
|
|
pt = max(0, pt);
|
|
|
|
|
if (fval(r2, RF_MIGRATION))
|
|
|
|
|
rsethorses(r2, rhorses(r2) + pt);
|
|
|
|
|
else {
|
|
|
|
|
migration * nb;
|
|
|
|
|
/* haben wir die Migration schonmal benutzt?
|
|
|
|
|
* wenn nicht, m<EFBFBD>ssen wir sie suchen.
|
|
|
|
|
* Wandernde Pferde vermehren sich nicht.
|
|
|
|
|
*/
|
|
|
|
|
nb = get_migrants(r2);
|
|
|
|
|
nb->horses += pt;
|
|
|
|
|
}
|
|
|
|
|
/* Wandernde Pferde sollten auch abgezogen werden */
|
|
|
|
|
rsethorses(r, rhorses(r) - pt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
assert(rhorses(r) >= 0);
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
count_race(const region *r, const race *rc)
|
|
|
|
|
{
|
|
|
|
|
unit *u;
|
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
|
|
for(u = r->units; u; u=u->next)
|
|
|
|
|
if(u->race == rc) c += u->number;
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern attrib_type at_germs;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
trees(region * r, const int current_season, const int last_weeks_season)
|
|
|
|
|
{
|
|
|
|
|
int growth, grownup_trees, i, seeds, sprout, seedchance;
|
|
|
|
|
direction_t d;
|
|
|
|
|
attrib *a;
|
|
|
|
|
|
|
|
|
|
if(current_season == SEASON_SUMMER || current_season == SEASON_AUTUMN) {
|
|
|
|
|
int elves = count_race(r,new_race[RC_ELF]);
|
|
|
|
|
|
|
|
|
|
a = a_find(r->attribs, &at_germs);
|
|
|
|
|
if(a && last_weeks_season == SEASON_SPRING) {
|
|
|
|
|
/* ungekeimte Samen bleiben erhalten, Spr<70><72>linge wachsen */
|
|
|
|
|
sprout = min(a->data.sa[1], rtrees(r, 1));
|
|
|
|
|
/* aus dem gesamt Spr<70><72>lingepool abziehen */
|
|
|
|
|
rsettrees(r, 1, rtrees(r, 1) - sprout);
|
|
|
|
|
/* zu den B<>umen hinzuf<75>gen */
|
|
|
|
|
rsettrees(r, 2, rtrees(r, 2) + sprout);
|
|
|
|
|
|
|
|
|
|
a_removeall(&r->attribs, &at_germs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
|
|
|
|
|
rsettrees(r, 1, (int)(rtrees(r, 1) * 0.9));
|
|
|
|
|
rsettrees(r, 2, (int)(rtrees(r, 2) * 0.9));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(production(r) <= 0) return;
|
|
|
|
|
|
2002-03-03 12:52:22 +01:00
|
|
|
|
/* Grundchance 1.0% */
|
2002-04-21 11:27:18 +02:00
|
|
|
|
seedchance = (int)(FORESTGROWTH * RESOURCE_QUANTITY);
|
2002-03-03 12:52:22 +01:00
|
|
|
|
/* Jeder Elf in der Region erh<72>ht die Chance um 0.0008%. */
|
|
|
|
|
seedchance += (min(elves, (production(r)*MAXPEASANTS_PER_AREA)/8)) * 8;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
grownup_trees = rtrees(r, 2);
|
|
|
|
|
seeds = 0;
|
|
|
|
|
|
|
|
|
|
for(i=0;i<grownup_trees;i++) {
|
2002-03-03 12:52:22 +01:00
|
|
|
|
if(rand()%1000000 < seedchance) seeds++;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
rsettrees(r, 0, rtrees(r, 0) + seeds);
|
|
|
|
|
|
|
|
|
|
/* B<>ume breiten sich in Nachbarregionen aus. */
|
|
|
|
|
|
|
|
|
|
/* Gesamtzahl der Samen:
|
|
|
|
|
* bis zu 6% (FORESTGROWTH*3) der B<EFBFBD>ume samen in die Nachbarregionen */
|
2002-03-03 13:04:03 +01:00
|
|
|
|
seeds = (rtrees(r, 2) * FORESTGROWTH * 3)/1000000;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
for (d=0;d!=MAXDIRECTIONS;++d) {
|
|
|
|
|
region * r2 = rconnect(r, d);
|
|
|
|
|
if (r2 && (terrain[r2->terrain].flags & WALK_INTO)) {
|
|
|
|
|
/* Eine Landregion, wir versuchen Samen zu verteilen:
|
|
|
|
|
* Die Chance, das Samen ein St<EFBFBD>ck Boden finden, in dem sie
|
|
|
|
|
* keimen k<EFBFBD>nnen, h<EFBFBD>ngt von der Bewuchsdichte und der
|
|
|
|
|
* verf<EFBFBD>gbaren Fl<EFBFBD>che ab. In Gletschern gibt es weniger
|
|
|
|
|
* M<EFBFBD>glichkeiten als in Ebenen. */
|
|
|
|
|
sprout = 0;
|
2002-03-03 13:04:03 +01:00
|
|
|
|
seedchance = (100 * maxworkingpeasants(r2)) / terrain[r2->terrain].production_max;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
for(i=0; i<seeds/MAXDIRECTIONS; i++) {
|
|
|
|
|
if(rand()%10000 < seedchance) sprout++;
|
|
|
|
|
}
|
|
|
|
|
rsettrees(r2, 0, rtrees(r2, 0) + sprout);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if(current_season == SEASON_SPRING) {
|
|
|
|
|
|
|
|
|
|
if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) return;
|
|
|
|
|
|
|
|
|
|
/* in at_germs merken uns die Zahl der Samen und Spr<70><72>linge, die
|
|
|
|
|
* dieses Jahr <EFBFBD>lter werden d<EFBFBD>rfen, damit nicht ein Same im selben
|
|
|
|
|
* Zyklus zum Baum werden kann */
|
|
|
|
|
a = a_find(r->attribs, &at_germs);
|
|
|
|
|
if(!a) {
|
|
|
|
|
a = a_add(&r->attribs, a_new(&at_germs));
|
|
|
|
|
a->data.sa[0] = (short)rtrees(r, 0);
|
|
|
|
|
a->data.sa[1] = (short)rtrees(r, 1);
|
|
|
|
|
}
|
|
|
|
|
/* wir haben 6 Wochen zum wachsen, jeder Same/Spro<72> hat 18% Chance
|
|
|
|
|
* zu wachsen, damit sollten nach 5-6 Wochen alle gewachsen sein */
|
|
|
|
|
growth = 1800;
|
|
|
|
|
|
|
|
|
|
/* Samenwachstum */
|
|
|
|
|
|
|
|
|
|
/* Raubbau abfangen, es d<>rfen nie mehr Samen wachsen, als aktuell
|
|
|
|
|
* in der Region sind */
|
|
|
|
|
seeds = min(a->data.sa[0], rtrees(r, 0));
|
|
|
|
|
sprout = 0;
|
|
|
|
|
|
|
|
|
|
for(i=0;i<seeds;i++) {
|
|
|
|
|
if(rand()%10000 < growth) sprout++;
|
|
|
|
|
}
|
|
|
|
|
/* aus dem Samenpool dieses Jahres abziehen */
|
|
|
|
|
a->data.sa[0] = (short)(seeds - sprout);
|
|
|
|
|
/* aus dem gesamt Samenpool abziehen */
|
|
|
|
|
rsettrees(r, 0, rtrees(r, 0) - sprout);
|
|
|
|
|
/* zu den Spr<70><72>linge hinzuf<75>gen */
|
|
|
|
|
rsettrees(r, 1, rtrees(r, 1) + sprout);
|
|
|
|
|
|
|
|
|
|
/* Baumwachstum */
|
|
|
|
|
|
|
|
|
|
/* hier gehen wir davon aus, das Jungb<67>ume nicht ohne weiteres aus
|
|
|
|
|
* der Region entfernt werden k<EFBFBD>nnen, da Jungb<EFBFBD>ume in der gleichen
|
|
|
|
|
* Runde nachwachsen, wir also nicht mehr zwischen diesj<EFBFBD>hrigen und
|
|
|
|
|
* 'alten' Jungb<EFBFBD>umen unterscheiden k<EFBFBD>nnten */
|
|
|
|
|
sprout = min(a->data.sa[1], rtrees(r, 1));
|
|
|
|
|
grownup_trees = 0;
|
|
|
|
|
|
|
|
|
|
for(i=0;i<sprout;i++) {
|
|
|
|
|
if(rand()%10000 < growth) grownup_trees++;
|
|
|
|
|
}
|
|
|
|
|
/* aus dem Spr<70><72>lingepool dieses Jahres abziehen */
|
|
|
|
|
a->data.sa[1] = (short)(sprout - grownup_trees);
|
|
|
|
|
/* aus dem gesamt Spr<70><72>lingepool abziehen */
|
|
|
|
|
rsettrees(r, 1, rtrees(r, 1) - grownup_trees);
|
|
|
|
|
/* zu den B<>umen hinzuf<75>gen */
|
|
|
|
|
rsettrees(r, 2, rtrees(r, 2) + grownup_trees);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Jetzt die Kr<4B>utervermehrung. Vermehrt wird logistisch:
|
|
|
|
|
*
|
|
|
|
|
* Jedes Kraut hat eine Wahrscheinlichkeit von (100-(vorhandene
|
|
|
|
|
* Kr<EFBFBD>uter))% sich zu vermehren. */
|
|
|
|
|
if(current_season == SEASON_SPRING || current_season == SEASON_SUMMER
|
|
|
|
|
|| current_season == SEASON_AUTUMN)
|
|
|
|
|
{
|
|
|
|
|
for(i = rherbs(r); i > 0; i--) {
|
|
|
|
|
if (rand()%100 < (100-rherbs(r))) rsetherbs(r, (short)(rherbs(r)+1));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
trees(region * r)
|
|
|
|
|
{
|
2001-12-10 01:13:39 +01:00
|
|
|
|
int i, maxtrees;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int tree = rtrees(r);
|
|
|
|
|
direction_t d;
|
|
|
|
|
|
|
|
|
|
/* B<>ume vermehren sich. m ist die Anzahl B<>ume, f<>r die es Land
|
|
|
|
|
* gibt. Der Wald besiedelt keine bebauten Gebiete, wird den Pferden
|
|
|
|
|
* aber Land wegnehmen. Gibt es zuviele Bauern, werden sie den Wald
|
|
|
|
|
* nicht f<EFBFBD>llen, sondern verhungern. Der Wald kann nur von Spielern gef<EFBFBD>llt
|
|
|
|
|
* werden! Der Wald wandert nicht. Auch bei magischen Terrainver<EFBFBD>nderungen
|
|
|
|
|
* darf m nicht negativ werden! */
|
|
|
|
|
|
|
|
|
|
if(production(r) <= 0) return;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
maxtrees = production(r) - rpeasants(r)/MAXPEASANTS_PER_AREA;
|
|
|
|
|
maxtrees = max(0, maxtrees);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Solange es noch freie Pl<50>tze gibt, darf jeder Baum versuchen, sich
|
|
|
|
|
* fortzupflanzen. Da B<EFBFBD>ume nicht sofort eingehen, wenn es keinen
|
|
|
|
|
* Platz gibt (wie zB. die Pferde), darf nicht einfach drauflos vermehrt
|
|
|
|
|
* werden und dann ein min () gemacht werden, sondern es mu<EFBFBD> auf diese
|
|
|
|
|
* Weise vermehrt werden. */
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
|
|
|
|
|
tree = (int)(tree*0.9);
|
|
|
|
|
} else if(maxtrees > 0) {
|
|
|
|
|
int growth = (int)((FORESTGROWTH * 200 * ((maxtrees*1.2)-tree))/maxtrees);
|
|
|
|
|
growth = max(FORESTGROWTH*50, growth);
|
|
|
|
|
growth = min(FORESTGROWTH*400, growth);
|
|
|
|
|
/* printf("Trees: <%d> %d -> ", growth, tree); */
|
|
|
|
|
for(i=0;i<tree;i++) {
|
|
|
|
|
if(rand()%10000 < growth) tree++;
|
|
|
|
|
}
|
|
|
|
|
/* printf("%d (max: %d)\n", tree, maxtrees); */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* B<>ume breiten sich in Nachbarregionen aus.
|
|
|
|
|
* warnung: fr<EFBFBD>her kamen b<EFBFBD>ume aus nachbarregionen, heute
|
|
|
|
|
* gehen sie von der aktuellen in die benachbarten.
|
|
|
|
|
* Die Chance, das ein Baum in eine Region r2 einwandert, ist
|
|
|
|
|
* (production-rtrees(r2))/10000.
|
|
|
|
|
* Die Richtung, in der sich ein Baum vermehrt, ist zuf<EFBFBD>llig.
|
|
|
|
|
* Es ibt also genausoviel Versuche, in einen Geltscher zu
|
|
|
|
|
* wandern, wie in eine ebene - nur halt weniger Erfolge.
|
|
|
|
|
* Die Summe der Versuche ist rtrees(r), jeder Baum
|
|
|
|
|
* versucht es also einmal pro Woche, mit maximal 10% chance
|
|
|
|
|
* (wenn ein voller wald von lauter leeren ebenen umgeben ist)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
for (d=0;d!=MAXDIRECTIONS;++d) {
|
|
|
|
|
region * r2 = rconnect(r, d);
|
|
|
|
|
if (r2
|
|
|
|
|
&& (terrain[r2->terrain].flags & WALK_INTO)
|
|
|
|
|
&& fval(r2, RF_MALLORN) == fval(r, RF_MALLORN)) {
|
|
|
|
|
/* Da hier rtrees(r2) abgefragt wird, macht es einen Unterschied,
|
|
|
|
|
* ob das wachstum in r2 schon stattgefunden hat, oder nicht.
|
|
|
|
|
* leider nicht einfach zu verhindern */
|
|
|
|
|
int pt = (production(r2)-rtrees(r2));
|
|
|
|
|
pt = tree*max(0, pt) /
|
|
|
|
|
(MAXDIRECTIONS*terrain[T_PLAIN].production_max*10);
|
|
|
|
|
if (fval(r2, RF_MIGRATION))
|
|
|
|
|
rsettrees(r2, rtrees(r2) + pt);
|
|
|
|
|
else {
|
|
|
|
|
migration * nb;
|
|
|
|
|
/* haben wir die Migration schonmal benutzt?
|
|
|
|
|
* wenn nicht, m<EFBFBD>ssen wir sie suchen.
|
|
|
|
|
* Wandernde Pferde vermehren sich nicht.
|
|
|
|
|
*/
|
|
|
|
|
nb = get_migrants(r2);
|
|
|
|
|
nb->trees += pt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rsettrees(r, tree);
|
|
|
|
|
assert(tree >= 0);
|
|
|
|
|
|
|
|
|
|
/* Jetzt die Kr<4B>utervermehrung. Vermehrt wird logistisch:
|
|
|
|
|
*
|
|
|
|
|
* Jedes Kraut hat eine Wahrscheinlichkeit von (100-(vorhandene
|
|
|
|
|
* Kr<EFBFBD>uter))% sich zu vermehren. */
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
for(i = rherbs(r); i > 0; i--) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rand()%100 < (100-rherbs(r))) rsetherbs(r, (short)(rherbs(r)+1));
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if NEW_RESOURCEGROWTH == 0
|
2001-12-10 01:13:39 +01:00
|
|
|
|
extern attrib_type at_laen;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
iron(region * r)
|
|
|
|
|
{
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) return;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifndef NO_GROWTH
|
|
|
|
|
if (rterrain(r) == T_MOUNTAIN) {
|
|
|
|
|
rsetiron(r, riron(r) + IRONPERTURN);
|
|
|
|
|
#if !NEW_LAEN
|
|
|
|
|
if(a_find(r->attribs, &at_laen)) {
|
|
|
|
|
rsetlaen(r, rlaen(r) + rand() % MAXLAENPERTURN);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-12-10 01:13:39 +01:00
|
|
|
|
} else if (rterrain(r) == T_GLACIER || rterrain(r) == T_ICEBERG_SLEEP) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rsetiron(r, min(MAXGLIRON, riron(r)+GLIRONPERTURN));
|
|
|
|
|
}
|
|
|
|
|
#endif
|
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 /* NEW_RESOURCEGROWTH */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
extern int season(int turn);
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
demographics(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
int current_season = season(turn);
|
|
|
|
|
int last_weeks_season = season(turn-1);
|
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
live(r);
|
|
|
|
|
/* check_split_dragons(); */
|
|
|
|
|
|
|
|
|
|
if (rterrain(r) != T_OCEAN) {
|
|
|
|
|
/* die Nachfrage nach Produkten steigt. */
|
|
|
|
|
#ifdef NEW_ITEMS
|
|
|
|
|
struct demand * dmd;
|
|
|
|
|
if (r->land) for (dmd=r->land->demands;dmd;dmd=dmd->next) {
|
|
|
|
|
if (dmd->value>0 && dmd->value < MAXDEMAND) {
|
|
|
|
|
int rise = DMRISE;
|
2002-03-27 22:49:27 +01:00
|
|
|
|
if (buildingtype_exists(r, bt_find("harbour"))) rise = DMRISEHAFEN;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rand() % 100 < rise) dmd->value++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
item_t n;
|
|
|
|
|
for (n = 0; n != MAXLUXURIES; n++) {
|
|
|
|
|
int d = rdemand(r, n);
|
|
|
|
|
if (d > 0 && d < MAXDEMAND) {
|
2001-03-04 19:41:27 +01:00
|
|
|
|
if (buildingtype_exists(r, &bt_harbour)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rand() % 100 < DMRISEHAFEN) {
|
|
|
|
|
d++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (rand() % 100 < DMRISE) {
|
|
|
|
|
d++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rsetdemand(r, n, (char)d);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/* Seuchen erst nachdem die Bauern sich vermehrt haben
|
|
|
|
|
* und gewandert sind */
|
|
|
|
|
|
|
|
|
|
calculate_emigration(r);
|
|
|
|
|
peasants(r);
|
|
|
|
|
plagues(r, false);
|
|
|
|
|
|
|
|
|
|
r->age++;
|
|
|
|
|
horses(r);
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(current_season != SEASON_WINTER) {
|
|
|
|
|
trees(r, current_season, last_weeks_season);
|
|
|
|
|
}
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
trees(r);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if NEW_RESOURCEGROWTH
|
2001-12-10 01:13:39 +01:00
|
|
|
|
update_resources(r);
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#else
|
|
|
|
|
iron(r);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
migrate(r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (free_migrants) {
|
|
|
|
|
migration * m = free_migrants->next;
|
|
|
|
|
free(free_migrants);
|
|
|
|
|
free_migrants = m;
|
|
|
|
|
};
|
|
|
|
|
putchar('\n');
|
|
|
|
|
|
|
|
|
|
remove_empty_units();
|
|
|
|
|
|
|
|
|
|
puts(" - Einwanderung...");
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
if (landregion(rterrain(r))) {
|
|
|
|
|
int rp = rpeasants(r) + r->land->newpeasants;
|
|
|
|
|
rsetpeasants(r, max(0, rp));
|
|
|
|
|
/* Wenn keine Bauer da ist, soll auch kein Geld da sein */
|
|
|
|
|
/* Martin */
|
|
|
|
|
if (rpeasants(r) == 0)
|
|
|
|
|
rsetmoney(r, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
checkorders();
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
modify(int i)
|
|
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
c = i * 2 / 3;
|
|
|
|
|
|
|
|
|
|
if (c >= 1) {
|
|
|
|
|
return (c + rand() % c);
|
|
|
|
|
} else {
|
|
|
|
|
return (i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
inactivefaction(faction * f)
|
|
|
|
|
{
|
|
|
|
|
FILE *inactiveFILE;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
char zText[128];
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-03-29 10:41:38 +01:00
|
|
|
|
sprintf(zText, "%s/%s", datapath(), "/inactive");
|
2001-02-03 14:45:35 +01:00
|
|
|
|
inactiveFILE = fopen(zText, "a");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
fprintf(inactiveFILE, "%s:%s:%d:%d\n",
|
|
|
|
|
factionid(f),
|
2001-12-10 01:13:39 +01:00
|
|
|
|
LOC(default_locale, rc_name(f->race, 1)),
|
2001-01-25 10:37:55 +01:00
|
|
|
|
modify(count_all(f)),
|
|
|
|
|
turn - f->lastorders);
|
|
|
|
|
|
|
|
|
|
fclose(inactiveFILE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
quit(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
|
|
|
|
faction *f;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
const race * frace;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Sterben erst nachdem man allen anderen gegeben hat - bzw. man kann
|
|
|
|
|
* alles machen, was nicht ein drei<EFBFBD>igt<EFBFBD>giger Befehl ist. */
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next)
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
for (S = u->orders; S; S = S->next)
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(S->s, u->faction->locale) == K_QUIT) {
|
2002-03-03 13:53:05 +01:00
|
|
|
|
if (checkpasswd(u->faction, getstrtoken())) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
destroyfaction(u->faction);
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, S->s, 86, MSG_EVENT);
|
|
|
|
|
printf(" Warnung: STIRB mit falschem Passwort f<>r Partei %s: %s\n",
|
|
|
|
|
factionid(u->faction), S->s);
|
|
|
|
|
}
|
2001-04-16 16:34:19 +02:00
|
|
|
|
} else if(igetkeyword(S->s, u->faction->locale) == K_RESTART && u->number > 0) {
|
2002-01-31 11:58:24 +01:00
|
|
|
|
char *s_race,*s_pass;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (!landregion(rterrain(r))) {
|
|
|
|
|
cmistake(u, S->s, 242, MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-01-31 11:58:24 +01:00
|
|
|
|
s_race = getstrtoken();
|
|
|
|
|
frace = findrace(s_race, u->faction->locale);
|
|
|
|
|
|
|
|
|
|
if (!frace) {
|
2002-01-13 11:42:56 +01:00
|
|
|
|
frace = u->faction->race;
|
2002-01-31 11:58:24 +01:00
|
|
|
|
s_pass = s_race;
|
|
|
|
|
} else {
|
|
|
|
|
s_pass = getstrtoken();
|
|
|
|
|
}
|
2002-03-24 12:24:57 +01:00
|
|
|
|
|
|
|
|
|
if (frace != u->faction->race && u->faction->age < 81) {
|
|
|
|
|
cmistake(u, S->s, 241, MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-05-12 09:04:39 +02:00
|
|
|
|
if (u->faction->age > 3 && fval(u->faction, FFL_RESTART)) {
|
2002-05-05 10:06:19 +02:00
|
|
|
|
cmistake(u, S->s, 314, MSG_EVENT);
|
2002-03-24 12:24:57 +01:00
|
|
|
|
continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-31 11:58:24 +01:00
|
|
|
|
if (!playerrace(frace)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 243, MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-03 13:53:05 +01:00
|
|
|
|
if (!checkpasswd(u->faction, s_pass)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 86, MSG_EVENT);
|
|
|
|
|
printf(" Warnung: NEUSTART mit falschem Passwort f<>r Partei %s: %s\n",
|
|
|
|
|
factionid(u->faction), S->s);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
restart(u, frace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
puts(" - beseitige Spieler, die sich zu lange nicht mehr gemeldet haben...");
|
|
|
|
|
|
|
|
|
|
remove("inactive");
|
|
|
|
|
|
2002-03-03 11:51:24 +01:00
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
if(fval(f, FL_NOIDLEOUT)) f->lastorders = turn;
|
|
|
|
|
#if NMRTIMEOUT
|
|
|
|
|
if (turn - f->lastorders >= NMRTIMEOUT) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
destroyfaction(f);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-01-13 10:14:13 +01:00
|
|
|
|
#endif
|
2002-03-03 13:53:05 +01:00
|
|
|
|
if (fval(f, FFL_OVERRIDE)) {
|
|
|
|
|
free(f->override);
|
|
|
|
|
f->override = strdup(itoa36(rand()));
|
|
|
|
|
}
|
|
|
|
|
if (turn!=f->lastorders) {
|
|
|
|
|
char info[256];
|
|
|
|
|
sprintf(info, "%d Einheiten, %d Personen, %d Silber",
|
2002-03-31 10:46:36 +02:00
|
|
|
|
f->no_units, f->number, f->money);
|
2002-03-03 13:53:05 +01:00
|
|
|
|
fprintf(sqlstream,
|
|
|
|
|
"UPDATE subscriptions SET lastturn=%d, password='%s', info='%s' "
|
2002-03-24 13:31:38 +01:00
|
|
|
|
"WHERE game=%d AND faction='%s';\n",
|
2002-03-03 13:53:05 +01:00
|
|
|
|
f->lastorders, f->override, info, GAME_ID, itoa36(f->no));
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(sqlstream,
|
2002-03-24 13:31:38 +01:00
|
|
|
|
"UPDATE subscriptions SET status='ACTIVE', lastturn=%d, password='%s' "
|
|
|
|
|
"WHERE game=%d AND faction='%s';\n",
|
2002-03-03 13:53:05 +01:00
|
|
|
|
f->lastorders, f->override, GAME_ID, itoa36(f->no));
|
|
|
|
|
}
|
2002-03-03 11:51:24 +01:00
|
|
|
|
|
|
|
|
|
if (turn - f->lastorders >= (NMRTIMEOUT - 1)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
inactivefaction(f);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-03-03 11:51:24 +01:00
|
|
|
|
#if NMRTIMEOUT
|
2001-01-25 10:37:55 +01:00
|
|
|
|
puts(" - beseitige Spieler, die sich nach der Anmeldung nicht "
|
|
|
|
|
"gemeldet haben...");
|
|
|
|
|
|
|
|
|
|
age = calloc(turn+1, sizeof(int));
|
|
|
|
|
for (f = factions; f; f = f->next) if(!fval(f, FL_NOIDLEOUT)) {
|
|
|
|
|
if (f->age>=0 && f->age <= turn) ++age[f->age];
|
|
|
|
|
if (f->age == 2 || f->age == 3) {
|
|
|
|
|
if (f->lastorders == turn - 2) {
|
|
|
|
|
destroyfaction(f);
|
|
|
|
|
++dropouts[f->age-2];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-23 11:32:57 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Clear away debris of destroyed factions */
|
|
|
|
|
|
|
|
|
|
puts(" - beseitige leere Einheiten und leere Parteien...");
|
|
|
|
|
|
|
|
|
|
remove_empty_units();
|
|
|
|
|
|
|
|
|
|
/* Auskommentiert: Wenn factions gel<65>scht werden, zeigen
|
|
|
|
|
* Spendenpointer ins Leere. */
|
|
|
|
|
/* remove_empty_factions(); */
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/* HELFE partei [<ALLES | SILBER | GIB | KAEMPFE | WAHRNEHMUNG>] [NICHT] */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_ally(unit * u, strlist * S)
|
|
|
|
|
{
|
|
|
|
|
ally * sf, ** sfp;
|
|
|
|
|
faction *f;
|
|
|
|
|
int keyword, not_kw;
|
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
|
|
f = getfaction();
|
|
|
|
|
|
|
|
|
|
if (f == 0 || f->no == 0) {
|
|
|
|
|
cmistake(u, S->s, 66, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (f == u->faction)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (!s[0])
|
|
|
|
|
keyword = P_ANY;
|
|
|
|
|
else
|
2001-04-16 16:34:19 +02:00
|
|
|
|
keyword = findparam(s, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
sfp = &u->faction->allies;
|
|
|
|
|
{
|
|
|
|
|
attrib * a = a_find(u->attribs, &at_group);
|
|
|
|
|
if (a) sfp = &((group*)a->data.v)->allies;
|
|
|
|
|
}
|
|
|
|
|
for (sf=*sfp; sf; sf = sf->next)
|
|
|
|
|
if (sf->faction == f)
|
|
|
|
|
break; /* Gleich die passende raussuchen, wenn vorhanden */
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
not_kw = getparam(u->faction->locale); /* HELFE partei [modus] NICHT */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if (!sf) {
|
|
|
|
|
if (keyword == P_NOT || not_kw == P_NOT) {
|
|
|
|
|
/* Wir helfen der Partei gar nicht... */
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
sf = calloc(1, sizeof(ally));
|
|
|
|
|
sf->faction = f;
|
|
|
|
|
sf->status = 0;
|
|
|
|
|
addlist(sfp, sf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
switch (keyword) {
|
|
|
|
|
case P_NOT:
|
|
|
|
|
sf->status = 0;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NOPARAM:
|
|
|
|
|
cmistake(u, S->s, 137, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case P_ANY:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = 0;
|
|
|
|
|
else
|
|
|
|
|
sf->status = HELP_ALL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_GIB:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_GIVE);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_GIVE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_SILVER:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_MONEY);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_MONEY;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_KAEMPFE:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_FIGHT);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_FIGHT;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
#ifdef HELFE_WAHRNEHMUNG
|
|
|
|
|
case P_OBSERVE:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_OBSERVE);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_OBSERVE;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
case P_FACTIONSTEALTH:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_FSTEALTH);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_FSTEALTH;
|
|
|
|
|
break;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case P_GUARD:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_GUARD);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_GUARD;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sf->status == 0) { /* Alle HELPs geloescht */
|
|
|
|
|
removelist(sfp, sf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_display(region * r, unit * u, strlist * S)
|
|
|
|
|
{
|
|
|
|
|
char **s, *s2;
|
|
|
|
|
|
|
|
|
|
s = 0;
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch (getparam(u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case P_BUILDING:
|
|
|
|
|
case P_GEBAEUDE:
|
|
|
|
|
if (!u->building) {
|
|
|
|
|
cmistake(u, S->s, 145, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u, S->s, 5, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-03-27 22:49:27 +01:00
|
|
|
|
if (u->building->type == bt_find("generic")) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 279, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-03-27 22:49:27 +01:00
|
|
|
|
if (u->building->type == bt_find("monument") && u->building->display[0] != 0) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 29, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->building->display;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_SHIP:
|
|
|
|
|
if (!u->ship) {
|
|
|
|
|
cmistake(u, S->s, 144, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u, S->s, 12, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->ship->display;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_UNIT:
|
|
|
|
|
s = &u->display;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_PRIVAT:
|
2001-02-13 20:22:48 +01:00
|
|
|
|
{
|
|
|
|
|
char *d = getstrtoken();
|
|
|
|
|
if(d == NULL || *d == 0) {
|
|
|
|
|
usetprivate(u, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
usetprivate(u, d);
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_REGION:
|
|
|
|
|
if (!u->building) {
|
|
|
|
|
cmistake(u, S->s, 145, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u, S->s, 148, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building != largestbuilding(r,false)) {
|
|
|
|
|
cmistake(u, S->s, 147, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &r->display;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
cmistake(u, S->s, 110, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!s)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
s2 = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (strlen(s2) >= DISPLAYSIZE) {
|
|
|
|
|
s2[DISPLAYSIZE] = 0;
|
|
|
|
|
cmistake(u, S->s, 3, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
set_string(&(*s), s2);
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_prefix(unit * u, strlist *S)
|
|
|
|
|
{
|
|
|
|
|
attrib **ap;
|
|
|
|
|
attrib *a, *a2;
|
|
|
|
|
int i;
|
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if(!*s) {
|
|
|
|
|
a = a_find(u->attribs, &at_group);
|
|
|
|
|
if (a) {
|
|
|
|
|
a_removeall(&((group*)a->data.v)->attribs, &at_raceprefix);
|
|
|
|
|
} else {
|
|
|
|
|
a_removeall(&u->faction->attribs, &at_raceprefix);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(i=0; race_prefixes[i] != NULL; i++) {
|
|
|
|
|
if(strncasecmp(s, LOC(u->faction->locale, race_prefixes[i]), strlen(s)) == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(race_prefixes[i] == NULL) {
|
|
|
|
|
cmistake(u, S->s, 299, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ap = &u->faction->attribs;
|
|
|
|
|
a = a_find(u->attribs, &at_group);
|
|
|
|
|
if (a) ap = &((group*)a->data.v)->attribs;
|
|
|
|
|
|
|
|
|
|
a2 = a_find(*ap, &at_raceprefix);
|
|
|
|
|
if(!a2)
|
|
|
|
|
a2 = a_add(ap, a_new(&at_raceprefix));
|
|
|
|
|
|
|
|
|
|
a2->data.v = strdup(race_prefixes[i]);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_synonym(unit * u, strlist *S)
|
|
|
|
|
{
|
|
|
|
|
attrib *a;
|
|
|
|
|
int i;
|
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
|
|
a = a_find(u->faction->attribs, &at_synonym);
|
|
|
|
|
if(a) { /* Kann nur einmal gesetzt werden */
|
|
|
|
|
cmistake(u, S->s, 302, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if(!s) {
|
|
|
|
|
cmistake(u, S->s, 301, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(i=0; race_synonyms[i].race != -1; i++) {
|
|
|
|
|
if (new_race[race_synonyms[i].race] == u->faction->race
|
|
|
|
|
&& strcasecmp(s, race_synonyms[i].synonyms[0]) == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(race_synonyms[i].race == -1) {
|
|
|
|
|
cmistake(u, S->s, 300, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a = a_add(&u->faction->attribs, a_new(&at_synonym));
|
|
|
|
|
((frace_synonyms *)(a->data.v))->synonyms[0] =
|
|
|
|
|
strdup(race_synonyms[i].synonyms[0]);
|
|
|
|
|
((frace_synonyms *)(a->data.v))->synonyms[1] =
|
|
|
|
|
strdup(race_synonyms[i].synonyms[1]);
|
|
|
|
|
((frace_synonyms *)(a->data.v))->synonyms[2] =
|
|
|
|
|
strdup(race_synonyms[i].synonyms[2]);
|
|
|
|
|
((frace_synonyms *)(a->data.v))->synonyms[3] =
|
|
|
|
|
strdup(race_synonyms[i].synonyms[3]);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
set_group(unit * u)
|
|
|
|
|
{
|
|
|
|
|
char * s = getstrtoken();
|
|
|
|
|
join_group(u, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
set_name(region * r, unit * u, strlist * S)
|
|
|
|
|
{
|
|
|
|
|
char **s, *s2;
|
|
|
|
|
int i;
|
|
|
|
|
param_t p;
|
|
|
|
|
boolean foreign = false;
|
|
|
|
|
|
|
|
|
|
s = 0;
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
p = getparam(u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if(p == P_FOREIGN) {
|
|
|
|
|
foreign = true;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
p = getparam(u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (p) {
|
|
|
|
|
case P_BUILDING:
|
|
|
|
|
case P_GEBAEUDE:
|
|
|
|
|
if (foreign == true) {
|
|
|
|
|
building *b = getbuilding(r);
|
|
|
|
|
unit *uo;
|
|
|
|
|
|
|
|
|
|
if (!b) {
|
|
|
|
|
cmistake(u, S->s, 6, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-27 22:49:27 +01:00
|
|
|
|
if (b->type == bt_find("generic")) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 278, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!fval(b,FL_UNNAMED)) {
|
|
|
|
|
cmistake(u, S->s, 246, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uo = buildingowner(r, b);
|
|
|
|
|
if (uo) {
|
|
|
|
|
if (cansee(uo->faction, r, u, 0)) {
|
|
|
|
|
add_message(&uo->faction->msgs, new_message(uo->faction,
|
|
|
|
|
"renamed_building_seen%b:building%u:renamer%r:region", b, u, r));
|
|
|
|
|
} else {
|
|
|
|
|
add_message(&uo->faction->msgs, new_message(uo->faction,
|
|
|
|
|
"renamed_building_notseen%b:building%r:region", b, r));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s = &b->name;
|
|
|
|
|
} else {
|
|
|
|
|
if (!u->building) {
|
|
|
|
|
cmistake(u, S->s, 145, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u, S->s, 148, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2002-03-27 22:49:27 +01:00
|
|
|
|
if (u->building->type == bt_find("generic")) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 278, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sprintf(buf, "Monument %d", u->building->no);
|
2002-03-27 22:49:27 +01:00
|
|
|
|
if (u->building->type == bt_find("monument")
|
2001-01-28 10:47:10 +01:00
|
|
|
|
&& !strcmp(u->building->name, buf)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 29, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->building->name;
|
|
|
|
|
freset(u->building, FL_UNNAMED);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_FACTION:
|
|
|
|
|
if (foreign == true) {
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
f = getfaction();
|
|
|
|
|
if (!f) {
|
|
|
|
|
cmistake(u, S->s, 66, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (f->age < 10) {
|
|
|
|
|
cmistake(u, S->s, 248, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(f,FL_UNNAMED)) {
|
|
|
|
|
cmistake(u, S->s, 247, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (cansee(f, r, u, 0)) {
|
|
|
|
|
add_message(&f->msgs, new_message(f,
|
|
|
|
|
"renamed_faction_seen%u:renamer%r:region", u, r));
|
|
|
|
|
} else {
|
|
|
|
|
add_message(&f->msgs, new_message(f,
|
|
|
|
|
"renamed_faction_notseen%r:region", r));
|
|
|
|
|
}
|
|
|
|
|
s = &f->name;
|
|
|
|
|
} else {
|
|
|
|
|
s = &u->faction->name;
|
|
|
|
|
freset(u->faction, FL_UNNAMED);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_SHIP:
|
|
|
|
|
if (foreign == true) {
|
|
|
|
|
ship *sh = getship(r);
|
|
|
|
|
unit *uo;
|
|
|
|
|
|
|
|
|
|
if (!sh) {
|
|
|
|
|
cmistake(u, S->s, 20, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(sh,FL_UNNAMED)) {
|
|
|
|
|
cmistake(u, S->s, 245, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
uo = shipowner(r,sh);
|
|
|
|
|
if (uo) {
|
|
|
|
|
if (cansee(uo->faction, r, u, 0)) {
|
|
|
|
|
add_message(&uo->faction->msgs, new_message(uo->faction,
|
|
|
|
|
"renamed_ship_seen%h:ship%u:renamer%r:region", sh, u, r));
|
|
|
|
|
} else {
|
|
|
|
|
add_message(&uo->faction->msgs, new_message(uo->faction,
|
|
|
|
|
"renamed_ship_notseen%h:ship%r:region", sh, r));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s = &sh->name;
|
|
|
|
|
} else {
|
|
|
|
|
if (!u->ship) {
|
|
|
|
|
cmistake(u, S->s, 144, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u, S->s, 12, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->ship->name;
|
|
|
|
|
freset(u->ship, FL_UNNAMED);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_UNIT:
|
|
|
|
|
if (foreign == true) {
|
2001-04-26 19:41:06 +02:00
|
|
|
|
unit *u2 = getunit(r, u->faction);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (!u2 || !cansee(u->faction, r, u2, 0)) {
|
|
|
|
|
cmistake(u, S->s, 64, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u,FL_UNNAMED)) {
|
2001-01-29 20:15:12 +01:00
|
|
|
|
cmistake(u, S->s, 244, MSG_EVENT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (cansee(u2->faction, r, u, 0)) {
|
|
|
|
|
add_message(&u2->faction->msgs, new_message(u2->faction,
|
|
|
|
|
"renamed_seen%u:renamer%u:renamed%r:region", u, u2, r));
|
|
|
|
|
} else {
|
|
|
|
|
add_message(&u2->faction->msgs, new_message(u2->faction,
|
|
|
|
|
"renamed_notseen%u:renamed%r:region", u2, r));
|
|
|
|
|
}
|
|
|
|
|
s = &u2->name;
|
|
|
|
|
} else {
|
|
|
|
|
s = &u->name;
|
|
|
|
|
freset(u, FL_UNNAMED);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_REGION:
|
|
|
|
|
if (!u->building) {
|
|
|
|
|
cmistake(u, S->s, 145, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u, S->s, 148, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building != largestbuilding(r,false)) {
|
|
|
|
|
cmistake(u, S->s, 147, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &r->land->name;
|
|
|
|
|
break;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
case P_GROUP:
|
|
|
|
|
{
|
|
|
|
|
attrib * a = a_find(u->attribs, &at_group);
|
|
|
|
|
if (a){
|
|
|
|
|
group * g = (group*)a->data.v;
|
|
|
|
|
s= &g->name;
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, S->s, 109, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
default:
|
|
|
|
|
cmistake(u, S->s, 109, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!s)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
s2 = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (!s2[0]) {
|
|
|
|
|
cmistake(u, S->s, 84, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; s2[i]; i++)
|
|
|
|
|
if (s2[i] == '(')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (s2[i]) {
|
|
|
|
|
cmistake(u, S->s, 112, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
set_string(&(*s), s2);
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
deliverMail(faction * f, region * r, unit * u, const char *s, unit * receiver)
|
|
|
|
|
{
|
2001-02-03 14:45:35 +01:00
|
|
|
|
if (!receiver) { /* BOTSCHAFT an PARTEI */
|
2001-12-10 01:13:39 +01:00
|
|
|
|
char * message = (char*)gc_add(strdup(s));
|
2001-02-03 14:45:35 +01:00
|
|
|
|
add_message(&f->msgs,
|
2001-12-10 01:13:39 +01:00
|
|
|
|
msg_message("unitmessage", "region unit string", r, u, message));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
else { /* BOTSCHAFT an EINHEIT */
|
|
|
|
|
unit *emp = receiver;
|
|
|
|
|
if (cansee(f, r, u, 0))
|
2001-12-10 01:13:39 +01:00
|
|
|
|
sprintf(buf, "Eine Botschaft von %s: '%s'", unitname(u), s);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
else
|
2001-12-10 01:13:39 +01:00
|
|
|
|
sprintf(buf, "Eine anonyme Botschaft: '%s'", s);
|
|
|
|
|
addstrlist(&emp->botschaften, strdup(buf));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mailunit(region * r, unit * u, int n, strlist * S, const char * s)
|
|
|
|
|
{
|
|
|
|
|
unit *u2; /* nur noch an eine Unit m<>glich */
|
|
|
|
|
|
|
|
|
|
u2=findunitr(r,n);
|
|
|
|
|
|
|
|
|
|
if (u2 && cansee(u->faction, r, u2, 0)) {
|
|
|
|
|
deliverMail(u2->faction, r, u, s, u2);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
cmistake(u, S->s, 64, MSG_MESSAGE);
|
|
|
|
|
/* Immer eine Meldung - sonst k<>nnte man so getarnte EHs enttarnen:
|
|
|
|
|
* keine Meldung -> EH hier. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mailfaction(unit * u, int n, strlist * S, const char * s)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
f = findfaction(n);
|
|
|
|
|
if (f && n>0)
|
|
|
|
|
deliverMail(f, u->region, u, s, NULL);
|
|
|
|
|
else
|
|
|
|
|
cmistake(u, S->s, 66, MSG_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
distributeMail(region * r, unit * u, strlist * S)
|
|
|
|
|
{
|
|
|
|
|
unit *u2;
|
|
|
|
|
char *s;
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
/* Falls kein Parameter, ist das eine Einheitsnummer;
|
|
|
|
|
* das F<EFBFBD>llwort "AN" mu<EFBFBD> wegfallen, da g<EFBFBD>ltige Nummer! */
|
|
|
|
|
|
|
|
|
|
if(strcasecmp(s, "an") == 0)
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch (findparam(s, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
case P_REGION: /* k<>nnen alle Einheiten in der Region sehen */
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, S->s, 30, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
if (strlen(s) >= DISPLAYSIZE) {
|
|
|
|
|
s[DISPLAYSIZE] = 0;
|
|
|
|
|
cmistake(u, S->s, 111, MSG_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
sprintf(buf, "von %s: '%s'", unitname(u), s);
|
|
|
|
|
addmessage(r, 0, buf, MSG_MESSAGE, ML_IMPORTANT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_FACTION:
|
|
|
|
|
{
|
|
|
|
|
boolean see = false;
|
|
|
|
|
|
|
|
|
|
n = getfactionid();
|
|
|
|
|
|
|
|
|
|
for(u2=r->units; u2; u2=u2->next) {
|
|
|
|
|
if(u2->faction->no == n && seefaction(u->faction, r, u2, 0)) {
|
|
|
|
|
see = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(see == false) {
|
|
|
|
|
cmistake(u, S->s, 66, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, S->s, 30, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mailfaction(u, n, S, s);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_UNIT:
|
|
|
|
|
{
|
|
|
|
|
boolean see = false;
|
|
|
|
|
n = getid();
|
|
|
|
|
|
|
|
|
|
for(u2=r->units; u2; u2=u2->next) {
|
|
|
|
|
if(u2->no == n && cansee(u->faction, r, u2, 0)) {
|
|
|
|
|
see = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(see == false) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
cmistake(u, S->s, 64, MSG_MESSAGE);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, S->s, 30, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mailunit(r, u, n, S, s);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_BUILDING:
|
|
|
|
|
case P_GEBAEUDE:
|
|
|
|
|
{
|
|
|
|
|
building *b = getbuilding(r);
|
|
|
|
|
|
|
|
|
|
if(!b) {
|
|
|
|
|
cmistake(u, S->s, 6, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, S->s, 30, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u2 = r->units; u2; u2 = u2->next) freset(u2->faction, FL_DH);
|
|
|
|
|
|
|
|
|
|
for(u2=r->units; u2; u2=u2->next) {
|
|
|
|
|
if(u2->building == b && !fval(u2->faction, FL_DH)
|
|
|
|
|
&& cansee(u->faction, r, u2, 0)) {
|
|
|
|
|
mailunit(r, u, u2->no, S, s);
|
|
|
|
|
fset(u2->faction, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_SHIP:
|
|
|
|
|
{
|
|
|
|
|
ship *sh = getship(r);
|
|
|
|
|
|
|
|
|
|
if(!sh) {
|
|
|
|
|
cmistake(u, S->s, 20, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, S->s, 30, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u2 = r->units; u2; u2 = u2->next) freset(u2->faction, FL_DH);
|
|
|
|
|
|
|
|
|
|
for(u2=r->units; u2; u2=u2->next) {
|
|
|
|
|
if(u2->ship == sh && !fval(u2->faction, FL_DH)
|
|
|
|
|
&& cansee(u->faction, r, u2, 0)) {
|
|
|
|
|
mailunit(r, u, u2->no, S, s);
|
|
|
|
|
fset(u2->faction, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
cmistake(u, S->s, 149, MSG_MESSAGE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
mail(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
|
|
|
|
|
|
|
|
|
puts(" - verschicke Botschaften...");
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next)
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
for (S = u->orders; S; S = S->next)
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(S->s, u->faction->locale) == K_MAIL)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
distributeMail(r, u, S);
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
report_option(unit * u, const char * sec, char *cmd)
|
|
|
|
|
{
|
|
|
|
|
const messageclass * mc;
|
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
|
|
mc = mc_find(sec);
|
|
|
|
|
|
|
|
|
|
if (mc == NULL) {
|
|
|
|
|
cmistake(u, findorder(u, cmd), 135, MSG_EVENT);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (s[0])
|
|
|
|
|
set_msglevel(&u->faction->warnings, mc->name, atoi(s));
|
|
|
|
|
else
|
|
|
|
|
set_msglevel(&u->faction->warnings, mc->name, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
set_passw(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
|
|
|
|
char *s;
|
|
|
|
|
int o, i;
|
|
|
|
|
magic_t mtyp;
|
|
|
|
|
|
|
|
|
|
puts(" - setze Passw<73>rter, Adressen und Format, Abstimmungen");
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next)
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
for (S = u->orders; S; S = S->next) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch (igetkeyword(S->s, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case NOKEYWORD:
|
|
|
|
|
cmistake(u, S->s, 22, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_BANNER:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
set_string(&u->faction->banner, s);
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"changebanner%s:value", gc_add(strdup(u->faction->banner))));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_EMAIL:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, S->s, 85, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (strstr(s, "internet:") || strchr(s, ' ')) {
|
|
|
|
|
cmistake(u, S->s, 117, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
set_string(&u->faction->email, s);
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"changemail%s:value", gc_add(strdup(u->faction->email))));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_PASSWORD:
|
2001-02-03 14:45:35 +01:00
|
|
|
|
{
|
|
|
|
|
char pbuf[32];
|
|
|
|
|
int i;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-02-03 14:45:35 +01:00
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (!s || !*s) {
|
|
|
|
|
for(i=0; i<6; i++) pbuf[i] = (char)(97 + rand() % 26);
|
|
|
|
|
pbuf[6] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
boolean pwok = true;
|
|
|
|
|
char *c;
|
|
|
|
|
|
|
|
|
|
strncpy(pbuf, s, 31);
|
|
|
|
|
pbuf[31] = 0;
|
|
|
|
|
c = pbuf;
|
|
|
|
|
while(*c) {
|
|
|
|
|
if(!isalnum(*c)) pwok = false;
|
|
|
|
|
c++;
|
|
|
|
|
}
|
2002-03-09 16:16:35 +01:00
|
|
|
|
if (pwok == false) {
|
2001-02-03 14:45:35 +01:00
|
|
|
|
cmistake(u, S->s, 283, MSG_EVENT);
|
|
|
|
|
for(i=0; i<6; i++) pbuf[i] = (char)(97 + rand() % 26);
|
|
|
|
|
pbuf[6] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set_string(&u->faction->passw, pbuf);
|
2002-03-31 16:08:33 +02:00
|
|
|
|
fset(u->faction, FFL_OVERRIDE);
|
2002-04-20 14:41:49 +02:00
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("changepasswd",
|
2002-03-03 13:53:05 +01:00
|
|
|
|
"value", gc_add(strdup(u->faction->passw))));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_REPORT:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
i = atoi(s);
|
|
|
|
|
sprintf(buf, "%d", i);
|
|
|
|
|
if (!strcmp(buf, s)) {
|
|
|
|
|
/* int level;
|
|
|
|
|
level = geti();
|
|
|
|
|
not implemented yet. set individual levels for f->msglevels */
|
|
|
|
|
} else {
|
|
|
|
|
report_option(u, s, S->s);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_SEND:
|
|
|
|
|
s = getstrtoken();
|
2001-12-10 01:13:39 +01:00
|
|
|
|
o = findoption(s, u->faction->locale);
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef AT_OPTION
|
2001-02-28 19:25:25 +01:00
|
|
|
|
/* Sonderbehandlung Zeitungsoption */
|
|
|
|
|
if (o == O_NEWS) {
|
|
|
|
|
attrib *a = a_find(u->faction->attribs, &at_option_news);
|
|
|
|
|
if(a) a->data.i = 0;
|
|
|
|
|
|
|
|
|
|
while((s = getstrtoken())) {
|
|
|
|
|
if(findparam(s) == P_NOT) {
|
|
|
|
|
a_removeall(&u->faction->attribs, &at_option_news);
|
2001-02-28 19:31:49 +01:00
|
|
|
|
u->faction->options = u->faction->options & ~O_NEWS;
|
2001-02-28 19:25:25 +01:00
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
int sec = atoi(s);
|
|
|
|
|
if(sec != 0) {
|
|
|
|
|
if(!a) a_add(&u->faction->attribs, a_new(&at_option_news));
|
|
|
|
|
a->data.i = a->data.i & (1<<(sec-1));
|
2001-02-28 19:31:49 +01:00
|
|
|
|
u->faction->options = u->faction->options | O_NEWS;
|
2001-02-28 19:25:25 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (o == -1) {
|
|
|
|
|
cmistake(u, S->s, 135, MSG_EVENT);
|
|
|
|
|
} else {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (getparam(u->faction->locale) == P_NOT) {
|
2002-02-04 19:11:12 +01:00
|
|
|
|
if(o == O_COMPRESS || o == O_BZIP2) {
|
2002-01-13 09:14:17 +01:00
|
|
|
|
cmistake(u, S->s, 305, MSG_EVENT);
|
|
|
|
|
} else {
|
2002-02-04 19:11:12 +01:00
|
|
|
|
u->faction->options = u->faction->options & ~((int)pow(2, o));
|
2002-01-13 09:14:17 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
2002-02-04 19:11:12 +01:00
|
|
|
|
u->faction->options = u->faction->options | ((int)pow(2,o));
|
|
|
|
|
if(o == O_COMPRESS) u->faction->options &= ~((int)pow(2,O_BZIP2));
|
|
|
|
|
if(o == O_BZIP2) u->faction->options &= ~((int)pow(2,O_COMPRESS));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_MAGIEGEBIET:
|
|
|
|
|
if(u->faction->magiegebiet != 0) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
add_message(&u->faction->msgs,
|
* möglichen Exploit beseitigt:
GIB xyz EINHEIT
GIB 0 ALLES SILBER
--> ALLE Befehle der übergebenen Einheit werden gelöscht.
* neue Funktion (convenience): ucansee(f, u1, u2)
liefert u1, wenn cansee(f,u1), sonst u2
* neue mistakes eingefügt uns übersetzt
* message bugfix:
u->htisorder kann gelöscht werden (z.b. NACH). Daher muss ein pointer auf
einen befehl in einer message immer auf den u->order Eintrag zeigen, damit er
zeit der auswertung noch existiert.
findorder(u, u->thisorder) tut das. Ist an mehreren Stellen nicht benutzt
worden. assert eingebaut, das das prüft.
* RESERVE_DONATIONS
Gegenstände, die von einer anderen Partei übergeben wurden, werden nicht
reserviert.
* TWOPASS_GIVE:
GIB Befehle werden zuerst an fremde Einheiten, danach in einem zweiten
Durchlauf an eigene Einheiten, ausgeführt.
* msg_message
An einigen messages ausprobiert, ob man die gleiche Message mehreren
Parteien einhängen kann - klappt, spart Speicher.
Allerdings fehlt dazu ein ordentliches memory-management (refcounter)
2001-05-10 07:50:52 +02:00
|
|
|
|
msg_error(u, S->s, "one_circle_only", ""));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
|
|
|
|
mtyp = getmagicskill();
|
|
|
|
|
if(mtyp == M_NONE) {
|
|
|
|
|
mistake(u, S->s, "Syntax: MAGIEGEBIET <Gebiet>", MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
region *r2;
|
|
|
|
|
unit *u2;
|
|
|
|
|
sc_mage *m;
|
|
|
|
|
region *last = lastregion(u->faction);
|
|
|
|
|
|
|
|
|
|
u->faction->magiegebiet = mtyp;
|
|
|
|
|
|
2002-02-03 13:56:15 +01:00
|
|
|
|
for (r2 = firstregion(u->faction); r2 != last; r2 = r2->next) {
|
|
|
|
|
for (u2 = r->units; u2; u2 = u2->next) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if(u2->faction == u->faction
|
2002-03-03 19:13:08 +01:00
|
|
|
|
&& has_skill(u2, SK_MAGIC)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
m = get_mage(u2);
|
|
|
|
|
m->magietyp = mtyp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean
|
|
|
|
|
display_item(faction *f, unit *u, const item_type * itype)
|
|
|
|
|
{
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char t[NAMESIZE + 1];
|
2001-02-03 14:45:35 +01:00
|
|
|
|
char filename[MAX_PATH];
|
2002-03-11 01:06:14 +01:00
|
|
|
|
const char *name;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if (u && *i_find(&u->items, itype) == NULL) return false;
|
2002-03-03 17:41:40 +01:00
|
|
|
|
/*
|
2002-01-01 21:51:18 +01:00
|
|
|
|
info = mkname("info", itype->rtype->_name[0]);
|
|
|
|
|
name = LOC(u->faction->locale, info);
|
2002-03-03 17:41:40 +01:00
|
|
|
|
if (strcmp(name, info)==0) {
|
|
|
|
|
*/
|
2001-04-16 16:34:19 +02:00
|
|
|
|
name = resourcename(itype->rtype, 0);
|
2002-01-01 21:51:18 +01:00
|
|
|
|
sprintf(filename, "%s/%s/items/%s", resourcepath(), locale_name(f->locale), name);
|
2001-02-03 14:45:35 +01:00
|
|
|
|
fp = fopen(filename, "r");
|
2002-01-01 21:51:18 +01:00
|
|
|
|
if (!fp) {
|
|
|
|
|
name = locale_string(f->locale, resourcename(itype->rtype, 0));
|
|
|
|
|
sprintf(filename, "%s/%s/items/%s", resourcepath(), locale_name(f->locale), name);
|
|
|
|
|
fp = fopen(filename, "r");
|
|
|
|
|
}
|
|
|
|
|
if (!fp) {
|
|
|
|
|
name = resourcename(itype->rtype, 0);
|
|
|
|
|
sprintf(filename, "%s/items/%s", resourcepath(), name);
|
|
|
|
|
fp = fopen(filename, "r");
|
|
|
|
|
}
|
|
|
|
|
if (!fp) return false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-01-28 02:55:31 +01:00
|
|
|
|
buf[0]='\0';
|
2002-01-01 21:51:18 +01:00
|
|
|
|
while (fgets(t, NAMESIZE, fp) != NULL) {
|
|
|
|
|
if (t[strlen(t) - 1] == '\n') {
|
|
|
|
|
t[strlen(t) - 1] = 0;
|
|
|
|
|
}
|
|
|
|
|
strcat(buf, t);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2002-01-01 21:51:18 +01:00
|
|
|
|
fclose(fp);
|
|
|
|
|
name = buf;
|
2002-03-03 17:41:40 +01:00
|
|
|
|
/* } */
|
2002-01-28 03:23:57 +01:00
|
|
|
|
ADDMSG(&f->msgs, msg_message("displayitem", "item description", itype->rtype, strdup(name)));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean
|
|
|
|
|
display_potion(faction *f, unit *u, const potion_type * ptype)
|
|
|
|
|
{
|
|
|
|
|
attrib *a;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (ptype==NULL) return false;
|
|
|
|
|
else {
|
|
|
|
|
int i = i_get(u->items, ptype->itype);
|
|
|
|
|
if (i==0 && 2*ptype->level > effskill(u,SK_ALCHEMY)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
a = a_find(f->attribs, &at_showitem);
|
|
|
|
|
while (a && a->data.v != ptype) a=a->next;
|
|
|
|
|
if (!a) {
|
|
|
|
|
a = a_add(&f->attribs, a_new(&at_showitem));
|
|
|
|
|
a->data.v = (void*) ptype->itype;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean
|
2001-12-10 01:13:39 +01:00
|
|
|
|
display_race(faction *f, unit *u, const race * rc)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char t[NAMESIZE + 1];
|
|
|
|
|
char filename[256];
|
|
|
|
|
const char *name;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
int a, at_count;
|
|
|
|
|
char buf2[2048];
|
|
|
|
|
|
|
|
|
|
if (u && u->race != rc) return false;
|
|
|
|
|
name = rc_name(rc, 0);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
sprintf(buf, "%s: ", LOC(f->locale, name));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
sprintf(filename, "showdata/%s", LOC(default_locale, name));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fp = fopen(filename, "r");
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(fp) {
|
|
|
|
|
while (fgets(t, NAMESIZE, fp) != NULL) {
|
|
|
|
|
if (t[strlen(t) - 1] == '\n') {
|
|
|
|
|
t[strlen(t) - 1] = 0;
|
|
|
|
|
}
|
|
|
|
|
strcat(buf, t);
|
|
|
|
|
}
|
|
|
|
|
fclose(fp);
|
|
|
|
|
strcat(buf, ". ");
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* hp_p : Trefferpunkte */
|
|
|
|
|
sprintf(buf2, "Trefferpunkte: %d", rc->hitpoints);
|
|
|
|
|
strcat(buf, buf2);
|
|
|
|
|
/* b_armor : R<>stung */
|
|
|
|
|
if (rc->armor > 0){
|
|
|
|
|
sprintf(buf2, ", R<>stung: %d", rc->armor);
|
|
|
|
|
strcat(buf, buf2);
|
|
|
|
|
}
|
|
|
|
|
/* b_attacke : Angriff */
|
|
|
|
|
sprintf(buf2, ", Angriff: %d", (rc->at_default+rc->at_bonus));
|
|
|
|
|
strcat(buf, buf2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* b_defense : Verteidigung */
|
|
|
|
|
sprintf(buf2, ", Verteidigung: %d", (rc->df_default+rc->df_bonus));
|
|
|
|
|
strcat(buf, buf2);
|
|
|
|
|
|
|
|
|
|
strcat(buf, ".");
|
|
|
|
|
|
|
|
|
|
/* b_damage : Schaden */
|
|
|
|
|
at_count=0;
|
|
|
|
|
for (a = 0; a < 6; a++) {
|
|
|
|
|
if (rc->attack[a].type != AT_NONE){
|
|
|
|
|
at_count++;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-14 12:11:01 +02:00
|
|
|
|
if (rc->battle_flags & BF_EQUIPMENT) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
strcat(buf, " Kann Waffen benutzen.");
|
|
|
|
|
}
|
2002-04-14 12:11:01 +02:00
|
|
|
|
if (rc->battle_flags & BF_RES_PIERCE) {
|
|
|
|
|
strcat(buf, " Ist durch Stichwaffen, B<>gen und Armbr<62>ste schwer zu verwunden.");
|
|
|
|
|
}
|
|
|
|
|
if (rc->battle_flags & BF_RES_CUT) {
|
|
|
|
|
strcat(buf, " Ist durch Hiebwaffen schwer zu verwunden.");
|
|
|
|
|
}
|
|
|
|
|
if (rc->battle_flags & BF_RES_BASH) {
|
|
|
|
|
strcat(buf, " Ist durch Schlagwaffen und Katapulte schwer zu verwunden.");
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
sprintf(buf2, " Hat %d Angriff%s", at_count, (at_count>1)?"e":"");
|
|
|
|
|
strcat(buf, buf2);
|
|
|
|
|
for (a = 0; a < 6; a++) {
|
|
|
|
|
if (rc->attack[a].type != AT_NONE){
|
|
|
|
|
if (a!=0){
|
|
|
|
|
strcat(buf, ", ");
|
|
|
|
|
} else {
|
|
|
|
|
strcat(buf, ": ");
|
|
|
|
|
}
|
|
|
|
|
switch(rc->attack[a].type) {
|
|
|
|
|
case AT_STANDARD:
|
|
|
|
|
sprintf(buf2, "ein Angriff mit der Waffe oder macht unbewaffnet %s Schaden", rc->def_damage);
|
|
|
|
|
break;
|
|
|
|
|
case AT_NATURAL:
|
|
|
|
|
sprintf(buf2, "ein Angriff mit Krallen, Z<>hnen oder Klauen, der %s Schaden macht", rc->attack[a].data.dice);
|
|
|
|
|
break;
|
|
|
|
|
case AT_SPELL:
|
|
|
|
|
case AT_COMBATSPELL:
|
|
|
|
|
case AT_DRAIN_ST:
|
|
|
|
|
case AT_DAZZLE:
|
|
|
|
|
sprintf(buf2, "ein magischer Angriff");
|
|
|
|
|
break;
|
|
|
|
|
case AT_STRUCTURAL:
|
|
|
|
|
sprintf(buf2, "ein Angriff, der %s Geb<65>udeschaden verursacht", rc->attack[a].data.dice);
|
|
|
|
|
}
|
|
|
|
|
strcat(buf, buf2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcat(buf, ".");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
addmessage(0, f, buf, MSG_EVENT, ML_IMPORTANT);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
instant_orders(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
|
|
|
|
char *s;
|
|
|
|
|
char *param;
|
|
|
|
|
spell *spell;
|
|
|
|
|
#ifdef NEW_ITEMS
|
|
|
|
|
const item_type * itype;
|
|
|
|
|
#else
|
|
|
|
|
potion_t potion;
|
|
|
|
|
item_t item;
|
|
|
|
|
#endif
|
|
|
|
|
const potion_type * ptype;
|
|
|
|
|
faction *f;
|
|
|
|
|
attrib *a;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
const race * rc;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int level = 0; /* 0 = MAX */
|
|
|
|
|
|
|
|
|
|
puts(" - Kontakte, Hilfe, Status, Kampfzauber, Texte, Bewachen (aus), Zeigen");
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
#ifdef NEW_ITEMS
|
|
|
|
|
a=a_find(f->attribs, &at_showitem);
|
|
|
|
|
while(a!=NULL) {
|
|
|
|
|
const item_type * itype = (const item_type *)a->data.v;
|
|
|
|
|
const potion_type * ptype = resource2potion(itype->rtype);
|
|
|
|
|
if (ptype!=NULL) {
|
|
|
|
|
attrib * n = a->nexttype;
|
|
|
|
|
/* potions werden separat behandelt */
|
|
|
|
|
display_item(f, NULL, (const item_type *)a->data.v);
|
|
|
|
|
a_remove(&f->attribs, a);
|
|
|
|
|
a = n;
|
|
|
|
|
} else a = a->nexttype;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
while((a=a_find(f->attribs, &at_show_item_description))!=NULL) {
|
|
|
|
|
display_item(f, NULL, (item_t)(a->data.i));
|
|
|
|
|
a_remove(&f->attribs, a);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next)
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
for (S = u->orders; S; S = S->next)
|
|
|
|
|
{
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(S->s, u->faction->locale)==K_GROUP) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_group(u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (S = u->orders; S; S = S->next)
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch (igetkeyword(S->s, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_URSPRUNG:
|
|
|
|
|
{
|
|
|
|
|
int px, py;
|
|
|
|
|
|
|
|
|
|
px = atoi(getstrtoken());
|
|
|
|
|
py = atoi(getstrtoken());
|
|
|
|
|
|
|
|
|
|
set_ursprung(u->faction, getplaneid(r), px, py);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_ALLY:
|
|
|
|
|
set_ally(u, S);
|
|
|
|
|
break;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
case K_PREFIX:
|
|
|
|
|
set_prefix(u, S);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_SYNONYM:
|
|
|
|
|
set_synonym(u, S);
|
|
|
|
|
break;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_SETSTEALTH:
|
|
|
|
|
setstealth(u, S);
|
|
|
|
|
break;
|
|
|
|
|
|
2002-04-12 14:46:16 +02:00
|
|
|
|
case K_WEREWOLF:
|
|
|
|
|
setwere(u, S);
|
|
|
|
|
break;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_STATUS:
|
|
|
|
|
param = getstrtoken();
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch (findparam(param, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case P_NOT:
|
|
|
|
|
u->status = ST_AVOID;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_BEHIND:
|
|
|
|
|
u->status = ST_BEHIND;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_FLEE:
|
|
|
|
|
u->status = ST_FLEE;
|
|
|
|
|
break;
|
|
|
|
|
|
2001-04-13 16:39:57 +02:00
|
|
|
|
case P_CHICKEN:
|
|
|
|
|
u->status = ST_CHICKEN;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_AGGRO:
|
|
|
|
|
u->status = ST_AGGRO;
|
|
|
|
|
break;
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case P_VORNE:
|
|
|
|
|
u->status = ST_FIGHT;
|
|
|
|
|
break;
|
2002-02-06 09:06:02 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case P_HELP:
|
|
|
|
|
param = getstrtoken();
|
2002-02-06 09:06:02 +01:00
|
|
|
|
if( findparam(param, u->faction->locale) == P_NOT) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fset(u, FL_NOAID);
|
2002-02-06 09:06:02 +01:00
|
|
|
|
} else {
|
|
|
|
|
freset(u, FL_NOAID);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if (strlen(param)) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
add_message(&u->faction->msgs,
|
* möglichen Exploit beseitigt:
GIB xyz EINHEIT
GIB 0 ALLES SILBER
--> ALLE Befehle der übergebenen Einheit werden gelöscht.
* neue Funktion (convenience): ucansee(f, u1, u2)
liefert u1, wenn cansee(f,u1), sonst u2
* neue mistakes eingefügt uns übersetzt
* message bugfix:
u->htisorder kann gelöscht werden (z.b. NACH). Daher muss ein pointer auf
einen befehl in einer message immer auf den u->order Eintrag zeigen, damit er
zeit der auswertung noch existiert.
findorder(u, u->thisorder) tut das. Ist an mehreren Stellen nicht benutzt
worden. assert eingebaut, das das prüft.
* RESERVE_DONATIONS
Gegenstände, die von einer anderen Partei übergeben wurden, werden nicht
reserviert.
* TWOPASS_GIVE:
GIB Befehle werden zuerst an fremde Einheiten, danach in einem zweiten
Durchlauf an eigene Einheiten, ausgeführt.
* msg_message
An einigen messages ausprobiert, ob man die gleiche Message mehreren
Parteien einhängen kann - klappt, spart Speicher.
Allerdings fehlt dazu ein ordentliches memory-management (refcounter)
2001-05-10 07:50:52 +02:00
|
|
|
|
msg_error(u, S->s, "unknown_status", ""));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
|
|
|
|
u->status = ST_FIGHT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* KAMPFZAUBER [[STUFE n] "<Spruchname>"] [NICHT] */
|
|
|
|
|
case K_COMBAT:
|
|
|
|
|
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
/* KAMPFZAUBER [NICHT] l<>scht alle gesetzten Kampfzauber */
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
unset_combatspell(u, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Optional: STUFE n */
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (findparam(s, u->faction->locale) == P_LEVEL) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Merken, setzen kommt erst sp<73>ter */
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
level = atoi(s);
|
|
|
|
|
level = max(0, level);
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
}
|
2002-02-06 09:06:02 +01:00
|
|
|
|
else level = 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
spell = find_spellbyname(u, s, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if(!spell){
|
2001-04-29 20:23:40 +02:00
|
|
|
|
cmistake(u, S->s, 173, MSG_MAGIC);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* KAMPFZAUBER "<Spruchname>" NICHT l<>scht diesen speziellen
|
|
|
|
|
* Kampfzauber */
|
|
|
|
|
s = getstrtoken();
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if(findparam(s, u->faction->locale) == P_NOT){
|
2001-01-25 10:37:55 +01:00
|
|
|
|
unset_combatspell(u,spell);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* KAMPFZAUBER "<Spruchname>" setzt diesen Kampfzauber */
|
|
|
|
|
set_combatspell(u,spell, S->s, level);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_DISPLAY:
|
|
|
|
|
set_display(r, u, S);
|
|
|
|
|
break;
|
|
|
|
|
case K_NAME:
|
|
|
|
|
set_name(r, u, S);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_GUARD:
|
2001-12-15 17:34:23 +01:00
|
|
|
|
if (u->faction->age < IMMUN_GEGEN_ANGRIFF) {
|
|
|
|
|
cmistake(u, S->s, 304, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (fval(u, FL_HUNGER)) {
|
|
|
|
|
cmistake(u, S->s, 223, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (getparam(u->faction->locale) == P_NOT)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
setguard(u, GUARD_NONE);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_RESHOW:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if(findparam(s, u->faction->locale) == P_ANY) {
|
|
|
|
|
param_t p = getparam(u->faction->locale);
|
2001-02-25 20:31:40 +01:00
|
|
|
|
|
|
|
|
|
if(p == P_ZAUBER) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
a_removeall(&u->faction->attribs, &at_seenspell);
|
2001-02-25 20:31:40 +01:00
|
|
|
|
} else if(p == P_POTIONS) {
|
|
|
|
|
int skill = effskill(u, SK_ALCHEMY);
|
|
|
|
|
potion_type *pt;
|
|
|
|
|
int c = 0;
|
|
|
|
|
for(pt = potiontypes; pt; pt=pt->next) {
|
|
|
|
|
if(pt->level * 2 <= skill) {
|
|
|
|
|
c += display_potion(u->faction, u, pt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(c == 0) {
|
|
|
|
|
cmistake(u, S->s, 285, MSG_EVENT);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, S->s, 222, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
spell = find_spellbyname(u, s, u->faction->locale);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
rc = findrace(s, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
itype = finditemtype(s, u->faction->locale);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (spell == NULL && itype == NULL && rc==NULL) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 21, MSG_EVENT);
|
|
|
|
|
break;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
if (spell && knowsspell(r, u, spell)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
attrib *a = a_find(u->faction->attribs, &at_seenspell);
|
|
|
|
|
while (a && a->data.i!=spell->id) a = a->nexttype;
|
|
|
|
|
if (a!=NULL) a_remove(&u->faction->attribs, a);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
if (itype != NULL) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if((ptype = resource2potion(item2resource(itype))) != NULL) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(display_potion(u->faction, u, ptype) == false
|
|
|
|
|
&& rc==NULL) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 21, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(display_item(u->faction, u, itype) == false
|
|
|
|
|
&& rc==NULL) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 21, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
if (rc != NULL) {
|
|
|
|
|
if (display_race(u->faction, u, rc) == false){
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 21, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
/* Beachten: einige Monster sollen auch unbewaffent die Region bewachen
|
|
|
|
|
* k<EFBFBD>nnen */
|
|
|
|
|
void
|
|
|
|
|
remove_unequipped_guarded(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next)
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2001-12-15 17:34:23 +01:00
|
|
|
|
if (getguard(u) && (!armedmen(u) || u->faction->age < IMMUN_GEGEN_ANGRIFF))
|
2001-01-25 10:37:55 +01:00
|
|
|
|
setguard(u, GUARD_NONE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
bewache_an(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
|
|
|
|
|
|
|
|
|
/* letzte schnellen befehle - bewache */
|
* möglichen Exploit beseitigt:
GIB xyz EINHEIT
GIB 0 ALLES SILBER
--> ALLE Befehle der übergebenen Einheit werden gelöscht.
* neue Funktion (convenience): ucansee(f, u1, u2)
liefert u1, wenn cansee(f,u1), sonst u2
* neue mistakes eingefügt uns übersetzt
* message bugfix:
u->htisorder kann gelöscht werden (z.b. NACH). Daher muss ein pointer auf
einen befehl in einer message immer auf den u->order Eintrag zeigen, damit er
zeit der auswertung noch existiert.
findorder(u, u->thisorder) tut das. Ist an mehreren Stellen nicht benutzt
worden. assert eingebaut, das das prüft.
* RESERVE_DONATIONS
Gegenstände, die von einer anderen Partei übergeben wurden, werden nicht
reserviert.
* TWOPASS_GIVE:
GIB Befehle werden zuerst an fremde Einheiten, danach in einem zweiten
Durchlauf an eigene Einheiten, ausgeführt.
* msg_message
An einigen messages ausprobiert, ob man die gleiche Message mehreren
Parteien einhängen kann - klappt, spart Speicher.
Allerdings fehlt dazu ein ordentliches memory-management (refcounter)
2001-05-10 07:50:52 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (!fval(u, FL_MOVED)) {
|
|
|
|
|
for (S = u->orders; S; S = S->next) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(S->s, u->faction->locale) == K_GUARD && getparam(u->faction->locale) != P_NOT) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (rterrain(r) != T_OCEAN) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (!fval(u, RCF_ILLUSIONARY) && u->race != new_race[RC_SPELL]) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifdef WACH_WAFF
|
2002-03-01 20:32:25 +01:00
|
|
|
|
/* Monster der Monsterpartei d<>rfen immer bewachen */
|
|
|
|
|
if (u->faction == findfaction(MONSTER_FACTION)){
|
|
|
|
|
guard(u, GUARD_ALL);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (!armedmen(u)) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
add_message(&u->faction->msgs,
|
* möglichen Exploit beseitigt:
GIB xyz EINHEIT
GIB 0 ALLES SILBER
--> ALLE Befehle der übergebenen Einheit werden gelöscht.
* neue Funktion (convenience): ucansee(f, u1, u2)
liefert u1, wenn cansee(f,u1), sonst u2
* neue mistakes eingefügt uns übersetzt
* message bugfix:
u->htisorder kann gelöscht werden (z.b. NACH). Daher muss ein pointer auf
einen befehl in einer message immer auf den u->order Eintrag zeigen, damit er
zeit der auswertung noch existiert.
findorder(u, u->thisorder) tut das. Ist an mehreren Stellen nicht benutzt
worden. assert eingebaut, das das prüft.
* RESERVE_DONATIONS
Gegenstände, die von einer anderen Partei übergeben wurden, werden nicht
reserviert.
* TWOPASS_GIVE:
GIB Befehle werden zuerst an fremde Einheiten, danach in einem zweiten
Durchlauf an eigene Einheiten, ausgeführt.
* msg_message
An einigen messages ausprobiert, ob man die gleiche Message mehreren
Parteien einhängen kann - klappt, spart Speicher.
Allerdings fehlt dazu ein ordentliches memory-management (refcounter)
2001-05-10 07:50:52 +02:00
|
|
|
|
msg_error(u, S->s, "unit_unarmed", ""));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
guard(u, GUARD_ALL);
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, S->s, 95, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, S->s, 2, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
* möglichen Exploit beseitigt:
GIB xyz EINHEIT
GIB 0 ALLES SILBER
--> ALLE Befehle der übergebenen Einheit werden gelöscht.
* neue Funktion (convenience): ucansee(f, u1, u2)
liefert u1, wenn cansee(f,u1), sonst u2
* neue mistakes eingefügt uns übersetzt
* message bugfix:
u->htisorder kann gelöscht werden (z.b. NACH). Daher muss ein pointer auf
einen befehl in einer message immer auf den u->order Eintrag zeigen, damit er
zeit der auswertung noch existiert.
findorder(u, u->thisorder) tut das. Ist an mehreren Stellen nicht benutzt
worden. assert eingebaut, das das prüft.
* RESERVE_DONATIONS
Gegenstände, die von einer anderen Partei übergeben wurden, werden nicht
reserviert.
* TWOPASS_GIVE:
GIB Befehle werden zuerst an fremde Einheiten, danach in einem zweiten
Durchlauf an eigene Einheiten, ausgeführt.
* msg_message
An einigen messages ausprobiert, ob man die gleiche Message mehreren
Parteien einhängen kann - klappt, spart Speicher.
Allerdings fehlt dazu ein ordentliches memory-management (refcounter)
2001-05-10 07:50:52 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sinkships(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
|
|
|
|
/* Unbemannte Schiffe k<>nnen sinken */
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
ship *sh;
|
|
|
|
|
|
|
|
|
|
list_foreach(ship, r->ships, sh) {
|
|
|
|
|
if (rterrain(r) == T_OCEAN && (!enoughsailors(r, sh) || !kapitaen(r, sh))) {
|
|
|
|
|
/* Schiff nicht seet<65>chtig */
|
|
|
|
|
damage_ship(sh, 0.30);
|
|
|
|
|
}
|
|
|
|
|
if (!shipowner(r, sh)) {
|
|
|
|
|
damage_ship(sh, 0.05);
|
|
|
|
|
}
|
|
|
|
|
if (sh->damage >= sh->size * DAMAGE_SCALE)
|
|
|
|
|
destroy_ship(sh, r);
|
|
|
|
|
}
|
|
|
|
|
list_next(sh);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The following functions do not really belong here: */
|
|
|
|
|
#include "eressea.h"
|
|
|
|
|
#include "build.h"
|
|
|
|
|
|
|
|
|
|
static attrib_type at_number = {
|
- 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
|
|
|
|
"faction_renum",
|
2001-01-25 10:37:55 +01:00
|
|
|
|
NULL, NULL, NULL, NULL, NULL,
|
|
|
|
|
ATF_UNIQUE
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
renumber_factions(void)
|
|
|
|
|
/* gibt parteien neue nummern */
|
|
|
|
|
{
|
|
|
|
|
struct renum {
|
|
|
|
|
struct renum * next;
|
|
|
|
|
int want;
|
|
|
|
|
faction * faction;
|
|
|
|
|
attrib * attrib;
|
|
|
|
|
} * renum = NULL, * rp;
|
|
|
|
|
faction * f;
|
|
|
|
|
for (f=factions;f;f=f->next) {
|
|
|
|
|
attrib * a = a_find(f->attribs, &at_number);
|
|
|
|
|
int want;
|
|
|
|
|
struct renum ** rn;
|
|
|
|
|
faction * old;
|
|
|
|
|
|
|
|
|
|
if (!a) continue;
|
|
|
|
|
want = a->data.i;
|
|
|
|
|
if (fval(f, FF_NEWID)) {
|
|
|
|
|
sprintf(buf, "NUMMER PARTEI %s: Die Partei kann nicht mehr als einmal ihre Nummer wecheln", itoa36(want));
|
|
|
|
|
addmessage(0, f, buf, MSG_MESSAGE, ML_IMPORTANT);
|
|
|
|
|
}
|
|
|
|
|
old = findfaction(want);
|
|
|
|
|
if (old) {
|
|
|
|
|
a_remove(&f->attribs, a);
|
|
|
|
|
sprintf(buf, "Die Nummer %s wird von einer anderen Partei benutzt.", itoa36(want));
|
|
|
|
|
addmessage(0, f, buf, MSG_MESSAGE, ML_IMPORTANT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!faction_id_is_unused(want)) {
|
|
|
|
|
a_remove(&f->attribs, a);
|
|
|
|
|
sprintf(buf, "Die Nummer %s wurde schon einmal von einer anderen Partei benutzt.", itoa36(want));
|
|
|
|
|
addmessage(0, f, buf, MSG_MESSAGE, ML_IMPORTANT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
for (rn=&renum; *rn; rn=&(*rn)->next) {
|
|
|
|
|
if ((*rn)->want>=want) break;
|
|
|
|
|
}
|
|
|
|
|
if (*rn && (*rn)->want==want) {
|
|
|
|
|
a_remove(&f->attribs, a);
|
|
|
|
|
sprintf(buf, "Die Nummer %s wurde bereits einer anderen Partei zugeteilt.", itoa36(want));
|
|
|
|
|
addmessage(0, f, buf, MSG_MESSAGE, ML_IMPORTANT);
|
|
|
|
|
} else {
|
|
|
|
|
struct renum * r = calloc(sizeof(struct renum), 1);
|
|
|
|
|
r->next = *rn;
|
|
|
|
|
r->attrib = a;
|
|
|
|
|
r->faction = f;
|
|
|
|
|
r->want = want;
|
|
|
|
|
*rn = r;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (rp=renum;rp;rp=rp->next) {
|
|
|
|
|
a_remove(&rp->faction->attribs, rp->attrib);
|
2001-12-30 12:27:58 +01:00
|
|
|
|
if (updatelog) fprintf(updatelog, "renum %s %s\n", itoa36(rp->faction->no), itoa36(rp->want));
|
2002-03-03 11:51:24 +01:00
|
|
|
|
fprintf(sqlstream, "UPDATE subscriptions set faction='%s' where "
|
2002-04-20 22:07:35 +02:00
|
|
|
|
"faction='%s' and game=%d;\n", itoa36(rp->want),
|
2002-03-03 11:51:24 +01:00
|
|
|
|
itoa36(rp->faction->no), GAME_ID);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rp->faction->no = rp->want;
|
|
|
|
|
register_faction_id(rp->want);
|
|
|
|
|
fset(rp->faction, FF_NEWID);
|
|
|
|
|
}
|
|
|
|
|
while (renum) {
|
|
|
|
|
rp = renum->next;
|
|
|
|
|
free(renum);
|
|
|
|
|
renum = rp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
reorder(void)
|
|
|
|
|
{
|
|
|
|
|
region * r;
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
unit * u, ** up=&r->units;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
boolean sorted=false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
while (*up) {
|
|
|
|
|
u = *up;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
if (!fval(u, FL_MARK)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
strlist * o;
|
|
|
|
|
for (o=u->orders;o;o=o->next) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(o->s, u->faction->locale)==K_SORT) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
const char * s = getstrtoken();
|
2001-04-16 16:34:19 +02:00
|
|
|
|
param_t p = findparam(s, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int id = getid();
|
|
|
|
|
unit **vp, *v = findunit(id);
|
|
|
|
|
if (v==NULL || v->faction!=u->faction || v->region!=r) {
|
|
|
|
|
cmistake(u, o->s, 258, MSG_EVENT);
|
|
|
|
|
} else if (v->building != u->building || v->ship!=u->ship) {
|
|
|
|
|
cmistake(u, o->s, 259, MSG_EVENT);
|
|
|
|
|
} else if (fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u, o->s, 260, MSG_EVENT);
|
2001-02-03 14:45:35 +01:00
|
|
|
|
} else if (v == u) {
|
|
|
|
|
cmistake(u, o->s, 10, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
switch(p) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case P_AFTER:
|
|
|
|
|
*up = u->next;
|
|
|
|
|
u->next = v->next;
|
|
|
|
|
v->next = u;
|
|
|
|
|
break;
|
|
|
|
|
case P_BEFORE:
|
|
|
|
|
if (fval(v, FL_OWNER)) {
|
|
|
|
|
cmistake(u, o->s, 261, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
vp=&r->units;
|
|
|
|
|
while (*vp!=v) vp=&(*vp)->next;
|
|
|
|
|
*vp = u;
|
|
|
|
|
*up = u->next;
|
|
|
|
|
u->next = v;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
}
|
|
|
|
|
fset(u, FL_MARK);
|
|
|
|
|
sorted = true;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (u==*up) up=&u->next;
|
|
|
|
|
}
|
2001-02-11 11:06:07 +01:00
|
|
|
|
if (sorted) for (u=r->units;u;u=u->next) freset(u, FL_MARK);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-21 13:23:58 +02:00
|
|
|
|
#if 0
|
2002-04-28 14:47:29 +02:00
|
|
|
|
/* Aus Geb<65>ude weisen, VERBANNE */
|
2002-04-21 13:23:58 +02:00
|
|
|
|
static void
|
|
|
|
|
evict(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
strlist *S;
|
|
|
|
|
unit * u;
|
|
|
|
|
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
for (S = u->orders; S; S = S->next) if (igetkeyword(S->s, u->faction->locale)==K_EVICT) {
|
|
|
|
|
/* Nur der Kapit<69>n bzw Burgherr kann jemanden rausschmei<65>en */
|
|
|
|
|
if(!fval(u, FL_OWNER)) {
|
2002-04-28 14:47:29 +02:00
|
|
|
|
/* Die Einheit ist nicht der Eigent<6E>mer */
|
|
|
|
|
cmistake(u,S->s,49,MSG_EVENT);
|
2002-04-21 13:23:58 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int id = getid();
|
|
|
|
|
unit *u2 = findunit(id);
|
2002-04-28 14:47:29 +02:00
|
|
|
|
if (!u2){
|
|
|
|
|
/* Einheit nicht gefunden */
|
|
|
|
|
cmistake(u,S->s,63,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (u->building){
|
|
|
|
|
/* in der selben Burg? */
|
|
|
|
|
if (u->building != u2->building){
|
|
|
|
|
/* nicht in Burg */
|
|
|
|
|
cmistake(u,S->s,33,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
leave_building(u2);
|
|
|
|
|
/* meldung an beide */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (u->ship){
|
|
|
|
|
if (u->ship != u2->ship){
|
|
|
|
|
/* nicht an Bord */
|
|
|
|
|
cmistake(u,S->s,32,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
leave_ship(u2);
|
|
|
|
|
/* meldung an beide */
|
|
|
|
|
}
|
2002-04-21 13:23:58 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
renumber(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
char *s;
|
|
|
|
|
strlist *S;
|
|
|
|
|
unit * u;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
faction * f = u->faction;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
for (S = u->orders; S; S = S->next) if (igetkeyword(S->s, u->faction->locale)==K_NUMBER) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
s = getstrtoken();
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch(findparam(s, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
case P_FACTION:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if(strlen(s)>4) s[4]=0;
|
2001-04-01 08:58:45 +02:00
|
|
|
|
if (s && *s) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int i = atoi36(s);
|
|
|
|
|
attrib * a = a_find(f->attribs, &at_number);
|
|
|
|
|
if (!a) a = a_add(&f->attribs, a_new(&at_number));
|
|
|
|
|
a->data.i = i;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_UNIT:
|
|
|
|
|
s = getstrtoken();
|
2001-04-01 08:58:45 +02:00
|
|
|
|
if(s == NULL || *s == 0) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
i = newunitid();
|
|
|
|
|
} else {
|
|
|
|
|
i = atoi36(s);
|
|
|
|
|
if (i<=0 || i>MAX_UNIT_NR) {
|
|
|
|
|
cmistake(u,S->s,114,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(forbiddenid(i)) {
|
|
|
|
|
cmistake(u,S->s,116,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(findunitg(i, r)) {
|
|
|
|
|
cmistake(u,S->s,115,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
uunhash(u);
|
|
|
|
|
if (!ualias(u)) {
|
|
|
|
|
attrib *a = a_add(&u->attribs, a_new(&at_alias));
|
|
|
|
|
a->data.i = -u->no;
|
|
|
|
|
}
|
|
|
|
|
u->no = i;
|
|
|
|
|
uhash(u);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_SHIP:
|
|
|
|
|
if(!u->ship) {
|
|
|
|
|
cmistake(u,S->s,144,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u,S->s,146,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
s = getstrtoken();
|
2001-04-01 08:58:45 +02:00
|
|
|
|
if(s == NULL || *s == 0) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
i = newcontainerid();
|
|
|
|
|
} else {
|
|
|
|
|
i = atoi36(s);
|
|
|
|
|
if (i<=0 || i>MAX_CONTAINER_NR) {
|
|
|
|
|
cmistake(u,S->s,114,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (findship(i) || findbuilding(i)) {
|
|
|
|
|
cmistake(u,S->s,115,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sunhash(u->ship);
|
|
|
|
|
u->ship->no = i;
|
|
|
|
|
shash(u->ship);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_BUILDING:
|
|
|
|
|
if(!u->building) {
|
|
|
|
|
cmistake(u,S->s,145,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(!fval(u, FL_OWNER)) {
|
|
|
|
|
cmistake(u,S->s,148,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if(*s == 0) {
|
|
|
|
|
i = newcontainerid();
|
|
|
|
|
} else {
|
|
|
|
|
i = atoi36(s);
|
|
|
|
|
if (i<=0 || i>MAX_CONTAINER_NR) {
|
|
|
|
|
cmistake(u,S->s,114,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(findship(i) || findbuilding(i)) {
|
|
|
|
|
cmistake(u,S->s,115,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
bunhash(u->building);
|
|
|
|
|
u->building->no = i;
|
|
|
|
|
bhash(u->building);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
cmistake(u,S->s,239,MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
renumber_factions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ageing(void)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
region *r;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* altern spezieller Attribute, die eine Sonderbehandlung brauchen? */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for(r=regions;r;r=r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for(u=r->units;u;u=u->next) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* Goliathwasser */
|
|
|
|
|
int i = get_effect(u, oldpotiontype[P_STRONG]);
|
|
|
|
|
if (i > 0){
|
|
|
|
|
change_effect(u, oldpotiontype[P_STRONG], -1 * min(u->number, i));
|
|
|
|
|
}
|
|
|
|
|
/* Berserkerblut*/
|
|
|
|
|
i = get_effect(u, oldpotiontype[P_BERSERK]);
|
|
|
|
|
if (i > 0){
|
|
|
|
|
change_effect(u, oldpotiontype[P_BERSERK], -1 * min(u->number, i));
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (is_cursed(u->attribs, C_OLDRACE, 0)){
|
2002-05-01 21:08:32 +02:00
|
|
|
|
curse *c = get_curse(u->attribs, ct_find("oldrace"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (c->duration == 1 && !(c->flag & CURSE_NOAGE)) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u->race = new_race[c->effect];
|
|
|
|
|
u->irace = new_race[c->effect];
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Borders */
|
|
|
|
|
age_borders();
|
|
|
|
|
|
|
|
|
|
/* Factions */
|
|
|
|
|
for (f=factions;f;f=f->next) {
|
|
|
|
|
a_age(&f->attribs);
|
|
|
|
|
handle_event(&f->attribs, "timer", f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Regionen */
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
building ** bp;
|
|
|
|
|
unit ** up;
|
|
|
|
|
ship ** sp;
|
|
|
|
|
|
|
|
|
|
a_age(&r->attribs);
|
|
|
|
|
handle_event(&r->attribs, "timer", r);
|
|
|
|
|
/* Einheiten */
|
|
|
|
|
for (up=&r->units;*up;) {
|
|
|
|
|
unit * u = *up;
|
|
|
|
|
a_age(&u->attribs);
|
|
|
|
|
if (u==*up) handle_event(&u->attribs, "timer", u);
|
|
|
|
|
if (u==*up) up = &(*up)->next;
|
|
|
|
|
}
|
|
|
|
|
/* Schiffe */
|
|
|
|
|
for (sp=&r->ships;*sp;) {
|
|
|
|
|
ship * s = *sp;
|
|
|
|
|
a_age(&s->attribs);
|
|
|
|
|
if (s==*sp) handle_event(&s->attribs, "timer", s);
|
|
|
|
|
if (s==*sp) sp = &(*sp)->next;
|
|
|
|
|
}
|
|
|
|
|
/* Geb<65>ude */
|
|
|
|
|
for (bp=&r->buildings;*bp;) {
|
|
|
|
|
building * b = *bp;
|
|
|
|
|
a_age(&b->attribs);
|
|
|
|
|
if (b==*bp) handle_event(&b->attribs, "timer", b);
|
|
|
|
|
if (b==*bp) bp = &(*bp)->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
maxunits(faction *f)
|
|
|
|
|
{
|
2001-12-15 13:26:04 +01:00
|
|
|
|
return (int) (global.maxunits * (1 + 0.4 * fspecial(f, FS_ADMINISTRATOR)));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-21 19:22:48 +02:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
new_units (void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u, *u2;
|
|
|
|
|
strlist *S, *S2;
|
|
|
|
|
|
|
|
|
|
/* neue einheiten werden gemacht und ihre befehle (bis zum "ende" zu
|
|
|
|
|
* ihnen rueberkopiert, damit diese einheiten genauso wie die alten
|
|
|
|
|
* einheiten verwendet werden koennen. */
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next)
|
|
|
|
|
for (u = r->units; u; u = u->next)
|
|
|
|
|
for (S = u->orders; S;) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if ((igetkeyword(S->s, u->faction->locale) == K_MAKE) && (getparam(u->faction->locale) == P_TEMP)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int g;
|
|
|
|
|
char * name;
|
|
|
|
|
int alias;
|
|
|
|
|
int mu = maxunits(u->faction);
|
|
|
|
|
|
|
|
|
|
if(u->faction->no_units >= mu) {
|
|
|
|
|
sprintf(buf, "Eine Partei darf aus nicht mehr als %d "
|
|
|
|
|
"Einheiten bestehen.", mu);
|
|
|
|
|
mistake(u, S->s, buf, MSG_PRODUCE);
|
|
|
|
|
S = S->next;
|
|
|
|
|
|
|
|
|
|
while (S) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(S->s, u->faction->locale) == K_END)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
S2 = S->next;
|
|
|
|
|
removelist(&u->orders, S);
|
|
|
|
|
S = S2;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
alias = getid();
|
|
|
|
|
|
|
|
|
|
name = getstrtoken();
|
|
|
|
|
if (name && strlen(name)==0) name = NULL;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
a_add(&u2->attribs, a_new(&at_alias))->data.i = alias;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
g = getguard(u);
|
|
|
|
|
if (g) setguard(u2, g);
|
|
|
|
|
else setguard(u, GUARD_NONE);
|
|
|
|
|
|
|
|
|
|
S = S->next;
|
|
|
|
|
|
|
|
|
|
while (S) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(S->s, u->faction->locale) == K_END)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
S2 = S->next;
|
|
|
|
|
translist(&u->orders, &u2->orders, S);
|
|
|
|
|
S = S2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (S)
|
|
|
|
|
S = S->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* im for-loop wuerde S = S->next ausgefuehrt, bevor S geprueft wird.
|
|
|
|
|
* Wenn S aber schon 0x0 ist, fuehrt das zu einem Fehler. Und wenn wir
|
|
|
|
|
* den while (S) ganz durchlaufen, wird S = 0x0 sein! Dh. wir
|
|
|
|
|
* sicherstellen, dass S != 0, bevor wir S = S->next auszufuehren! */
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setdefaults (void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next){
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
boolean trade = false;
|
|
|
|
|
|
|
|
|
|
set_string(&u->thisorder, u->lastorder);
|
|
|
|
|
for(S = u->orders; S; S = S->next) {
|
2002-01-13 10:14:13 +01:00
|
|
|
|
const char * cmd;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
keyword_t keyword = igetkeyword(S->s, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
switch (keyword) {
|
|
|
|
|
|
|
|
|
|
/* Wenn gehandelt wird, darf kein langer Befehl ausgef<65>hrt
|
|
|
|
|
* werden. Da Handel erst nach anderen langen Befehlen kommt,
|
|
|
|
|
* mu<EFBFBD> das vorher abgefangen werden. Wir merken uns also
|
|
|
|
|
* hier, ob die Einheit handelt. */
|
|
|
|
|
|
|
|
|
|
case K_BUY:
|
|
|
|
|
case K_SELL:
|
|
|
|
|
trade = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2001-05-27 16:02:12 +02:00
|
|
|
|
case K_CAST:
|
|
|
|
|
set_string(&u->thisorder, "");
|
|
|
|
|
break;
|
|
|
|
|
/* dient dazu, das neben Zaubern kein weiterer Befehl
|
|
|
|
|
* ausgef<EFBFBD>hrt werden kann, Zaubern ist ein kurzer Befehl */
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen
|
|
|
|
|
* Arten von MACHE zaehlen aber als neue defaults und werden
|
|
|
|
|
* behandelt wie die anderen (deswegen kein break nach case
|
|
|
|
|
* K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl)
|
|
|
|
|
* abgespeichert). */
|
|
|
|
|
|
|
|
|
|
case K_MAKE:
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (getparam(u->faction->locale) == P_TEMP) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_BESIEGE:
|
|
|
|
|
case K_ENTERTAIN:
|
|
|
|
|
case K_RESEARCH:
|
|
|
|
|
case K_SPY:
|
|
|
|
|
case K_STEAL:
|
|
|
|
|
case K_SABOTAGE:
|
|
|
|
|
case K_STUDY:
|
|
|
|
|
case K_TAX:
|
|
|
|
|
case K_TEACH:
|
|
|
|
|
case K_ZUECHTE:
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2001-12-10 01:13:39 +01:00
|
|
|
|
case K_PFLANZE:
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_BIETE:
|
|
|
|
|
case K_PIRACY:
|
|
|
|
|
if (idle (u->faction)) {
|
2001-12-23 11:32:57 +01:00
|
|
|
|
set_string (&u->thisorder, locale_string(u->faction->locale, "defaultorder"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Ab hier Befehle, die auch eine idle
|
|
|
|
|
* Faction machen darf: */
|
|
|
|
|
case K_ROUTE:
|
|
|
|
|
case K_WORK:
|
|
|
|
|
case K_DRIVE:
|
|
|
|
|
case K_MOVE:
|
2002-04-12 14:46:16 +02:00
|
|
|
|
case K_WEREWOLF:
|
2002-01-13 10:14:13 +01:00
|
|
|
|
cmd = S->s;
|
|
|
|
|
#if HUNGER_DISABLES_LONGORDERS
|
|
|
|
|
if (fval(u, FL_HUNGER)) {
|
|
|
|
|
cmd = locale_string(u->faction->locale, "defaultorder");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2002-01-13 10:14:13 +01:00
|
|
|
|
#endif
|
|
|
|
|
set_string(&u->thisorder, cmd);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen
|
|
|
|
|
* mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern
|
|
|
|
|
* nicht moeglich ist, Schulden zu machen. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Wenn die Einheit handelt, mu<6D> der Default-Befehl gel<65>scht
|
|
|
|
|
* werden. */
|
|
|
|
|
|
2001-02-18 11:06:10 +01:00
|
|
|
|
if(trade == true) {
|
2001-02-18 20:07:31 +01:00
|
|
|
|
/* fset(u, FL_LONGACTION); */
|
2001-02-18 11:06:10 +01:00
|
|
|
|
set_string(&u->thisorder, "");
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* thisorder kopieren wir nun nach lastorder. in lastorder steht
|
|
|
|
|
* der DEFAULT befehl der einheit. da MOVE kein default werden
|
|
|
|
|
* darf, wird MOVE nicht in lastorder kopiert. MACHE TEMP wurde ja
|
|
|
|
|
* schon gar nicht erst in thisorder kopiert, so dass MACHE TEMP
|
|
|
|
|
* durch diesen code auch nicht zum default wird Ebenso soll BIETE
|
|
|
|
|
* nicht hierher, da i.A. die Einheit dann ja weg ist (und damit
|
|
|
|
|
* die Einheitsnummer ungueltig). Auch Attackiere sollte nie in
|
|
|
|
|
* den Default <EFBFBD>bernommen werden */
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch (igetkeyword (u->thisorder, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_MOVE:
|
|
|
|
|
case K_BIETE:
|
|
|
|
|
case K_ATTACK:
|
2002-04-12 14:46:16 +02:00
|
|
|
|
case K_WEREWOLF:
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
set_string(&u->lastorder, u->thisorder);
|
|
|
|
|
}
|
|
|
|
|
/* Attackiere sollte niemals Default werden */
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(u->lastorder, u->faction->locale) == K_ATTACK)
|
2001-12-23 11:32:57 +01:00
|
|
|
|
set_string(&u->lastorder, locale_string(u->faction->locale, "defaultorder"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2002-03-16 18:30:48 +01:00
|
|
|
|
use_item(unit * u, const item_type * itype, int amount, const char * cmd)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int i;
|
2002-03-16 18:30:48 +01:00
|
|
|
|
int target = read_unitid(u->faction, u->region);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
i = new_get_pooled(u, itype->rtype, GET_DEFAULT);
|
|
|
|
|
|
2002-03-16 18:30:48 +01:00
|
|
|
|
if (amount>i) {
|
|
|
|
|
amount = i;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (i==0) {
|
|
|
|
|
cmistake(u, cmd, 43, MSG_PRODUCE);
|
|
|
|
|
return ENOITEM;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-16 18:30:48 +01:00
|
|
|
|
if (target==-1) {
|
|
|
|
|
if (itype->use==NULL) {
|
|
|
|
|
cmistake(u, cmd, 76, MSG_PRODUCE);
|
|
|
|
|
return EUNUSABLE;
|
|
|
|
|
}
|
|
|
|
|
return itype->use(u, itype, amount, cmd);
|
|
|
|
|
} else {
|
|
|
|
|
if (itype->useonother==NULL) {
|
|
|
|
|
cmistake(u, cmd, 76, MSG_PRODUCE);
|
|
|
|
|
return EUNUSABLE;
|
|
|
|
|
}
|
|
|
|
|
return itype->useonother(u, target, itype, amount, cmd);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
canheal(const unit *u)
|
|
|
|
|
{
|
2001-12-10 01:13:39 +01:00
|
|
|
|
switch(old_race(u->race)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case RC_DAEMON:
|
|
|
|
|
return 15;
|
|
|
|
|
break;
|
|
|
|
|
case RC_GOBLIN:
|
|
|
|
|
return 20;
|
|
|
|
|
break;
|
|
|
|
|
case RC_TROLL:
|
|
|
|
|
return 15;
|
|
|
|
|
break;
|
|
|
|
|
case RC_FIREDRAGON:
|
|
|
|
|
case RC_DRAGON:
|
|
|
|
|
case RC_WYRM:
|
|
|
|
|
return 10;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->race->flags & RCF_NOHEAL) return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
monthly_healing(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
int p;
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
int umhp;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if((u->race->flags & RCF_NOHEAL) || fval(u, FL_HUNGER) || fspecial(u->faction, FS_UNDEAD))
|
2001-01-25 10:37:55 +01:00
|
|
|
|
continue;
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if(rterrain(r) == T_OCEAN && !u->ship && !(u->race->flags & RCF_SWIM))
|
2001-01-25 10:37:55 +01:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
umhp = unit_max_hp(u) * u->number;
|
|
|
|
|
|
|
|
|
|
if(fspecial(u->faction, FS_REGENERATION)) {
|
|
|
|
|
u->hp = umhp;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Effekt von Elixier der Macht schwindet */
|
|
|
|
|
if (u->hp > umhp) {
|
|
|
|
|
u->hp -= (int) ceil((u->hp - umhp) / 2.0);
|
|
|
|
|
if (u->hp < umhp)
|
|
|
|
|
u->hp = umhp;
|
|
|
|
|
}
|
|
|
|
|
else if (u->hp < umhp && (p=canheal(u)) > 0) {
|
|
|
|
|
/* Mind 1 HP wird pro Runde geheilt, weil angenommen wird,
|
|
|
|
|
das alle Personen mind. 10 HP haben. */
|
|
|
|
|
int max_unit = max(umhp, u->number * 10);
|
|
|
|
|
#ifdef NEW_TAVERN
|
|
|
|
|
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("inn")) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
max_unit = max_unit * 3 / 2;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/* Aufaddieren der geheilten HP. */
|
|
|
|
|
u->hp = min(u->hp + max_unit/(100/p), umhp);
|
|
|
|
|
if (u->hp < umhp && (rand() % 10 < max_unit % 10))
|
|
|
|
|
++u->hp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
defaultorders (void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
char * c;
|
|
|
|
|
int i;
|
|
|
|
|
strlist *s;
|
|
|
|
|
list_foreach(region, regions, r) {
|
|
|
|
|
list_foreach(unit, r->units, u) {
|
|
|
|
|
list_foreach(strlist, u->orders, s) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch (igetkeyword(s->s, u->faction->locale)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_DEFAULT:
|
|
|
|
|
c = getstrtoken();
|
|
|
|
|
i = atoi(c);
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 0 :
|
|
|
|
|
if (c[0]=='0') set_string(&u->lastorder, getstrtoken());
|
|
|
|
|
else set_string(&u->lastorder, c);
|
|
|
|
|
s->s[0]=0;
|
|
|
|
|
break;
|
|
|
|
|
case 1 :
|
2001-04-16 16:34:19 +02:00
|
|
|
|
sprintf(buf, "%s \"%s\"", locale_string(u->faction->locale, keywords[K_DEFAULT]), getstrtoken());
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_string(&s->s, buf);
|
|
|
|
|
break;
|
|
|
|
|
default :
|
2001-04-16 16:34:19 +02:00
|
|
|
|
sprintf(buf, "%s %d \"%s\"", locale_string(u->faction->locale, keywords[K_DEFAULT]), i-1, getstrtoken());
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_string(&s->s, buf);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
list_next(s);
|
|
|
|
|
}
|
|
|
|
|
list_next(u);
|
|
|
|
|
}
|
|
|
|
|
list_next(r);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SKILLFIX_SAVE
|
|
|
|
|
void write_skillfix(void);
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-03-04 19:41:27 +01:00
|
|
|
|
/* ************************************************************ */
|
|
|
|
|
/* GANZ WICHTIG! ALLE GE<47>NDERTEN SPR<50>CHE NEU ANZEIGEN */
|
|
|
|
|
/* GANZ WICHTIG! F<>GT AUCH NEUE ZAUBER IN DIE LISTE DER BEKANNTEN EIN */
|
|
|
|
|
/* ************************************************************ */
|
|
|
|
|
static void
|
|
|
|
|
update_spells(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
for(r=regions; r; r=r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for(u=r->units;u;u=u->next) {
|
|
|
|
|
sc_mage *m = get_mage(u);
|
|
|
|
|
if (u->faction->no != MONSTER_FACTION && m != NULL) {
|
|
|
|
|
if (m->magietyp == M_GRAU) continue;
|
|
|
|
|
updatespelllist(u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2002-01-27 11:57:26 +01:00
|
|
|
|
static void
|
|
|
|
|
age_factions(void)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
2002-03-27 22:49:27 +01:00
|
|
|
|
++f->age;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (f->age < IMMUN_GEGEN_ANGRIFF) {
|
|
|
|
|
add_message(&f->msgs, new_message(f,
|
|
|
|
|
"newbieimmunity%i:turns", IMMUN_GEGEN_ANGRIFF - f->age));
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-01-27 11:57:26 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-01-27 11:57:26 +01:00
|
|
|
|
static void
|
|
|
|
|
use(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
for (S = u->orders; S; S = S->next) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(S->s, u->faction->locale) == K_USE) {
|
2002-03-16 18:30:48 +01:00
|
|
|
|
const char * t = getstrtoken();
|
|
|
|
|
int n = atoi(t);
|
|
|
|
|
const item_type * itype;
|
|
|
|
|
if (n==0) {
|
|
|
|
|
n = 1;
|
2002-03-17 12:43:55 +01:00
|
|
|
|
} else {
|
2002-03-16 18:30:48 +01:00
|
|
|
|
t = getstrtoken();
|
|
|
|
|
}
|
|
|
|
|
itype = finditemtype(t, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if (itype!=NULL) {
|
2002-03-16 18:30:48 +01:00
|
|
|
|
use_item(u, itype, n, S->s);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, S->s, 43, MSG_PRODUCE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-01-27 11:57:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
processorders (void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
|
|
|
|
if (turn == 0) srand(time((time_t *) NULL));
|
|
|
|
|
else srand(turn);
|
|
|
|
|
|
|
|
|
|
puts(" - neue Einheiten erschaffen...");
|
|
|
|
|
new_units();
|
|
|
|
|
|
|
|
|
|
puts(" - Monster KI...");
|
|
|
|
|
plan_monsters();
|
|
|
|
|
set_passw(); /* und pruefe auf illegale Befehle */
|
|
|
|
|
|
|
|
|
|
puts(" - Defaults und Instant-Befehle...");
|
|
|
|
|
setdefaults();
|
|
|
|
|
instant_orders();
|
|
|
|
|
|
|
|
|
|
mail();
|
|
|
|
|
puts(" - Altern");
|
|
|
|
|
age_factions();
|
|
|
|
|
|
|
|
|
|
puts(" - Benutzen");
|
|
|
|
|
use();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
puts(" - Kontaktieren, Betreten von Schiffen und Geb<65>uden (1.Versuch)");
|
|
|
|
|
do_misc(0);
|
2001-04-26 19:41:06 +02:00
|
|
|
|
|
|
|
|
|
puts(" - GM Kommandos");
|
|
|
|
|
infocommands();
|
|
|
|
|
gmcommands();
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
puts(" - Verlassen");
|
|
|
|
|
do_leave();
|
|
|
|
|
|
|
|
|
|
puts(" - Kontakte l<>schen");
|
|
|
|
|
remove_contacts();
|
|
|
|
|
|
|
|
|
|
puts(" - Jihad-Angriffe");
|
|
|
|
|
jihad_attacks();
|
|
|
|
|
|
|
|
|
|
puts(" - Attackieren");
|
|
|
|
|
if(nobattle == false) do_battle();
|
|
|
|
|
if (turn == 0) srand(time((time_t *) NULL));
|
|
|
|
|
else srand(turn);
|
|
|
|
|
|
|
|
|
|
puts(" - Belagern");
|
|
|
|
|
do_siege();
|
|
|
|
|
|
|
|
|
|
puts(" - Initialisieren des Pools, Reservieren");
|
|
|
|
|
init_pool();
|
|
|
|
|
|
|
|
|
|
puts(" - Kontaktieren, Betreten von Schiffen und Geb<65>uden (2.Versuch)");
|
|
|
|
|
do_misc(1);
|
|
|
|
|
|
|
|
|
|
puts(" - Folge setzen");
|
|
|
|
|
follow();
|
|
|
|
|
|
|
|
|
|
if (turn == 0) srand(time((time_t *) NULL));
|
|
|
|
|
else srand(turn);
|
|
|
|
|
|
|
|
|
|
puts(" - Zerst<73>ren, Geben, Rekrutieren, Vergessen");
|
|
|
|
|
economics();
|
2002-01-27 11:40:40 +01:00
|
|
|
|
remove_empty_units();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-02-03 14:45:35 +01:00
|
|
|
|
puts(" - Geb<65>udeunterhalt (1. Versuch)");
|
|
|
|
|
maintain_buildings(false);
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
puts(" - Sterben");
|
|
|
|
|
quit();
|
|
|
|
|
|
|
|
|
|
puts(" - Zaubern");
|
|
|
|
|
magic();
|
2002-02-22 20:41:20 +01:00
|
|
|
|
remove_empty_units();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
puts(" - Lehren");
|
|
|
|
|
teaching();
|
|
|
|
|
|
|
|
|
|
puts(" - Lernen");
|
|
|
|
|
learn();
|
|
|
|
|
|
|
|
|
|
puts(" - Produzieren, Geldverdienen, Handeln, Anwerben");
|
|
|
|
|
produce();
|
|
|
|
|
|
|
|
|
|
puts(" - Schiffe sinken");
|
|
|
|
|
sinkships();
|
|
|
|
|
|
|
|
|
|
puts(" - Bewegungen");
|
|
|
|
|
movement();
|
|
|
|
|
|
|
|
|
|
puts(" - Bewache (an)");
|
|
|
|
|
bewache_an();
|
|
|
|
|
|
|
|
|
|
puts(" - Zufallsbegegnungen");
|
|
|
|
|
encounters();
|
|
|
|
|
|
|
|
|
|
if (turn == 0) srand(time((time_t *) NULL));
|
|
|
|
|
else srand(turn);
|
|
|
|
|
|
|
|
|
|
puts(" - Monster fressen und vertreiben Bauern");
|
|
|
|
|
monsters_kill_peasants();
|
|
|
|
|
|
2002-04-27 21:40:31 +02:00
|
|
|
|
puts(" - random events");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
randomevents();
|
2002-04-27 21:40:31 +02:00
|
|
|
|
|
|
|
|
|
puts(" - newspaper commands");
|
|
|
|
|
xecmd();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-03-31 13:52:28 +02:00
|
|
|
|
puts(" - regeneration (healing & aura)");
|
|
|
|
|
monthly_healing();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
regeneration_magiepunkte();
|
|
|
|
|
|
|
|
|
|
#if NEW_LAEN
|
|
|
|
|
puts(" - Laenwachstum");
|
|
|
|
|
growlaen();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
puts(" - Defaults setzen");
|
|
|
|
|
defaultorders();
|
|
|
|
|
|
|
|
|
|
puts(" - Unterhaltskosten, Nachfrage, Seuchen, Wachstum, Auswanderung");
|
|
|
|
|
demographics();
|
|
|
|
|
|
|
|
|
|
puts(" - Geb<65>udeunterhalt (2. Versuch)");
|
|
|
|
|
maintain_buildings(true);
|
|
|
|
|
|
|
|
|
|
puts(" - Jihads setzen");
|
|
|
|
|
set_jihad();
|
|
|
|
|
|
2001-04-29 21:27:42 +02:00
|
|
|
|
#ifdef USE_UGROUPS
|
2001-04-28 17:39:13 +02:00
|
|
|
|
puts(" - Verb<72>nde bilden");
|
|
|
|
|
ugroups();
|
2001-04-29 21:27:42 +02:00
|
|
|
|
#endif
|
2001-04-28 17:39:13 +02:00
|
|
|
|
|
2001-02-25 20:31:40 +01:00
|
|
|
|
puts(" - Einheiten Sortieren");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
reorder();
|
2002-04-21 13:23:58 +02:00
|
|
|
|
#if 0
|
|
|
|
|
puts(" - Einheiten aus Geb<65>uden/Schiffen weisen");
|
|
|
|
|
evict();
|
|
|
|
|
#endif
|
2001-02-25 20:31:40 +01:00
|
|
|
|
puts(" - Neue Nummern");
|
|
|
|
|
renumber();
|
2001-02-11 13:10:58 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
for (r = regions;r;r=r->next) reorder_owners(r);
|
|
|
|
|
|
|
|
|
|
puts(" - Attribute altern");
|
|
|
|
|
ageing();
|
|
|
|
|
|
|
|
|
|
#ifdef SKILLFIX_SAVE
|
|
|
|
|
write_skillfix();
|
|
|
|
|
#endif
|
2001-03-04 19:41:27 +01:00
|
|
|
|
/* immer ausf<73>hren, wenn neue Spr<70>che dazugekommen sind, oder sich
|
|
|
|
|
* Beschreibungen ge<EFBFBD>ndert haben */
|
|
|
|
|
update_spells();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2001-02-10 11:40:12 +01:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
count_migrants (const faction * f)
|
|
|
|
|
{
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
unit *u = f->units;
|
|
|
|
|
int n = 0;
|
|
|
|
|
while (u) {
|
|
|
|
|
assert(u->faction == f);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u->race != f->race && u->race != new_race[RC_ILLUSION] && u->race != new_race[RC_SPELL]
|
|
|
|
|
&& !!playerrace(u->race) && !(is_cursed(u->attribs, C_SLAVE, 0)))
|
2001-02-10 11:40:12 +01:00
|
|
|
|
{
|
|
|
|
|
n += u->number;
|
|
|
|
|
}
|
|
|
|
|
u = u->nextF;
|
|
|
|
|
}
|
|
|
|
|
if (f->num_migrants != n)
|
|
|
|
|
puts("FEHLER: Anzahl Migranten falsch");
|
|
|
|
|
#endif
|
|
|
|
|
return f->num_migrants;
|
|
|
|
|
}
|