2001-01-25 10:37:55 +01:00
|
|
|
|
/* vi: set ts=2:
|
|
|
|
|
*
|
2001-04-16 16:34:19 +02:00
|
|
|
|
*
|
2003-07-29 11:48:03 +02:00
|
|
|
|
* Eressea PB(E)M host Copyright (C) 1998-2003
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* Christian Schlittchen (corwin@amber.kn-bremen.de)
|
|
|
|
|
* Katja Zedel (katze@felidae.kn-bremen.de)
|
|
|
|
|
* Henning Peters (faroul@beyond.kn-bremen.de)
|
|
|
|
|
* Enno Rehling (enno@eressea-pbem.de)
|
|
|
|
|
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
|
|
|
*
|
|
|
|
|
* based on:
|
|
|
|
|
*
|
|
|
|
|
* Atlantis v1.0 13 September 1993 Copyright 1993 by Russell Wallace
|
|
|
|
|
* Atlantis v1.7 Copyright 1996 by Alex Schr<EFBFBD>der
|
|
|
|
|
*
|
|
|
|
|
* This program may not be used, modified or distributed without
|
|
|
|
|
* prior permission by the authors of Eressea.
|
|
|
|
|
* This program may not be sold or used commercially without prior written
|
|
|
|
|
* permission from the authors.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
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>
|
2004-02-21 23:25:00 +01:00
|
|
|
|
#ifdef WORMHOLE_MODULE
|
|
|
|
|
#include <modules/wormhole.h>
|
|
|
|
|
#endif
|
2001-01-30 21:02:06 +01:00
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
/* gamecode includes */
|
|
|
|
|
#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>
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#ifdef ALLIANCES
|
|
|
|
|
#include <modules/alliance.h>
|
|
|
|
|
#endif
|
2002-04-27 21:40:31 +02:00
|
|
|
|
|
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;
|
2003-09-21 12:09:08 +02:00
|
|
|
|
boolean nomonsters = false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static int
|
2003-09-21 09:40:16 +02:00
|
|
|
|
RemoveNMRNewbie(void) {
|
2004-04-10 12:43:46 +02:00
|
|
|
|
static int value = -1;
|
|
|
|
|
if (value<0) {
|
|
|
|
|
const char * str = get_param(global.parameters, "nmr.removenewbie");
|
|
|
|
|
value = str?atoi(str):0;
|
|
|
|
|
}
|
|
|
|
|
return value;
|
2003-07-29 11:48:03 +02: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
|
|
|
|
{
|
2004-04-12 01:56:47 +02:00
|
|
|
|
faction * oldf = u->faction;
|
|
|
|
|
faction *f = addfaction(oldf->email, oldf->passw, rc, oldf->locale, oldf->subscription);
|
2003-12-14 11:02:29 +01:00
|
|
|
|
unit * nu = addplayer(u->region, f);
|
2004-04-10 12:43:46 +02:00
|
|
|
|
strlist ** o=&u->orders;
|
2002-11-02 15:10:52 +01:00
|
|
|
|
f->subscription = u->faction->subscription;
|
2004-04-10 12:43:46 +02:00
|
|
|
|
fset(f, FFL_RESTART);
|
|
|
|
|
if (f->subscription) fprintf(sqlstream, "UPDATE subscriptions set faction='%s', race='%s' where id=%u;\n",
|
2002-11-02 15:10:52 +01:00
|
|
|
|
itoa36(f->no), dbrace(rc), f->subscription);
|
2004-04-10 12:43:46 +02:00
|
|
|
|
f->magiegebiet = u->faction->magiegebiet;
|
|
|
|
|
f->options = u->faction->options;
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
destroyfaction(u->faction);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
checkorders(void)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
puts(" - Warne sp<73>te Spieler...");
|
|
|
|
|
for (f = factions; f; f = f->next)
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (f->no!=MONSTER_FACTION && turn - f->lastorders == NMRTimeout() - 1)
|
2002-07-29 09:35:37 +02:00
|
|
|
|
ADDMSG(&f->msgs, msg_message("turnreminder", ""));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2004-03-09 22:14:27 +01:00
|
|
|
|
static boolean
|
|
|
|
|
help_money(const unit * u)
|
|
|
|
|
{
|
|
|
|
|
if (u->race->ec_flags & GIVEITEM) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
get_food(region *r)
|
|
|
|
|
{
|
|
|
|
|
unit *u;
|
2003-03-26 10:30:32 +01:00
|
|
|
|
int peasantfood = rpeasants(r)*10;
|
2004-02-29 09:59:15 +01:00
|
|
|
|
unit * demon = r->units;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
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 */
|
2003-07-29 11:48:03 +02:00
|
|
|
|
freset(u, UFL_HUNGER);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
need -= get_money(u);
|
|
|
|
|
if (need > 0) {
|
|
|
|
|
unit *v;
|
|
|
|
|
|
2004-03-09 22:14:27 +01:00
|
|
|
|
for (v = r->units; need && v; v = v->next) {
|
|
|
|
|
if (v->faction == u->faction && help_money(v)) {
|
|
|
|
|
int give = get_money(v) - lifestyle(v);
|
|
|
|
|
give = min(need, give);
|
|
|
|
|
if (give>0) {
|
|
|
|
|
change_money(v, -give);
|
|
|
|
|
change_money(u, give);
|
|
|
|
|
need -= give;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
2004-03-09 22:14:27 +01:00
|
|
|
|
faction * f = u->faction;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
need -= max(0, get_money(u));
|
|
|
|
|
|
|
|
|
|
if (need > 0) {
|
|
|
|
|
unit *v;
|
|
|
|
|
|
2003-03-24 23:42:41 +01:00
|
|
|
|
for (v = r->units; need && v; v = v->next) {
|
2004-03-09 22:14:27 +01:00
|
|
|
|
if (v->faction != f && alliedunit(v, f, HELP_MONEY) && help_money(v)) {
|
|
|
|
|
int give = get_money(v) - lifestyle(v);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
give = min(need, give);
|
|
|
|
|
|
2004-03-09 22:14:27 +01:00
|
|
|
|
if (give>0) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
change_money(v, -give);
|
|
|
|
|
change_money(u, give);
|
|
|
|
|
need -= give;
|
|
|
|
|
add_spende(v->faction, u->faction, give, r);
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-03-24 23:42:41 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Die Einheit hat nicht genug Geld zusammengekratzt und
|
|
|
|
|
* nimmt Schaden: */
|
2003-03-24 23:42:41 +01:00
|
|
|
|
if (need) {
|
|
|
|
|
int lspp = lifestyle(u)/u->number;
|
|
|
|
|
if (lspp > 0) {
|
|
|
|
|
int number = (need+lspp-1)/lspp;
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (hunger(number, u)) fset(u, UFL_HUNGER);
|
2003-03-24 23:42:41 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-02-29 09:59:15 +01:00
|
|
|
|
/* 3. bestimmen, wie viele Bauern gefressen werden.
|
|
|
|
|
* bei fehlenden Bauern den D<EFBFBD>mon hungern lassen
|
|
|
|
|
*/
|
2003-03-26 10:30:32 +01:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (u->race == new_race[RC_DAEMON]) {
|
2004-02-29 09:59:15 +01:00
|
|
|
|
int hungry = u->number;
|
|
|
|
|
|
|
|
|
|
while (demon!=NULL && hungry>0) {
|
|
|
|
|
/* alwayy start with the first known uint that may have some blood */
|
|
|
|
|
static const struct potion_type * pt_blood;
|
|
|
|
|
unit * ud = demon;
|
|
|
|
|
if (pt_blood==NULL) pt_blood = pt_find("peasantblood");
|
|
|
|
|
demon = NULL; /* this will be re-set in the loop */
|
|
|
|
|
while (ud!=NULL) {
|
|
|
|
|
if (ud->race==new_race[RC_DAEMON]) {
|
|
|
|
|
if (get_effect(ud, pt_blood)) {
|
|
|
|
|
/* new best guess for first blood-donor: */
|
|
|
|
|
if (demon==NULL) demon = ud;
|
|
|
|
|
/* if he's in our faction, drain him: */
|
|
|
|
|
if (ud->faction==u->faction) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ud=ud->next;
|
|
|
|
|
}
|
|
|
|
|
if (ud!=NULL) {
|
|
|
|
|
int blut = get_effect(ud, pt_blood);
|
|
|
|
|
blut = min(blut, hungry);
|
|
|
|
|
change_effect(ud, pt_blood, -blut);
|
|
|
|
|
hungry -= blut;
|
2004-02-29 11:00:26 +01:00
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
/* no more help for us */
|
|
|
|
|
}
|
2004-02-29 09:59:15 +01:00
|
|
|
|
}
|
2003-03-26 10:30:32 +01:00
|
|
|
|
if (r->planep == NULL || !fval(r->planep, PFL_NOFEED)) {
|
2004-02-29 09:59:15 +01:00
|
|
|
|
if (peasantfood>=hungry) {
|
|
|
|
|
peasantfood -= hungry;
|
|
|
|
|
hungry = 0;
|
2003-03-26 10:30:32 +01:00
|
|
|
|
} else {
|
2004-02-29 09:59:15 +01:00
|
|
|
|
hungry -= peasantfood;
|
2003-03-26 10:30:32 +01:00
|
|
|
|
peasantfood = 0;
|
|
|
|
|
}
|
2004-02-29 09:59:15 +01:00
|
|
|
|
if (hungry > 0) {
|
|
|
|
|
hunger(hungry, u); /* nicht gef<65>tterte d<>monen hungern */
|
2003-03-24 23:42:41 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-03-26 10:30:32 +01:00
|
|
|
|
rsetpeasants(r, peasantfood/10);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
|
{
|
2004-04-09 03:32:06 +02:00
|
|
|
|
unit **up = &r->units;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-04-09 03:32:06 +02:00
|
|
|
|
get_food(r);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-04-09 03:32:06 +02:00
|
|
|
|
while (*up) {
|
2004-03-09 22:14:27 +01:00
|
|
|
|
unit * u = *up;
|
2004-04-09 03:32:06 +02:00
|
|
|
|
/* 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 */
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
reduce_skill(u, sb, weeks);
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("dumbeffect",
|
|
|
|
|
"unit weeks skill", u, weeks, (skill_t)sb->id));
|
|
|
|
|
} /* sonst Gl<47>ck gehabt: wer nix wei<65>, kann nix vergessen... */
|
2004-03-09 22:14:27 +01:00
|
|
|
|
change_effect(u, oldpotiontype[P_FOOL], -effect);
|
2004-04-09 03:32:06 +02:00
|
|
|
|
}
|
2004-03-09 22:14:27 +01:00
|
|
|
|
age_unit(r, u);
|
|
|
|
|
if (*up==u) up=&u->next;
|
2004-04-09 03:32:06 +02:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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 */
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2002-02-24 20:29:21 +01:00
|
|
|
|
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(a_find(r->attribs, &at_laen)) {
|
|
|
|
|
rsetlaen(r, rlaen(r) + rand() % MAXLAENPERTURN);
|
|
|
|
|
}
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-24 22:54:14 +02:00
|
|
|
|
#ifdef ENHANCED_QUIT
|
|
|
|
|
static void
|
|
|
|
|
transfer_faction(faction *f, faction *f2)
|
|
|
|
|
{
|
|
|
|
|
unit *u, *un;
|
|
|
|
|
|
|
|
|
|
for (u = f->units; u;) {
|
2003-04-27 09:44:05 +02:00
|
|
|
|
un = u->nextF;
|
2003-04-24 22:54:14 +02:00
|
|
|
|
if(!unit_has_cursed_item(u)
|
|
|
|
|
&& !has_skill(u, SK_MAGIC)
|
|
|
|
|
&& !has_skill(u, SK_ALCHEMY)) {
|
|
|
|
|
u_setfaction(u, f2);
|
|
|
|
|
}
|
|
|
|
|
u = un;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
quit(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
2002-05-12 09:29:28 +02:00
|
|
|
|
unit *u, *un;
|
2002-05-19 13:08:06 +02:00
|
|
|
|
strlist *S;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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. */
|
|
|
|
|
|
2002-05-12 09:29:28 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u;) {
|
|
|
|
|
un = 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) {
|
2003-06-22 10:38:55 +02:00
|
|
|
|
if (checkpasswd(u->faction, getstrtoken(), false)) {
|
2003-04-24 22:54:14 +02:00
|
|
|
|
#ifdef ENHANCED_QUIT
|
|
|
|
|
int f2_id = getid();
|
|
|
|
|
|
|
|
|
|
if(f2_id > 0) {
|
|
|
|
|
faction *f2 = findfaction(f2_id);
|
|
|
|
|
|
|
|
|
|
f = u->faction;
|
|
|
|
|
|
|
|
|
|
if(f2 == NULL) {
|
|
|
|
|
cmistake(u, S->s, 66, MSG_EVENT);
|
|
|
|
|
} else if(f == f2) {
|
|
|
|
|
cmistake(u, S->s, 8, MSG_EVENT);
|
|
|
|
|
#ifdef ALLIANCES
|
|
|
|
|
} else if(u->faction->alliance != f2->alliance) {
|
|
|
|
|
cmistake(u, S->s, 315, MSG_EVENT);
|
|
|
|
|
#else
|
magicskillboost
-- implementiert. Kann nur einmal pro Partei verwendet werden, und nur von einem Magier. Müssen wir erklären.
Amulett des wahren Sehens und Ring der Unsichtbarkeit geben lediglich einen Bonus auf Wahrnehmung (+2) und Tarnung (+4).
-- das define war nicht aktiviert
Halblinge haben Armbrustschiessen +0 (statt +1).
-- spearates Rassenfile für WDW
Es gibt spezielle Regeln für Allianzen, und der HELFE und KONTAKTIERE Befehl sind eingeschränkt. Konkret kann kein HELP_FIGHT HELP_GUARD HELP_FSTEALTH HELP_MONEY gegeben werden (die anderen sind erlaubt).
-- mit #defeine ALLIES_ONLY definiert
Jede Allianz kann bis zu 15 Magier und 15 Alchemisten haben. Jede einzelne Partei der Allianz kann dabei nicht mehr als 15/Anzahl_Parteien (aufgerundet) Magier bzw. Alchemisten haben, und die Gesamtsumme darf 15 nicht übersteigen.
-- mit #define ALLIANCE_LIMITS gemacht.
Die Startgeschenke (Personen, Silber, ...) werden pro Allianz, nicht pro Spieler verteilt. Größere Allianzen bekommen also weniger pro Spieler.
-- Nochmal geändert: Die Allianzen kriegen jede 168 Personen zum Start, weil sich das gut aufteilen lässt. Das wird auf 28 Einheiten pro Partei gesplittet, jede Einheit hat eines der Talente, außer der Starteinheit, die hat den magicskillboost. Einige Skills kommen öfter vor als andere, das ist nicht einfach vermeidbar. Sollte aber auch wurscht sein, es geht primär darum, lehren zu können.
Es gibt ein Einheitenlimit von 1000 Einheiten pro Allianz.
-- die Regel sparen wir uns einfach mal.
2003-12-14 22:45:47 +01:00
|
|
|
|
#error ENHANCED_QUIT defined without ALLIANCES
|
2003-04-24 22:54:14 +02:00
|
|
|
|
#endif
|
2003-04-27 09:44:05 +02:00
|
|
|
|
} else if(!alliedfaction(NULL, f, f2, HELP_MONEY)) {
|
2003-04-24 22:54:14 +02:00
|
|
|
|
cmistake(u, S->s, 316, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
transfer_faction(f,f2);
|
|
|
|
|
destroyfaction(f);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
destroyfaction(u->faction);
|
|
|
|
|
}
|
|
|
|
|
#else
|
2001-01-25 10:37:55 +01:00
|
|
|
|
destroyfaction(u->faction);
|
2003-04-24 22:54:14 +02:00
|
|
|
|
#endif
|
2002-05-12 09:29:28 +02:00
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, S->s, 86, MSG_EVENT);
|
2004-05-25 23:50:23 +02:00
|
|
|
|
log_warning(("STIRB mit falschem Passwort f<>r Partei %s: %s\n",
|
|
|
|
|
factionid(u->faction), S->s));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2001-04-16 16:34:19 +02:00
|
|
|
|
} else if(igetkeyword(S->s, u->faction->locale) == K_RESTART && u->number > 0) {
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char *s_race, *s_pass;
|
2002-01-31 11:58:24 +01:00
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-22 10:38:55 +02:00
|
|
|
|
if (!checkpasswd(u->faction, s_pass, false)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cmistake(u, S->s, 86, MSG_EVENT);
|
2004-05-25 23:50:23 +02:00
|
|
|
|
log_warning(("NEUSTART mit falschem Passwort f<>r Partei %s: %s\n",
|
|
|
|
|
factionid(u->faction), S->s));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
restart(u, frace);
|
2002-05-12 09:29:28 +02:00
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2002-05-12 09:29:28 +02:00
|
|
|
|
}
|
|
|
|
|
u = un;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
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) {
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if(fval(f, FFL_NOIDLEOUT)) f->lastorders = turn;
|
|
|
|
|
if (NMRTimeout()>0 && turn - f->lastorders >= NMRTimeout()) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
destroyfaction(f);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
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-11-02 15:10:52 +01:00
|
|
|
|
if (f->subscription) fprintf(sqlstream,
|
2002-03-03 13:53:05 +01:00
|
|
|
|
"UPDATE subscriptions SET lastturn=%d, password='%s', info='%s' "
|
2002-11-02 15:10:52 +01:00
|
|
|
|
"WHERE id=%u;\n",
|
|
|
|
|
f->lastorders, f->override, info, f->subscription);
|
2002-03-03 13:53:05 +01:00
|
|
|
|
} else {
|
2002-11-02 15:10:52 +01:00
|
|
|
|
if (f->subscription) fprintf(sqlstream,
|
2002-03-24 13:31:38 +01:00
|
|
|
|
"UPDATE subscriptions SET status='ACTIVE', lastturn=%d, password='%s' "
|
2002-11-02 15:10:52 +01:00
|
|
|
|
"WHERE id=%u;\n",
|
|
|
|
|
f->lastorders, f->override, f->subscription);
|
2002-03-03 13:53:05 +01:00
|
|
|
|
}
|
2002-03-03 11:51:24 +01:00
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (NMRTimeout()>0 && turn - f->lastorders >= (NMRTimeout() - 1)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
inactivefaction(f);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
puts(" - beseitige Spieler, die sich nach der Anmeldung nicht "
|
|
|
|
|
"gemeldet haben...");
|
|
|
|
|
|
2004-01-04 12:28:26 +01:00
|
|
|
|
age = calloc(max(4,turn+1), sizeof(int));
|
2002-09-02 22:36:12 +02:00
|
|
|
|
for (f = factions; f; f = f->next) if (f->no != MONSTER_FACTION) {
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (RemoveNMRNewbie() && !fval(f, FFL_NOIDLEOUT)) {
|
2002-09-02 22:36:12 +02:00
|
|
|
|
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];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#if defined(ALLIANCES) && !defined(ALLIANCEJOIN)
|
|
|
|
|
if (f->alliance==NULL) {
|
2004-01-18 21:17:47 +01:00
|
|
|
|
/* destroyfaction(f); */
|
2002-09-02 22:36:12 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#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;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char *s;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2002-12-18 01:34:19 +01:00
|
|
|
|
case P_TRAVEL:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_TRAVEL);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_TRAVEL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_GIB:
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2003-06-22 10:38:55 +02:00
|
|
|
|
char **s;
|
|
|
|
|
const char *s2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2004-05-14 12:07:36 +02:00
|
|
|
|
if (u->building->type == bt_find("artsculpture") && u->building->display[0] != 0) {
|
|
|
|
|
cmistake(u, S->s, 29, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
s = &u->building->display;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_SHIP:
|
|
|
|
|
if (!u->ship) {
|
|
|
|
|
cmistake(u, S->s, 144, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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
|
|
|
|
{
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char *d = getstrtoken();
|
2001-02-13 20:22:48 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_group(unit * u)
|
|
|
|
|
{
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char * s = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
join_group(u, s);
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_name(region * r, unit * u, strlist * S)
|
|
|
|
|
{
|
2003-06-22 10:38:55 +02:00
|
|
|
|
char **s;
|
|
|
|
|
const char *s2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2004-05-14 12:07:36 +02:00
|
|
|
|
if (u->building->type == bt_find("artsculpure")) {
|
|
|
|
|
cmistake(u, S->s, 29, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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)) {
|
2003-03-08 21:57:38 +01:00
|
|
|
|
cmistake(u, S->s, 63, MSG_EVENT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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
|
2003-03-08 21:57:38 +01:00
|
|
|
|
cmistake(u, S->s, 63, MSG_MESSAGE);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* 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);
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
distributeMail(region * r, unit * u, strlist * S)
|
|
|
|
|
{
|
|
|
|
|
unit *u2;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char *s;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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 {
|
|
|
|
|
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) {
|
2003-03-08 21:57:38 +01:00
|
|
|
|
cmistake(u, S->s, 63, 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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();
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#ifdef MSG_LEVELS
|
|
|
|
|
if (s[0])
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_msglevel(&u->faction->warnings, mc->name, atoi(s));
|
|
|
|
|
else
|
|
|
|
|
set_msglevel(&u->faction->warnings, mc->name, -1);
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
set_passw(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char *s;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static boolean
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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);
|
2003-09-21 09:48:40 +02:00
|
|
|
|
sprintf(filename, "%s/%s/items/%s", resourcepath(), locale_name(default_locale), name);
|
2002-01-01 21:51:18 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static boolean
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static 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;
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-11 00:02:52 +02:00
|
|
|
|
static void
|
|
|
|
|
reshow(unit * u, const char* cmd, const char * s, param_t p)
|
|
|
|
|
{
|
|
|
|
|
int skill, c;
|
|
|
|
|
const potion_type * ptype;
|
|
|
|
|
const item_type * itype;
|
|
|
|
|
const spell * sp;
|
|
|
|
|
const race * rc;
|
|
|
|
|
|
|
|
|
|
switch (p) {
|
|
|
|
|
case P_ZAUBER:
|
|
|
|
|
a_removeall(&u->faction->attribs, &at_seenspell);
|
|
|
|
|
break;
|
|
|
|
|
case P_POTIONS:
|
|
|
|
|
skill = effskill(u, SK_ALCHEMY);
|
|
|
|
|
c = 0;
|
|
|
|
|
for (ptype = potiontypes; ptype!=NULL; ptype=ptype->next) {
|
|
|
|
|
if (ptype->level * 2 <= skill) {
|
|
|
|
|
c += display_potion(u->faction, u, ptype);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (c == 0) cmistake(u, cmd, 285, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
case NOPARAM:
|
|
|
|
|
/* check if it's an item */
|
|
|
|
|
itype = finditemtype(s, u->faction->locale);
|
|
|
|
|
if (itype!=NULL) {
|
|
|
|
|
ptype = resource2potion(item2resource(itype));
|
|
|
|
|
if (ptype!=NULL) {
|
|
|
|
|
if (display_potion(u->faction, u, ptype)) break;
|
|
|
|
|
} else {
|
|
|
|
|
if (display_item(u->faction, u, itype)) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* try for a spell */
|
|
|
|
|
sp = find_spellbyname(u, s, u->faction->locale);
|
|
|
|
|
if (sp!=NULL && has_spell(u, sp)) {
|
|
|
|
|
attrib *a = a_find(u->faction->attribs, &at_seenspell);
|
|
|
|
|
while (a!=NULL && a->data.i!=sp->id) a = a->nexttype;
|
|
|
|
|
if (a!=NULL) a_remove(&u->faction->attribs, a);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* last, check if it's a race. */
|
|
|
|
|
rc = findrace(s, u->faction->locale);
|
|
|
|
|
if (rc != NULL) {
|
|
|
|
|
if (display_race(u->faction, u, rc)) break;
|
|
|
|
|
}
|
|
|
|
|
cmistake(u, cmd, 21, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
cmistake(u, cmd, 222, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
instant_orders(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char *s;
|
|
|
|
|
const char *param;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
spell *spell;
|
|
|
|
|
faction *f;
|
|
|
|
|
attrib *a;
|
|
|
|
|
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) {
|
2003-07-29 11:48:03 +02:00
|
|
|
|
fset(u, UFL_NOAID);
|
2002-02-06 09:06:02 +01:00
|
|
|
|
} else {
|
2003-07-29 11:48:03 +02:00
|
|
|
|
freset(u, UFL_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;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (fval(u, UFL_HUNGER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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();
|
2004-04-11 00:02:52 +02:00
|
|
|
|
if (findparam(s, u->faction->locale) == P_ANY) {
|
2001-04-16 16:34:19 +02:00
|
|
|
|
param_t p = getparam(u->faction->locale);
|
2004-04-11 00:02:52 +02:00
|
|
|
|
reshow(u, S->s, s, p);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2004-04-11 00:02:52 +02:00
|
|
|
|
else reshow(u, S->s, s, NOPARAM);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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) {
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!fval(u, UFL_MOVED)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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)
|
2004-05-31 18:21:03 +02:00
|
|
|
|
destroy_ship(sh);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
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) {
|
2002-11-02 16:50:51 +01:00
|
|
|
|
f = rp->faction;
|
|
|
|
|
a_remove(&f->attribs, rp->attrib);
|
2002-11-02 15:10:52 +01:00
|
|
|
|
if (f->subscription) fprintf(sqlstream, "UPDATE subscriptions set faction='%s' where "
|
2002-11-02 16:52:07 +01:00
|
|
|
|
"id=%u;\n", itoa36(rp->want),
|
2002-11-02 15:10:52 +01:00
|
|
|
|
f->subscription);
|
2002-11-02 16:50:51 +01:00
|
|
|
|
f->no = rp->want;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
register_faction_id(rp->want);
|
2002-11-02 16:50:51 +01:00
|
|
|
|
fset(f, FF_NEWID);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
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);
|
2003-07-29 11:48:03 +02:00
|
|
|
|
} else if (fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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:
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (fval(v, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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 */
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if(!fval(u, UFL_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
|
|
|
|
|
|
2002-12-18 18:40:21 +01:00
|
|
|
|
#ifdef REGIONOWNERS
|
|
|
|
|
static void
|
|
|
|
|
declare_war(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
unit * u;
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
strlist *S;
|
|
|
|
|
faction * f = u->faction;
|
|
|
|
|
for (S = u->orders; S; S = S->next) {
|
|
|
|
|
switch (igetkeyword(S->s, f->locale)) {
|
|
|
|
|
case K_WAR:
|
|
|
|
|
for (;;) {
|
|
|
|
|
const char * s = getstrtoken();
|
|
|
|
|
if (s[0]==0) break;
|
|
|
|
|
else {
|
|
|
|
|
faction * enemy = findfaction(atoi36(s));
|
|
|
|
|
if (enemy) {
|
|
|
|
|
if (!is_enemy(f, enemy)) {
|
|
|
|
|
add_enemy(f, enemy);
|
|
|
|
|
ADDMSG(&enemy->msgs, msg_message("war_notify", "enemy", f));
|
|
|
|
|
ADDMSG(&f->msgs, msg_message("war_confirm", "enemy", enemy));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ADDMSG(&f->msgs, msg_message("error66", "unit region command", u, r, S->s));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case K_PEACE:
|
|
|
|
|
for (;;) {
|
|
|
|
|
const char * s = getstrtoken();
|
|
|
|
|
if (s[0]==0) break;
|
|
|
|
|
else {
|
|
|
|
|
faction * enemy = findfaction(atoi36(s));
|
|
|
|
|
if (enemy) {
|
|
|
|
|
if (is_enemy(f, enemy)) {
|
|
|
|
|
remove_enemy(f, enemy);
|
|
|
|
|
ADDMSG(&enemy->msgs, msg_message("peace_notify", "enemy", f));
|
|
|
|
|
ADDMSG(&f->msgs, msg_message("peace_confirm", "enemy", enemy));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ADDMSG(&f->msgs, msg_message("error66", "unit region command", u, r, S->s));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
renumber(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char *s;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
strlist *S;
|
|
|
|
|
unit * u;
|
|
|
|
|
int i;
|
|
|
|
|
|
2002-12-18 18:40:21 +01:00
|
|
|
|
for (r=regions;r;r=r->next) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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();
|
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;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if(!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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:
|
2004-03-08 19:39:34 +01:00
|
|
|
|
case P_GEBAEUDE:
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if(!u->building) {
|
|
|
|
|
cmistake(u,S->s,145,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if(!fval(u, UFL_OWNER)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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)) {
|
2002-11-02 15:10:52 +01:00
|
|
|
|
u->race = new_race[curse_geteffect(c)];
|
|
|
|
|
u->irace = new_race[curse_geteffect(c)];
|
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;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char * name;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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)
|
|
|
|
|
{
|
2004-05-22 16:41:27 +02:00
|
|
|
|
region *r;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit *u;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
strlist *slist;
|
|
|
|
|
boolean trade = false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
if (LongHunger() && fval(u, UFL_HUNGER)) {
|
|
|
|
|
/* Hungernde Einheiten f<>hren NUR den default-Befehl aus */
|
|
|
|
|
const char * cmd = locale_string(u->faction->locale, "defaultorder");
|
|
|
|
|
set_string(&u->thisorder, cmd);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
/* by default the default long order becomes the new long order. */
|
|
|
|
|
set_string(&u->thisorder, u->lastorder);
|
|
|
|
|
|
|
|
|
|
/* check all orders for a potential new long order this round: */
|
|
|
|
|
for (slist=u->orders; !trade && slist!=NULL; slist=slist->next) {
|
|
|
|
|
const char * cmd = slist->s;
|
|
|
|
|
|
|
|
|
|
keyword_t keyword = igetkeyword(cmd, u->faction->locale);
|
|
|
|
|
switch (keyword) {
|
|
|
|
|
|
|
|
|
|
case K_BUY:
|
|
|
|
|
case K_SELL:
|
|
|
|
|
/* Wenn die Einheit handelt, mu<6D> der Default-Befehl gel<65>scht
|
|
|
|
|
* werden. */
|
|
|
|
|
set_string(&u->thisorder, "");
|
|
|
|
|
trade = true;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_CAST:
|
|
|
|
|
/* dient dazu, das neben Zaubern kein weiterer Befehl
|
|
|
|
|
* ausgef<EFBFBD>hrt werden kann, Zaubern ist ein kurzer Befehl */
|
|
|
|
|
set_string(&u->thisorder, "");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_MAKE:
|
|
|
|
|
/* 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). */
|
|
|
|
|
if (getparam(u->faction->locale) == P_TEMP) break;
|
|
|
|
|
/* else fall through */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if GROWING_TREES
|
2004-05-22 16:41:27 +02:00
|
|
|
|
case K_PFLANZE:
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#endif
|
2004-05-22 16:41:27 +02:00
|
|
|
|
case K_BESIEGE:
|
|
|
|
|
case K_ENTERTAIN:
|
|
|
|
|
case K_TAX:
|
|
|
|
|
case K_RESEARCH:
|
|
|
|
|
case K_SPY:
|
|
|
|
|
case K_STEAL:
|
|
|
|
|
case K_SABOTAGE:
|
|
|
|
|
case K_STUDY:
|
|
|
|
|
case K_TEACH:
|
|
|
|
|
case K_ZUECHTE:
|
|
|
|
|
case K_BIETE:
|
|
|
|
|
case K_PIRACY:
|
|
|
|
|
/* <20>ber dieser Zeile nur Befehle, die auch eine idle Faction machen darf */
|
|
|
|
|
if (idle (u->faction)) {
|
|
|
|
|
set_string (&u->thisorder, locale_string(u->faction->locale, "defaultorder"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* else fall through */
|
|
|
|
|
|
|
|
|
|
case K_ROUTE:
|
|
|
|
|
case K_WORK:
|
|
|
|
|
case K_DRIVE:
|
|
|
|
|
case K_MOVE:
|
|
|
|
|
case K_WEREWOLF:
|
|
|
|
|
set_string(&u->thisorder, cmd);
|
|
|
|
|
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. */
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02: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 */
|
|
|
|
|
switch (igetkeyword (u->thisorder, u->faction->locale)) {
|
|
|
|
|
case K_MOVE:
|
|
|
|
|
case K_BIETE:
|
|
|
|
|
case K_ATTACK:
|
|
|
|
|
case K_WEREWOLF:
|
|
|
|
|
case NOKEYWORD:
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
default:
|
|
|
|
|
set_string(&u->lastorder, u->thisorder);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
/* Attackiere sollte niemals Default werden */
|
|
|
|
|
if (igetkeyword(u->lastorder, u->faction->locale) == K_ATTACK) {
|
|
|
|
|
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
|
|
|
|
{
|
2004-05-22 16:41:27 +02:00
|
|
|
|
int i;
|
|
|
|
|
int target = read_unitid(u->faction, u->region);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
i = new_get_pooled(u, itype->rtype, GET_DEFAULT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
if (amount>i) {
|
|
|
|
|
amount = i;
|
|
|
|
|
}
|
|
|
|
|
if (i==0) {
|
|
|
|
|
cmistake(u, cmd, 43, MSG_PRODUCE);
|
|
|
|
|
return ENOITEM;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 16:41:27 +02: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)
|
|
|
|
|
{
|
2004-06-07 23:43:55 +02:00
|
|
|
|
region *r;
|
|
|
|
|
static const curse_type * heal_ct = NULL;
|
|
|
|
|
if (heal_ct==NULL) heal_ct = ct_find("healingzone");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
int healingcurse = 0;
|
2002-11-03 13:47:29 +01:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
if (heal_ct!=NULL) {
|
|
|
|
|
/* bonus zur<75>cksetzen */
|
|
|
|
|
curse * c = get_curse(r->attribs, heal_ct);
|
|
|
|
|
if (c!=NULL) {
|
|
|
|
|
healingcurse = curse_geteffect(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
int umhp = unit_max_hp(u) * u->number;
|
|
|
|
|
int p;
|
|
|
|
|
|
|
|
|
|
/* hp <20>ber Maximum bauen sich ab. Wird zb durch Elixier der Macht
|
|
|
|
|
* oder ver<EFBFBD>ndertes Ausdauertalent verursacht */
|
|
|
|
|
if (u->hp > umhp) {
|
|
|
|
|
u->hp -= (int) ceil((u->hp - umhp) / 2.0);
|
|
|
|
|
if (u->hp < umhp)
|
|
|
|
|
u->hp = umhp;
|
|
|
|
|
}
|
2002-11-03 13:47:29 +01:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
if((u->race->flags & RCF_NOHEAL) || fval(u, UFL_HUNGER) || fspecial(u->faction, FS_UNDEAD))
|
|
|
|
|
continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
if(rterrain(r) == T_OCEAN && !u->ship && !(canswim(u)))
|
|
|
|
|
continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
if(fspecial(u->faction, FS_REGENERATION)) {
|
|
|
|
|
u->hp = umhp;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
p = canheal(u);
|
|
|
|
|
if (u->hp < umhp && p > 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);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifdef NEW_TAVERN
|
2004-06-07 23:43:55 +02:00
|
|
|
|
struct building * b = inside_building(u);
|
|
|
|
|
const struct building_type * btype = b?b->type:NULL;
|
|
|
|
|
if (btype == bt_find("inn")) {
|
|
|
|
|
max_unit = max_unit * 3 / 2;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#endif
|
2004-06-07 23:43:55 +02:00
|
|
|
|
/* der healing curse ver<65>ndert den Regenerationsprozentsatz.
|
|
|
|
|
* Wenn dies f<EFBFBD>r negative Heilung benutzt wird, kann es zu
|
|
|
|
|
* negativen u->hp f<EFBFBD>hren! */
|
|
|
|
|
if (healingcurse != 0) {
|
|
|
|
|
p += healingcurse;
|
|
|
|
|
}
|
2002-05-24 09:12:50 +02:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
/* Aufaddieren der geheilten HP. */
|
|
|
|
|
u->hp = min(u->hp + max_unit*p/100, umhp);
|
|
|
|
|
if (u->hp < umhp && (rand() % 10 < max_unit % 10)){
|
|
|
|
|
++u->hp;
|
|
|
|
|
}
|
|
|
|
|
/* soll man an negativer regeneration sterben k<>nnen? */
|
|
|
|
|
if (u->hp <= 0){
|
|
|
|
|
u->hp = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
defaultorders (void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char * c;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2004-06-12 10:13:14 +02:00
|
|
|
|
int i = use_item(u, itype, n, S->s);
|
|
|
|
|
assert(i<=0 || !"use_item should not return positive values.");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
2004-06-12 10:13:14 +02:00
|
|
|
|
cmistake(u, S->s, 43, MSG_PRODUCE);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
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...");
|
2003-09-21 12:09:08 +02:00
|
|
|
|
if (!nomonsters) plan_monsters();
|
2002-01-27 11:57:26 +01:00
|
|
|
|
set_passw(); /* und pruefe auf illegale Befehle */
|
|
|
|
|
|
|
|
|
|
puts(" - Defaults und Instant-Befehle...");
|
|
|
|
|
setdefaults();
|
|
|
|
|
instant_orders();
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#ifdef ALLIANCES
|
|
|
|
|
alliancekick();
|
|
|
|
|
#endif
|
2002-01-27 11:57:26 +01:00
|
|
|
|
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)");
|
2002-11-25 20:11:27 +01:00
|
|
|
|
do_misc(false);
|
2001-04-26 19:41:06 +02:00
|
|
|
|
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#ifdef ALLIANCES
|
|
|
|
|
puts(" - Testen der Allianzbedingungen");
|
|
|
|
|
alliancevictory();
|
|
|
|
|
#endif
|
|
|
|
|
|
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)");
|
2002-11-25 20:11:27 +01:00
|
|
|
|
do_misc(false);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-02-22 15:42:24 +01:00
|
|
|
|
puts(" - Folge auf Einheiten ersetzen");
|
|
|
|
|
follow_unit();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (!global.disabled[K_TEACH]) {
|
|
|
|
|
puts(" - Lehren");
|
|
|
|
|
teaching();
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
puts(" - Lernen");
|
|
|
|
|
learn();
|
|
|
|
|
|
|
|
|
|
puts(" - Produzieren, Geldverdienen, Handeln, Anwerben");
|
|
|
|
|
produce();
|
|
|
|
|
|
2002-11-25 20:11:27 +01:00
|
|
|
|
puts(" - Kontaktieren, Betreten von Schiffen und Geb<65>uden (3.Versuch)");
|
|
|
|
|
do_misc(true);
|
|
|
|
|
|
2003-03-15 18:14:02 +01:00
|
|
|
|
puts(" - Schiffe sinken");
|
|
|
|
|
sinkships();
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
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();
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef ALLIANCEJOIN
|
|
|
|
|
alliancejoin();
|
2002-12-18 18:40:21 +01:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef REGIONOWNERS
|
|
|
|
|
puts(" - Krieg & Frieden");
|
|
|
|
|
declare_war();
|
2002-04-21 13:23:58 +02:00
|
|
|
|
#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();
|
|
|
|
|
|
2004-02-21 23:25:00 +01:00
|
|
|
|
#ifdef WORMHOLE_MODULE
|
|
|
|
|
create_wormholes();
|
|
|
|
|
#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)
|
2004-01-11 10:39:16 +01:00
|
|
|
|
log_error(("Anzahl Migranten f<>r (%s) ist falsch: %d statt %d.\n", factionid(f), f->num_migrants, n));
|
2001-02-10 11:40:12 +01:00
|
|
|
|
#endif
|
|
|
|
|
return f->num_migrants;
|
|
|
|
|
}
|
2004-01-11 12:55:48 +01:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
writepasswd(void)
|
|
|
|
|
{
|
|
|
|
|
FILE * F;
|
|
|
|
|
char zText[128];
|
|
|
|
|
|
|
|
|
|
sprintf(zText, "%s/passwd", basepath());
|
|
|
|
|
F = cfopen(zText, "w");
|
|
|
|
|
if (F) {
|
|
|
|
|
faction *f;
|
|
|
|
|
puts("Schreibe Passw<73>rter...");
|
|
|
|
|
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
fprintf(F, "%s:%s:%s:%s:%u\n",
|
|
|
|
|
factionid(f), f->email, f->passw, f->override, f->subscription);
|
|
|
|
|
}
|
|
|
|
|
fclose(F);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|