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 */
|
2004-06-27 18:56:01 +02:00
|
|
|
|
#include <kernel/alchemy.h>
|
|
|
|
|
#include <kernel/alliance.h>
|
|
|
|
|
#include <kernel/battle.h>
|
|
|
|
|
#include <kernel/border.h>
|
|
|
|
|
#include <kernel/building.h>
|
|
|
|
|
#include <kernel/faction.h>
|
|
|
|
|
#include <kernel/group.h>
|
|
|
|
|
#include <kernel/item.h>
|
|
|
|
|
#include <kernel/karma.h>
|
|
|
|
|
#include <kernel/magic.h>
|
|
|
|
|
#include <kernel/message.h>
|
|
|
|
|
#include <kernel/movement.h>
|
|
|
|
|
#include <kernel/order.h>
|
|
|
|
|
#include <kernel/plane.h>
|
|
|
|
|
#include <kernel/pool.h>
|
|
|
|
|
#include <kernel/race.h>
|
|
|
|
|
#include <kernel/region.h>
|
|
|
|
|
#include <kernel/resources.h>
|
|
|
|
|
#include <kernel/save.h>
|
|
|
|
|
#include <kernel/ship.h>
|
|
|
|
|
#include <kernel/skill.h>
|
|
|
|
|
#include <kernel/spy.h>
|
|
|
|
|
#include <kernel/unit.h>
|
2001-04-29 21:27:42 +02:00
|
|
|
|
#ifdef USE_UGROUPS
|
2004-06-27 18:56:01 +02:00
|
|
|
|
# include <kernel/ugroup.h>
|
2001-04-29 21:27:42 +02:00
|
|
|
|
#endif
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/racename.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include <attributes/raceprefix.h>
|
|
|
|
|
#include <attributes/synonym.h>
|
- Neue Messages fertig
Messages werden jetzt in einem anderen Meta-Format (message* of
message_type*) gespeichert, das man in beliebige Formate (CR oder NR)
rendern kann. crmessage.c und nrmessage.c sind die render-engines dafür.
Die Messagetypen werden in res/{de,en}/messages.xml gesammelt, ultimativ
kann das aber durchaus eine einzelne Datei sein. Die ist derzeit nicht
wirklich xml (Umlaute drin, keine Definitionsdatei), aber gut lesbar.
- make_message
Diese Funktion ersetzt new_message, und ist etwas einfacher in der Syntax:
make_message("dumb_mistake", "unit region command", u, r, cmd) erzeugt
eine neue Nachricht, die dann einfach mit add_message wie bisher an die
Nachrichtenliste gehängt werden kann.
TODO: Messages könnte man durchaus reference-counten, und in mehrere Listen
einfügen, solang sie a) mehrfachverwendet (Kampf!) und b) vom Betrachter
unabhängig sind. Das spart einigen Speicher.
- CR Version erhöht.
Weil die MESSAGETYPES Blocks anders sind als früher
- OFFENSIVE_DELAY
Verbietet Einheiten, deren Partei eine Reigon niht bewachen, den
Angriff in der Region, wenn sie sich in der Runde zuvor bewegt haben.
Status der letzten Runde wird in neuem Attribut at_moved gespeichert.
- SHORT_ATTACKS
ein define, das angibt ob Kämpfen grundsätzlich keine lange Aktion ist.
- XML Parser
xml.[hc] enthält einen XML-Parser, dem man ein plugin mit callbacks
übergibt, die nach dem Parsen eines tokens aufgerufen werden.
2001-04-12 19:21:57 +02:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* util includes */
|
|
|
|
|
#include <event.h>
|
|
|
|
|
#include <base36.h>
|
2001-01-30 21:02:06 +01:00
|
|
|
|
#include <goodies.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include <rand.h>
|
2002-03-03 11:51:24 +01:00
|
|
|
|
#include <sql.h>
|
2001-05-20 23:47:56 +02:00
|
|
|
|
#include <util/message.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-04-27 21:40:31 +02:00
|
|
|
|
#include <modules/xecmd.h>
|
|
|
|
|
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef AT_OPTION
|
2001-02-28 19:25:25 +01:00
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/option.h>
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#endif
|
2001-02-28 19:25:25 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* libc includes */
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <assert.h>
|
2001-02-03 14:45:35 +01:00
|
|
|
|
#include <ctype.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-04-14 14:11:45 +02:00
|
|
|
|
#include <attributes/otherfaction.h>
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* - external symbols ------------------------------------------ */
|
|
|
|
|
extern int dropouts[2];
|
|
|
|
|
extern int * age;
|
|
|
|
|
/* - exported global symbols ----------------------------------- */
|
|
|
|
|
boolean nobattle = false;
|
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
|
2004-06-21 18:45:27 +02:00
|
|
|
|
restart_race(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-06-21 18:45:27 +02:00
|
|
|
|
order ** ordp = &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);
|
2004-07-10 19:16:15 +02:00
|
|
|
|
if (f->subscription) {
|
|
|
|
|
sql_print(("UPDATE subscriptions set faction='%s', race='%s' where id=%u;\n",
|
|
|
|
|
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;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
free_orders(&nu->orders);
|
2004-04-10 12:43:46 +02:00
|
|
|
|
nu->orders = u->orders;
|
|
|
|
|
u->orders = NULL;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
while (*ordp) {
|
|
|
|
|
order * ord = *ordp;
|
|
|
|
|
if (get_keyword(ord) == K_RESTART) {
|
|
|
|
|
*ordp = ord->next;
|
|
|
|
|
ord->next = NULL;
|
|
|
|
|
if (u->thisorder == ord) set_order(&u->thisorder, NULL);
|
|
|
|
|
if (u->lastorder == ord) set_order(&u->lastorder, NULL);
|
2004-04-10 12:43:46 +02:00
|
|
|
|
} else {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
ordp = &ord->next;
|
2004-04-10 12:43:46 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
restart(unit * u, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token(); /* skip keyword */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!landregion(rterrain(u->region))) {
|
|
|
|
|
cmistake(u, ord, 242, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
const char * s_race = getstrtoken(), * s_pass;
|
|
|
|
|
const race * frace = findrace(s_race, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!frace) {
|
|
|
|
|
frace = u->faction->race;
|
|
|
|
|
s_pass = s_race;
|
|
|
|
|
} else {
|
|
|
|
|
s_pass = getstrtoken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (frace != u->faction->race && u->faction->age < 81) {
|
|
|
|
|
cmistake(u, ord, 241, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (u->faction->age > 3 && fval(u->faction, FFL_RESTART)) {
|
|
|
|
|
cmistake(u, ord, 314, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!playerrace(frace)) {
|
|
|
|
|
cmistake(u, ord, 243, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!checkpasswd(u->faction, s_pass, false)) {
|
|
|
|
|
cmistake(u, ord, 86, MSG_EVENT);
|
|
|
|
|
log_warning(("NEUSTART mit falschem Passwort f<>r Partei %s: %s\n",
|
|
|
|
|
factionid(u->faction), ord));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
restart_race(u, frace);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-27 18:56:01 +02:00
|
|
|
|
static boolean
|
2004-06-27 20:56:03 +02:00
|
|
|
|
EnhancedQuit(void)
|
2004-06-27 18:56:01 +02:00
|
|
|
|
{
|
|
|
|
|
static int value = -1;
|
|
|
|
|
if (value<0) {
|
|
|
|
|
const char * str = get_param(global.parameters, "alliance.transferquit");
|
|
|
|
|
value = (str!=0 && strcmp(str, "true")==0);
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
quit(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token(); /* skip keyword */
|
2003-04-24 22:54:14 +02:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (checkpasswd(u->faction, getstrtoken(), false)) {
|
2004-06-27 18:56:01 +02:00
|
|
|
|
if (EnhancedQuit()) {
|
|
|
|
|
int f2_id = getid();
|
|
|
|
|
|
|
|
|
|
if (f2_id > 0) {
|
|
|
|
|
faction *f2 = findfaction(f2_id);
|
|
|
|
|
faction * f = u->faction;
|
|
|
|
|
|
|
|
|
|
if(f2 == NULL) {
|
|
|
|
|
cmistake(u, ord, 66, MSG_EVENT);
|
|
|
|
|
} else if(f == f2) {
|
|
|
|
|
cmistake(u, ord, 8, MSG_EVENT);
|
|
|
|
|
} else if (!u->faction->alliance || u->faction->alliance != f2->alliance) {
|
|
|
|
|
cmistake(u, ord, 315, MSG_EVENT);
|
|
|
|
|
} else if(!alliedfaction(NULL, f, f2, HELP_MONEY)) {
|
|
|
|
|
cmistake(u, ord, 316, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
transfer_faction(f,f2);
|
|
|
|
|
destroyfaction(f);
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
} else {
|
2004-06-27 18:56:01 +02:00
|
|
|
|
destroyfaction(u->faction);
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
destroyfaction(u->faction);
|
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, ord, 86, MSG_EVENT);
|
|
|
|
|
log_warning(("STIRB mit falschem Passwort f<>r Partei %s: %s\n",
|
|
|
|
|
factionid(u->faction), ord));
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2002-03-24 12:24:57 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static void
|
|
|
|
|
parse_quit(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
faction *f;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* Sterben erst nachdem man allen anderen gegeben hat - bzw. man kann
|
|
|
|
|
* alles machen, was nicht ein drei<EFBFBD>igt<EFBFBD>giger Befehl ist. */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit * u, * un;
|
|
|
|
|
for (u = r->units; u;) {
|
|
|
|
|
order * ord;
|
|
|
|
|
un = u->next;
|
|
|
|
|
for (ord = u->orders; ord; ord = ord->next) {
|
|
|
|
|
switch (get_keyword(ord)) {
|
|
|
|
|
case K_QUIT:
|
|
|
|
|
if (quit(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_RESTART:
|
|
|
|
|
if (u->number > 0) {
|
|
|
|
|
if (restart(u, ord)!=0) ord = NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (ord==NULL) break;
|
|
|
|
|
}
|
|
|
|
|
u = un;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
puts(" - beseitige Spieler, die sich zu lange nicht mehr gemeldet haben...");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
remove("inactive");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
if(fval(f, FFL_NOIDLEOUT)) f->lastorders = turn;
|
|
|
|
|
if (NMRTimeout()>0 && turn - f->lastorders >= NMRTimeout()) {
|
|
|
|
|
destroyfaction(f);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
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",
|
|
|
|
|
f->no_units, f->number, f->money);
|
2004-07-10 19:16:15 +02:00
|
|
|
|
if (f->subscription) {
|
|
|
|
|
sql_print(("UPDATE subscriptions SET lastturn=%d, password='%s', info='%s' WHERE id=%u;\n",
|
|
|
|
|
f->lastorders, f->override, info, f->subscription));
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
} else {
|
2004-07-10 19:16:15 +02:00
|
|
|
|
if (f->subscription) {
|
|
|
|
|
sql_print(("UPDATE subscriptions SET status='ACTIVE', lastturn=%d, password='%s' WHERE id=%u;\n",
|
|
|
|
|
f->lastorders, f->override, f->subscription));
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
2002-03-03 11:51:24 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (NMRTimeout()>0 && turn - f->lastorders >= (NMRTimeout() - 1)) {
|
|
|
|
|
inactivefaction(f);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
puts(" - beseitige Spieler, die sich nach der Anmeldung nicht "
|
|
|
|
|
"gemeldet haben...");
|
|
|
|
|
|
|
|
|
|
age = calloc(max(4,turn+1), sizeof(int));
|
|
|
|
|
for (f = factions; f; f = f->next) if (f->no != MONSTER_FACTION) {
|
|
|
|
|
if (RemoveNMRNewbie() && !fval(f, FFL_NOIDLEOUT)) {
|
|
|
|
|
if (f->age>=0 && f->age <= turn) ++age[f->age];
|
|
|
|
|
if (f->age == 2 || f->age == 3) {
|
|
|
|
|
if (f->lastorders == turn - 2) {
|
|
|
|
|
destroyfaction(f);
|
|
|
|
|
++dropouts[f->age-2];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-06-27 18:56:01 +02:00
|
|
|
|
#ifndef ALLIANCEJOIN
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (f->alliance==NULL) {
|
|
|
|
|
/* destroyfaction(f); */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#endif
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
/* Clear away debris of destroyed factions */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
puts(" - beseitige leere Einheiten und leere Parteien...");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
remove_empty_units();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* Auskommentiert: Wenn factions gel<65>scht werden, zeigen
|
|
|
|
|
* Spendenpointer ins Leere. */
|
|
|
|
|
/* remove_empty_factions(); */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/* HELFE partei [<ALLES | SILBER | GIB | KAEMPFE | WAHRNEHMUNG>] [NICHT] */
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
ally_cmd(unit * u, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
ally * sf, ** sfp;
|
|
|
|
|
faction *f;
|
|
|
|
|
int keyword, not_kw;
|
|
|
|
|
const char *s;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
f = getfaction();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (f == 0 || f->no == 0) {
|
|
|
|
|
cmistake(u, ord, 66, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (f == u->faction) return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!s[0])
|
|
|
|
|
keyword = P_ANY;
|
|
|
|
|
else
|
|
|
|
|
keyword = findparam(s, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02: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-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
not_kw = getparam(u->faction->locale); /* HELFE partei [modus] NICHT */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!sf) {
|
|
|
|
|
if (keyword == P_NOT || not_kw == P_NOT) {
|
|
|
|
|
/* Wir helfen der Partei gar nicht... */
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
sf = calloc(1, sizeof(ally));
|
|
|
|
|
sf->faction = f;
|
|
|
|
|
sf->status = 0;
|
|
|
|
|
addlist(sfp, sf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
switch (keyword) {
|
|
|
|
|
case P_NOT:
|
|
|
|
|
sf->status = 0;
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case NOPARAM:
|
|
|
|
|
cmistake(u, ord, 137, MSG_EVENT);
|
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_ANY:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = 0;
|
|
|
|
|
else
|
|
|
|
|
sf->status = HELP_ALL;
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02: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;
|
2002-12-18 01:34:19 +01:00
|
|
|
|
|
|
|
|
|
case P_GIB:
|
2004-06-21 18:45:27 +02: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;
|
|
|
|
|
|
|
|
|
|
case P_FACTIONSTEALTH:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_FSTEALTH);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_FSTEALTH;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_GUARD:
|
|
|
|
|
if (not_kw == P_NOT)
|
|
|
|
|
sf->status = sf->status & (HELP_ALL - HELP_GUARD);
|
|
|
|
|
else
|
|
|
|
|
sf->status = sf->status | HELP_GUARD;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (sf->status == 0) { /* Alle HELPs geloescht */
|
|
|
|
|
removelist(sfp, sf);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
display_cmd(unit * u, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
char **s = NULL;
|
|
|
|
|
region * r = u->region;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
switch (getparam(u->faction->locale)) {
|
|
|
|
|
case P_BUILDING:
|
|
|
|
|
case P_GEBAEUDE:
|
|
|
|
|
if (!u->building) {
|
|
|
|
|
cmistake(u, ord, 145, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u, ord, 5, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building->type == bt_find("generic")) {
|
|
|
|
|
cmistake(u, ord, 279, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building->type == bt_find("monument") && u->building->display[0] != 0) {
|
|
|
|
|
cmistake(u, ord, 29, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building->type == bt_find("artsculpture") && u->building->display[0] != 0) {
|
|
|
|
|
cmistake(u, ord, 29, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->building->display;
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_SHIP:
|
|
|
|
|
if (!u->ship) {
|
|
|
|
|
cmistake(u, ord, 144, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u, ord, 12, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->ship->display;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_UNIT:
|
|
|
|
|
s = &u->display;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case P_PRIVAT:
|
|
|
|
|
{
|
|
|
|
|
const char *d = getstrtoken();
|
|
|
|
|
if(d == NULL || *d == 0) {
|
|
|
|
|
usetprivate(u, NULL);
|
|
|
|
|
} else {
|
|
|
|
|
usetprivate(u, d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_REGION:
|
|
|
|
|
if (!u->building) {
|
|
|
|
|
cmistake(u, ord, 145, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u, ord, 148, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building != largestbuilding(r,false)) {
|
|
|
|
|
cmistake(u, ord, 147, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &r->display;
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
default:
|
|
|
|
|
cmistake(u, ord, 110, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!s) return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_string(&(*s), getstrtoken());
|
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
prefix_cmd(unit * u, struct order * ord)
|
2001-12-10 01:13:39 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
attrib **ap;
|
2004-07-09 21:14:10 +02:00
|
|
|
|
attrib *a;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
int i;
|
|
|
|
|
const char *s;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-07-09 21:14:10 +02:00
|
|
|
|
if (!*s) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
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 0;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for(i=0; race_prefixes[i] != NULL; i++) {
|
|
|
|
|
if(strncasecmp(s, LOC(u->faction->locale, race_prefixes[i]), strlen(s)) == 0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(race_prefixes[i] == NULL) {
|
|
|
|
|
cmistake(u, ord, 299, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
ap = &u->faction->attribs;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
a = a_find(u->attribs, &at_group);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (a) ap = &((group*)a->data.v)->attribs;
|
2004-07-09 21:14:10 +02:00
|
|
|
|
set_prefix(ap, race_prefixes[i]);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
return 0;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
synonym_cmd(unit * u, struct order * ord)
|
2001-12-10 01:13:39 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
int i;
|
|
|
|
|
const char *s;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
attrib * a = a_find(u->faction->attribs, &at_synonym);
|
|
|
|
|
if (a!=NULL) { /* Kann nur einmal gesetzt werden */
|
|
|
|
|
cmistake(u, ord, 302, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (s==NULL) {
|
|
|
|
|
cmistake(u, ord, 301, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (race_synonyms[i].race == -1) {
|
|
|
|
|
cmistake(u, ord, 300, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
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 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
name_cmd(unit * u, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
region * r = u->region;
|
2003-06-22 10:38:55 +02:00
|
|
|
|
char **s;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
const char *s2;
|
|
|
|
|
int i;
|
|
|
|
|
param_t p;
|
|
|
|
|
boolean foreign = false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s = 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
p = getparam(u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (p == P_FOREIGN) {
|
|
|
|
|
foreign = true;
|
|
|
|
|
p = getparam(u->faction->locale);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
switch (p) {
|
|
|
|
|
case P_BUILDING:
|
|
|
|
|
case P_GEBAEUDE:
|
|
|
|
|
if (foreign == true) {
|
|
|
|
|
building *b = getbuilding(r);
|
|
|
|
|
unit *uo;
|
|
|
|
|
|
|
|
|
|
if (!b) {
|
|
|
|
|
cmistake(u, ord, 6, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (b->type == bt_find("generic")) {
|
|
|
|
|
cmistake(u, ord, 278, MSG_EVENT);
|
|
|
|
|
break;
|
2004-07-12 23:10:16 +02:00
|
|
|
|
} else {
|
|
|
|
|
const struct locale * lang = locales;
|
|
|
|
|
for (;lang;lang=nextlocale(lang)) {
|
|
|
|
|
const char * bdname = LOC(lang, b->type->_name);
|
|
|
|
|
size_t bdlen = strlen(bdname);
|
|
|
|
|
if (strlen(b->name)>=bdlen && strncmp(b->name, bdname, bdlen)==0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (lang==NULL) {
|
|
|
|
|
cmistake(u, ord, 246, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
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, ord, 145, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u, ord, 148, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building->type == bt_find("generic")) {
|
|
|
|
|
cmistake(u, ord, 278, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sprintf(buf, "Monument %d", u->building->no);
|
|
|
|
|
if (u->building->type == bt_find("monument")
|
|
|
|
|
&& !strcmp(u->building->name, buf)) {
|
|
|
|
|
cmistake(u, ord, 29, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building->type == bt_find("artsculpure")) {
|
|
|
|
|
cmistake(u, ord, 29, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->building->name;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_FACTION:
|
|
|
|
|
if (foreign == true) {
|
|
|
|
|
faction *f;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
f = getfaction();
|
|
|
|
|
if (!f) {
|
|
|
|
|
cmistake(u, ord, 66, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (f->age < 10) {
|
|
|
|
|
cmistake(u, ord, 248, MSG_EVENT);
|
|
|
|
|
break;
|
2004-07-12 23:10:16 +02:00
|
|
|
|
} else {
|
|
|
|
|
const struct locale * lang = locales;
|
|
|
|
|
for (;lang;lang=nextlocale(lang)) {
|
|
|
|
|
const char * fdname = LOC(lang, "factiondefault");
|
|
|
|
|
size_t fdlen = strlen(fdname);
|
|
|
|
|
if (strlen(f->name)>=fdlen && strncmp(f->name, fdname, fdlen)==0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (lang==NULL) {
|
|
|
|
|
cmistake(u, ord, 247, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_SHIP:
|
|
|
|
|
if (foreign == true) {
|
|
|
|
|
ship *sh = getship(r);
|
|
|
|
|
unit *uo;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!sh) {
|
|
|
|
|
cmistake(u, ord, 20, MSG_EVENT);
|
|
|
|
|
break;
|
2004-07-12 23:10:16 +02:00
|
|
|
|
} else {
|
|
|
|
|
const struct locale * lang = locales;
|
|
|
|
|
for (;lang;lang=nextlocale(lang)) {
|
|
|
|
|
const char * sdname = LOC(lang, sh->type->name[0]);
|
|
|
|
|
size_t sdlen = strlen(sdname);
|
|
|
|
|
if (strlen(sh->name)>=sdlen && strncmp(sh->name, sdname, sdlen)==0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sdname = LOC(lang, parameters[P_SHIP]);
|
|
|
|
|
sdlen = strlen(sdname);
|
|
|
|
|
if (strlen(sh->name)>=sdlen && strncmp(sh->name, sdname, sdlen)==0) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (lang==NULL) {
|
|
|
|
|
cmistake(u, ord, 245, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
uo = shipowner(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, ord, 144, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u, ord, 12, MSG_PRODUCE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &u->ship->name;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_UNIT:
|
|
|
|
|
if (foreign == true) {
|
|
|
|
|
unit *u2 = getunit(r, u->faction);
|
2004-07-12 23:10:16 +02:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!u2 || !cansee(u->faction, r, u2, 0)) {
|
|
|
|
|
cmistake(u, ord, 63, MSG_EVENT);
|
|
|
|
|
break;
|
2004-07-12 23:10:16 +02:00
|
|
|
|
} else {
|
|
|
|
|
const char * udefault = LOC(u2->faction->locale, "unitdefault");
|
|
|
|
|
size_t udlen = strlen(udefault);
|
|
|
|
|
size_t unlen = strlen(u2->name);
|
|
|
|
|
if (unlen>=udlen && strncmp(u2->name, udefault, udlen)!=0) {
|
|
|
|
|
cmistake(u2, ord, 244, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_REGION:
|
|
|
|
|
if (!u->building) {
|
|
|
|
|
cmistake(u, ord, 145, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u, ord, 148, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (u->building != largestbuilding(r,false)) {
|
|
|
|
|
cmistake(u, ord, 147, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
s = &r->land->name;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
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, ord, 109, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
cmistake(u, ord, 109, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!s) return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s2 = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!s2[0]) {
|
|
|
|
|
cmistake(u, ord, 84, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; s2[i]; i++)
|
|
|
|
|
if (s2[i] == '(')
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (s2[i]) {
|
|
|
|
|
cmistake(u, ord, 112, MSG_EVENT);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
set_string(&(*s), s2);
|
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
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
|
2004-06-21 18:45:27 +02:00
|
|
|
|
mailunit(region * r, unit * u, int n, struct order * ord, const char * s)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 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
|
2004-06-21 18:45:27 +02:00
|
|
|
|
mailfaction(unit * u, int n, struct order * ord, const char * s)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
|
|
|
|
|
f = findfaction(n);
|
|
|
|
|
if (f && n>0)
|
|
|
|
|
deliverMail(f, u->region, u, s, NULL);
|
|
|
|
|
else
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 66, MSG_MESSAGE);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
mail_cmd(unit * u, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
region * r = u->region;
|
|
|
|
|
unit *u2;
|
|
|
|
|
const char *s;
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token(); /* skip the keyword */
|
|
|
|
|
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, "to") == 0) s = getstrtoken();
|
|
|
|
|
else if (strcasecmp(s, "an") == 0) s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
switch (findparam(s, u->faction->locale)) {
|
|
|
|
|
case P_REGION:
|
|
|
|
|
/* k<>nnen alle Einheiten in der Region sehen */
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, ord, 30, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
sprintf(buf, "von %s: '%s'", unitname(u), s);
|
|
|
|
|
addmessage(r, 0, buf, MSG_MESSAGE, ML_IMPORTANT);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_FACTION:
|
|
|
|
|
{
|
|
|
|
|
boolean see = false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
n = getfactionid();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for(u2=r->units; u2; u2=u2->next) {
|
|
|
|
|
if(u2->faction->no == n && seefaction(u->faction, r, u2, 0)) {
|
|
|
|
|
see = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(see == false) {
|
|
|
|
|
cmistake(u, ord, 66, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, ord, 30, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
mailfaction(u, n, ord, s);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_UNIT:
|
|
|
|
|
{
|
|
|
|
|
boolean see = false;
|
|
|
|
|
n = getid();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for(u2=r->units; u2; u2=u2->next) {
|
|
|
|
|
if(u2->no == n && cansee(u->faction, r, u2, 0)) {
|
|
|
|
|
see = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(see == false) {
|
|
|
|
|
cmistake(u, ord, 63, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, ord, 30, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
mailunit(r, u, n, ord, s);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_BUILDING:
|
|
|
|
|
case P_GEBAEUDE:
|
|
|
|
|
{
|
|
|
|
|
building *b = getbuilding(r);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(!b) {
|
|
|
|
|
cmistake(u, ord, 6, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, ord, 30, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (u2 = r->units; u2; u2 = u2->next) freset(u2->faction, FL_DH);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
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, ord, s);
|
|
|
|
|
fset(u2->faction, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_SHIP:
|
|
|
|
|
{
|
|
|
|
|
ship *sh = getship(r);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(!sh) {
|
|
|
|
|
cmistake(u, ord, 20, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, ord, 30, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (u2 = r->units; u2; u2 = u2->next) freset(u2->faction, FL_DH);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
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, ord, s);
|
|
|
|
|
fset(u2->faction, FL_DH);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
default:
|
|
|
|
|
cmistake(u, ord, 149, MSG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
static void
|
2004-06-21 18:45:27 +02:00
|
|
|
|
report_option(unit * u, const char * sec, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
const messageclass * mc;
|
|
|
|
|
const char *s;
|
|
|
|
|
|
|
|
|
|
mc = mc_find(sec);
|
|
|
|
|
|
|
|
|
|
if (mc == NULL) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 135, MSG_EVENT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
banner_cmd(unit * u, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_string(&u->faction->banner, getstrtoken());
|
|
|
|
|
add_message(&u->faction->msgs, new_message(u->faction,
|
|
|
|
|
"changebanner%s:value", gc_add(strdup(u->faction->banner))));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
email_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
const char * s;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
2001-02-03 14:45:35 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!s[0]) {
|
|
|
|
|
cmistake(u, ord, 85, MSG_EVENT);
|
|
|
|
|
} else if (strstr(s, "internet:") || strchr(s, ' ')) {
|
|
|
|
|
cmistake(u, ord, 117, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
set_string(&u->faction->email, s);
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("changemail", "value",
|
|
|
|
|
gc_add(strdup(u->faction->email))));
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
password_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
char pbuf[32];
|
|
|
|
|
int i;
|
|
|
|
|
const char * s;
|
|
|
|
|
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
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++;
|
|
|
|
|
}
|
|
|
|
|
if (pwok == false) {
|
|
|
|
|
cmistake(u, ord, 283, MSG_EVENT);
|
|
|
|
|
for(i=0; i<6; i++) pbuf[i] = (char)(97 + rand() % 26);
|
|
|
|
|
pbuf[6] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set_string(&u->faction->passw, pbuf);
|
|
|
|
|
fset(u->faction, FFL_OVERRIDE);
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_message("changepasswd",
|
|
|
|
|
"value", gc_add(strdup(u->faction->passw))));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
report_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
const char * s;
|
|
|
|
|
int i;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
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, ord);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
send_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
const char * s;
|
|
|
|
|
int option;
|
|
|
|
|
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
option = findoption(s, u->faction->locale);
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#ifdef AT_OPTION
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* Sonderbehandlung Zeitungsoption */
|
|
|
|
|
if (option == 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);
|
|
|
|
|
u->faction->options = u->faction->options & ~O_NEWS;
|
|
|
|
|
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));
|
|
|
|
|
u->faction->options = u->faction->options | O_NEWS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-02-28 23:14:59 +01:00
|
|
|
|
#endif
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (option == -1) {
|
|
|
|
|
cmistake(u, ord, 135, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
if (getparam(u->faction->locale) == P_NOT) {
|
|
|
|
|
if (option == O_COMPRESS || option == O_BZIP2) {
|
|
|
|
|
cmistake(u, ord, 305, MSG_EVENT);
|
|
|
|
|
} else {
|
|
|
|
|
u->faction->options = u->faction->options & ~((int)pow(2, option));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
u->faction->options = u->faction->options | ((int)pow(2, option));
|
|
|
|
|
if(option == O_COMPRESS) u->faction->options &= ~((int)pow(2, O_BZIP2));
|
|
|
|
|
if(option == O_BZIP2) u->faction->options &= ~((int)pow(2, O_COMPRESS));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static void
|
|
|
|
|
set_passw(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
puts(" - setze Passw<73>rter, Adressen und Format, Abstimmungen");
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
struct order * ord;
|
|
|
|
|
for (ord = u->orders; ord; ord = ord->next) {
|
|
|
|
|
switch (get_keyword(ord)) {
|
|
|
|
|
case NOKEYWORD:
|
|
|
|
|
cmistake(u, ord, 22, MSG_EVENT);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_BANNER:
|
|
|
|
|
if (banner_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_EMAIL:
|
|
|
|
|
if (email_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_PASSWORD:
|
|
|
|
|
if (password_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_REPORT:
|
|
|
|
|
if (report_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_SEND:
|
|
|
|
|
if (send_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
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
|
2004-06-21 18:45:27 +02:00
|
|
|
|
reshow(unit * u, struct order * ord, const char * s, param_t p)
|
2004-04-11 00:02:52 +02:00
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (c == 0) cmistake(u, ord, 285, MSG_EVENT);
|
2004-04-11 00:02:52 +02:00
|
|
|
|
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;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 21, MSG_EVENT);
|
2004-04-11 00:02:52 +02:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 222, MSG_EVENT);
|
2004-04-11 00:02:52 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-03 17:34:26 +02:00
|
|
|
|
#ifdef HEROES
|
|
|
|
|
static int
|
|
|
|
|
promote_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
int money, people;
|
|
|
|
|
|
|
|
|
|
if (maxheroes(u->faction) < countheroes(u->faction)+u->number) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_maxed", "max count",
|
|
|
|
|
maxheroes(u->faction), countheroes(u->faction)));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (!playerrace(u->race)) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_race", "race",
|
|
|
|
|
u->race));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
money = get_all(u, i_silver->rtype);
|
|
|
|
|
people = count_all(u->faction) * u->number;
|
|
|
|
|
|
|
|
|
|
if (people>money) {
|
|
|
|
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "heroes_cost", "cost have",
|
|
|
|
|
people, money));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
use_all(u, i_silver->rtype, people);
|
|
|
|
|
fset(u, UFL_HERO);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
group_cmd(unit * u, struct order * ord)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
const char * s;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
join_group(u, s);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
origin_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
int px, py;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
2002-04-12 14:46:16 +02:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
px = atoi(getstrtoken());
|
|
|
|
|
py = atoi(getstrtoken());
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_ursprung(u->faction, getplaneid(u->region), px, py);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
guard_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
|
|
|
|
|
if (u->faction->age < IMMUN_GEGEN_ANGRIFF) {
|
|
|
|
|
cmistake(u, ord, 304, MSG_EVENT);
|
|
|
|
|
} else if (fval(u, UFL_HUNGER)) {
|
|
|
|
|
cmistake(u, ord, 223, MSG_EVENT);
|
|
|
|
|
} else if (getparam(u->faction->locale) == P_NOT) {
|
|
|
|
|
setguard(u, GUARD_NONE);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
reshow_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
const char * s;
|
|
|
|
|
param_t p = NOPARAM;
|
2001-04-13 16:39:57 +02:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
2001-04-13 16:39:57 +02:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (findparam(s, u->faction->locale) == P_ANY) {
|
|
|
|
|
p = getparam(u->faction->locale);
|
|
|
|
|
s = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reshow(u, ord, s, p);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2002-02-06 09:06:02 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
status_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
const char * param;
|
|
|
|
|
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
|
|
|
|
|
param = getstrtoken();
|
|
|
|
|
switch (findparam(param, u->faction->locale)) {
|
|
|
|
|
case P_NOT:
|
|
|
|
|
u->status = ST_AVOID;
|
|
|
|
|
break;
|
|
|
|
|
case P_BEHIND:
|
|
|
|
|
u->status = ST_BEHIND;
|
|
|
|
|
break;
|
|
|
|
|
case P_FLEE:
|
|
|
|
|
u->status = ST_FLEE;
|
|
|
|
|
break;
|
|
|
|
|
case P_CHICKEN:
|
|
|
|
|
u->status = ST_CHICKEN;
|
|
|
|
|
break;
|
|
|
|
|
case P_AGGRO:
|
|
|
|
|
u->status = ST_AGGRO;
|
|
|
|
|
break;
|
|
|
|
|
case P_VORNE:
|
|
|
|
|
u->status = ST_FIGHT;
|
|
|
|
|
break;
|
|
|
|
|
case P_HELP:
|
|
|
|
|
if (getparam(u->faction->locale) == P_NOT) {
|
|
|
|
|
fset(u, UFL_NOAID);
|
|
|
|
|
} else {
|
|
|
|
|
freset(u, UFL_NOAID);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (strlen(param)) {
|
|
|
|
|
add_message(&u->faction->msgs,
|
|
|
|
|
msg_feedback(u, ord, "unknown_status", ""));
|
|
|
|
|
} else {
|
|
|
|
|
u->status = ST_FIGHT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
combatspell_cmd(unit * u, struct order * ord)
|
|
|
|
|
{
|
|
|
|
|
const char * s;
|
|
|
|
|
int level = 0;
|
|
|
|
|
spell * spell;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* KAMPFZAUBER [NICHT] l<>scht alle gesetzten Kampfzauber */
|
|
|
|
|
if (!s || *s == 0 || findparam(s, u->faction->locale) == P_NOT) {
|
|
|
|
|
unset_combatspell(u, 0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* Optional: STUFE n */
|
|
|
|
|
if (findparam(s, u->faction->locale) == P_LEVEL) {
|
|
|
|
|
/* Merken, setzen kommt erst sp<73>ter */
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
level = atoi(s);
|
|
|
|
|
level = max(0, level);
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
spell = find_spellbyname(u, s, u->faction->locale);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(!spell){
|
|
|
|
|
cmistake(u, ord, 173, MSG_MAGIC);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
s = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (findparam(s, u->faction->locale) == P_NOT) {
|
|
|
|
|
/* KAMPFZAUBER "<Spruchname>" NICHT l<>scht diesen speziellen
|
|
|
|
|
* Kampfzauber */
|
|
|
|
|
unset_combatspell(u, spell);
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
/* KAMPFZAUBER "<Spruchname>" setzt diesen Kampfzauber */
|
|
|
|
|
set_combatspell(u, spell, ord, level);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static void
|
|
|
|
|
instant_orders(void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
faction *f;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
puts(" - Kontakte, Hilfe, Status, Kampfzauber, Texte, Bewachen (aus), Zeigen");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
attrib *a;
|
|
|
|
|
#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
|
|
|
|
|
a = a_find(f->attribs, &at_show_item_description);
|
|
|
|
|
while (a!=NULL) {
|
|
|
|
|
display_item(f, NULL, (item_t)(a->data.i));
|
|
|
|
|
a_remove(&f->attribs, a);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
parse(K_GROUP, group_cmd, false);
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
unit * u;
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
order * ord;
|
|
|
|
|
for (ord = u->orders; ord; ord = ord->next) {
|
|
|
|
|
switch (get_keyword(ord)) {
|
|
|
|
|
case K_URSPRUNG:
|
|
|
|
|
if (origin_cmd(u, ord)!=0) ord=NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_ALLY:
|
|
|
|
|
if (ally_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_PREFIX:
|
|
|
|
|
if (prefix_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_SYNONYM:
|
|
|
|
|
if (synonym_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_SETSTEALTH:
|
|
|
|
|
if (setstealth_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_WEREWOLF:
|
|
|
|
|
if (setwere_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_STATUS:
|
|
|
|
|
/* KAEMPFE [ NICHT | AGGRESSIV | DEFENSIV | HINTEN | FLIEHE ] */
|
|
|
|
|
if (status_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_COMBAT:
|
|
|
|
|
/* KAMPFZAUBER [[STUFE n] "<Spruchname>"] [NICHT] */
|
|
|
|
|
if (combatspell_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_DISPLAY:
|
|
|
|
|
if (display_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_NAME:
|
|
|
|
|
if (name_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_GUARD:
|
|
|
|
|
if (guard_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case K_RESHOW:
|
|
|
|
|
if (reshow_cmd(u, ord)!=0) ord = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
/* 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)
|
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
region *r;
|
|
|
|
|
unit *u;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* letzte schnellen befehle - bewache */
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
if (!fval(u, UFL_MOVED)) {
|
|
|
|
|
struct order * ord;
|
|
|
|
|
for (ord = u->orders; ord; ord = ord->next) {
|
|
|
|
|
if (get_keyword(ord) == K_GUARD) {
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
if (getparam(u->faction->locale) == P_NOT) continue;
|
|
|
|
|
if (rterrain(r) != T_OCEAN) {
|
|
|
|
|
if (!fval(u, RCF_ILLUSIONARY) && u->race != new_race[RC_SPELL]) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifdef WACH_WAFF
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* Monster der Monsterpartei d<>rfen immer bewachen */
|
|
|
|
|
if (u->faction == findfaction(MONSTER_FACTION)){
|
|
|
|
|
guard(u, GUARD_ALL);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-03-01 20:32:25 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (!armedmen(u)) {
|
|
|
|
|
ADDMSG(&u->faction->msgs,
|
|
|
|
|
msg_feedback(u, ord, "unit_unarmed", ""));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#endif
|
2004-06-21 18:45:27 +02:00
|
|
|
|
guard(u, GUARD_ALL);
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, ord, 95, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, ord, 2, MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
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) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (rterrain(r) == T_OCEAN && (!enoughsailors(sh, r) || get_captain(sh)==NULL)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Schiff nicht seet<65>chtig */
|
|
|
|
|
damage_ship(sh, 0.30);
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (shipowner(sh)==NULL) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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);
|
2004-07-10 19:16:15 +02:00
|
|
|
|
if (f->subscription) {
|
|
|
|
|
sql_print(("UPDATE subscriptions set faction='%s' where id=%u;\n",
|
|
|
|
|
itoa36(rp->want), 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) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
unit ** up=&r->units;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
boolean sorted=false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
while (*up) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
unit * u = *up;
|
2001-02-03 14:45:35 +01:00
|
|
|
|
if (!fval(u, FL_MARK)) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
struct order * ord;
|
|
|
|
|
for (ord = u->orders;ord;ord=ord->next) {
|
|
|
|
|
if (get_keyword(ord)==K_SORT) {
|
|
|
|
|
const char * s;
|
|
|
|
|
param_t p;
|
|
|
|
|
int id;
|
|
|
|
|
unit *v;
|
|
|
|
|
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
p = findparam(s, u->faction->locale);
|
|
|
|
|
id = getid();
|
|
|
|
|
v = findunit(id);
|
|
|
|
|
|
|
|
|
|
if (v==NULL || v->faction!=u->faction || v->region!=r) {
|
|
|
|
|
cmistake(u, ord, 258, MSG_EVENT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else if (v->building != u->building || v->ship!=u->ship) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 259, MSG_EVENT);
|
2003-07-29 11:48:03 +02:00
|
|
|
|
} else if (fval(u, UFL_OWNER)) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 260, MSG_EVENT);
|
2001-02-03 14:45:35 +01:00
|
|
|
|
} else if (v == u) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 10, MSG_EVENT);
|
2001-02-03 14:45:35 +01:00
|
|
|
|
} 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)) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(v, ord, 261, MSG_EVENT);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
unit ** vp=&r->units;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (sorted) {
|
|
|
|
|
unit * u;
|
|
|
|
|
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) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (S = u->orders; S; S = S->next) if (get_keyword(ord)==K_EVICT) {
|
|
|
|
|
int id;
|
|
|
|
|
unit *u2;
|
2002-04-21 13:23:58 +02:00
|
|
|
|
/* 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 */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u,ord,49,MSG_EVENT);
|
2002-04-21 13:23:58 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
id = getid();
|
|
|
|
|
u2 = findunit(id);
|
|
|
|
|
|
|
|
|
|
if (u2==NULL) {
|
2002-04-28 14:47:29 +02:00
|
|
|
|
/* Einheit nicht gefunden */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u,ord,63,MSG_EVENT);
|
2002-04-28 14:47:29 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (u->building){
|
|
|
|
|
/* in der selben Burg? */
|
|
|
|
|
if (u->building != u2->building){
|
|
|
|
|
/* nicht in Burg */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u,ord,33,MSG_EVENT);
|
2002-04-28 14:47:29 +02:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
leave_building(u2);
|
|
|
|
|
/* meldung an beide */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (u->ship){
|
|
|
|
|
if (u->ship != u2->ship){
|
|
|
|
|
/* nicht an Bord */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 32, MSG_EVENT);
|
2002-04-28 14:47:29 +02:00
|
|
|
|
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) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
switch (get_keyword(ord)) {
|
2002-12-18 18:40:21 +01:00
|
|
|
|
case K_WAR:
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
2002-12-18 18:40:21 +01:00
|
|
|
|
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 {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
ADDMSG(&f->msgs, msg_message("error66", "unit region command", u, r, ord));
|
2002-12-18 18:40:21 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case K_PEACE:
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
2002-12-18 18:40:21 +01:00
|
|
|
|
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 {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
ADDMSG(&f->msgs, msg_message("error66", "unit region command", u, r, ord));
|
2002-12-18 18:40:21 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
renumber(void)
|
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
region *r;
|
|
|
|
|
const char *s;
|
|
|
|
|
unit * u;
|
|
|
|
|
int i;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-12-18 18:40:21 +01:00
|
|
|
|
for (r=regions;r;r=r->next) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
faction * f = u->faction;
|
|
|
|
|
struct order * ord;
|
|
|
|
|
for (ord = u->orders; ord; ord = ord->next) if (get_keyword(ord)==K_NUMBER) {
|
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
switch(findparam(s, u->faction->locale)) {
|
|
|
|
|
|
|
|
|
|
case P_FACTION:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if (s && *s) {
|
|
|
|
|
int id = atoi36(s);
|
|
|
|
|
attrib * a = a_find(f->attribs, &at_number);
|
|
|
|
|
if (!a) a = a_add(&f->attribs, a_new(&at_number));
|
|
|
|
|
a->data.i = id;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_UNIT:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if(s == NULL || *s == 0) {
|
|
|
|
|
i = newunitid();
|
|
|
|
|
} else {
|
|
|
|
|
i = atoi36(s);
|
|
|
|
|
if (i<=0 || i>MAX_UNIT_NR) {
|
|
|
|
|
cmistake(u, ord, 114, MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(forbiddenid(i)) {
|
|
|
|
|
cmistake(u, ord, 116, MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if(findunitg(i, r)) {
|
|
|
|
|
cmistake(u, ord, 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;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_SHIP:
|
|
|
|
|
if(!u->ship) {
|
|
|
|
|
cmistake(u,ord,144,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u,ord,146,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if(s == NULL || *s == 0) {
|
|
|
|
|
i = newcontainerid();
|
|
|
|
|
} else {
|
|
|
|
|
i = atoi36(s);
|
|
|
|
|
if (i<=0 || i>MAX_CONTAINER_NR) {
|
|
|
|
|
cmistake(u,ord,114,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (findship(i) || findbuilding(i)) {
|
|
|
|
|
cmistake(u,ord,115,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sunhash(u->ship);
|
|
|
|
|
u->ship->no = i;
|
|
|
|
|
shash(u->ship);
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_BUILDING:
|
|
|
|
|
case P_GEBAEUDE:
|
|
|
|
|
if(!u->building) {
|
|
|
|
|
cmistake(u,ord,145,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(!fval(u, UFL_OWNER)) {
|
|
|
|
|
cmistake(u,ord,148,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
if(*s == 0) {
|
|
|
|
|
i = newcontainerid();
|
|
|
|
|
} else {
|
|
|
|
|
i = atoi36(s);
|
|
|
|
|
if (i<=0 || i>MAX_CONTAINER_NR) {
|
|
|
|
|
cmistake(u,ord,114,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if(findship(i) || findbuilding(i)) {
|
|
|
|
|
cmistake(u,ord,115,MSG_EVENT);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
bunhash(u->building);
|
|
|
|
|
u->building->no = i;
|
|
|
|
|
bhash(u->building);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
cmistake(u,ord,239,MSG_EVENT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
renumber_factions();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
region *r;
|
|
|
|
|
unit *u, *u2;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* neue einheiten werden gemacht und ihre befehle (bis zum "ende" zu
|
2004-06-27 14:19:58 +02:00
|
|
|
|
* ihnen rueberkopiert, damit diese einheiten genauso wie die alten
|
|
|
|
|
* einheiten verwendet werden koennen. */
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (r = regions; r; r = r->next) {
|
2004-06-27 14:19:58 +02:00
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
order ** ordp = &u->orders;
|
|
|
|
|
while (*ordp) {
|
|
|
|
|
order * makeord = *ordp;
|
|
|
|
|
if (get_keyword(makeord) == K_MAKE) {
|
|
|
|
|
init_tokens(makeord);
|
|
|
|
|
skip_token();
|
|
|
|
|
if (getparam(u->faction->locale) == P_TEMP) {
|
|
|
|
|
char * name;
|
|
|
|
|
int g, alias;
|
|
|
|
|
int mu = maxunits(u->faction);
|
|
|
|
|
order ** newordersp;
|
|
|
|
|
|
|
|
|
|
if(u->faction->no_units >= mu) {
|
|
|
|
|
sprintf(buf, "Eine Partei darf aus nicht mehr als %d "
|
|
|
|
|
"Einheiten bestehen.", mu);
|
|
|
|
|
mistake(u, makeord, buf, MSG_PRODUCE);
|
|
|
|
|
ordp = &makeord->next;
|
|
|
|
|
|
|
|
|
|
while (*ordp) {
|
|
|
|
|
order * ord = *ordp;
|
|
|
|
|
if (get_keyword(ord) == K_END) break;
|
|
|
|
|
*ordp = ord->next;
|
|
|
|
|
ord->next = NULL;
|
|
|
|
|
free_order(ord);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
alias = getid();
|
|
|
|
|
|
|
|
|
|
name = strdup(getstrtoken());
|
|
|
|
|
if (name && strlen(name)==0) name = NULL;
|
|
|
|
|
u2 = create_unit(r, u->faction, 0, u->faction->race, alias, name, u);
|
|
|
|
|
if (name!=NULL) free(name);
|
|
|
|
|
fset(u2, UFL_ISNEW);
|
|
|
|
|
|
|
|
|
|
a_add(&u2->attribs, a_new(&at_alias))->data.i = alias;
|
|
|
|
|
|
|
|
|
|
g = getguard(u);
|
|
|
|
|
if (g) setguard(u2, g);
|
|
|
|
|
else setguard(u, GUARD_NONE);
|
|
|
|
|
|
|
|
|
|
ordp = &makeord->next;
|
|
|
|
|
newordersp = &u2->orders;
|
|
|
|
|
while (*ordp) {
|
|
|
|
|
order * ord = *ordp;
|
|
|
|
|
if (get_keyword(ord) == K_END) break;
|
|
|
|
|
*ordp = ord->next;
|
|
|
|
|
ord->next = NULL;
|
|
|
|
|
*newordersp = ord;
|
|
|
|
|
newordersp = &ord->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (*ordp==makeord) ordp=&makeord->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
order *ord;
|
2004-05-22 16:41:27 +02:00
|
|
|
|
boolean trade = false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-08-03 17:34:26 +02:00
|
|
|
|
if (LongHunger(u)) {
|
2004-05-22 16:41:27 +02:00
|
|
|
|
/* Hungernde Einheiten f<>hren NUR den default-Befehl aus */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_order(&u->thisorder, default_order(u->faction->locale));
|
2004-05-22 16:41:27 +02:00
|
|
|
|
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. */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
u->thisorder = copy_order(u->lastorder);
|
|
|
|
|
|
2004-05-22 16:41:27 +02:00
|
|
|
|
/* check all orders for a potential new long order this round: */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
for (ord = u->orders; ord; ord = ord->next) {
|
|
|
|
|
keyword_t keyword = get_keyword(ord);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
|
|
|
|
|
switch (keyword) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* Wenn gehandelt wird, darf kein langer Befehl ausgef<65>hrt
|
|
|
|
|
* werden. Da Handel erst nach anderen langen Befehlen kommt,
|
|
|
|
|
* mu<EFBFBD> das vorher abgefangen werden. Wir merken uns also
|
|
|
|
|
* hier, ob die Einheit handelt. */
|
2004-05-22 16:41:27 +02:00
|
|
|
|
case K_BUY:
|
|
|
|
|
case K_SELL:
|
|
|
|
|
/* Wenn die Einheit handelt, mu<6D> der Default-Befehl gel<65>scht
|
2004-06-21 18:45:27 +02:00
|
|
|
|
* werden. */
|
2004-05-22 16:41:27 +02:00
|
|
|
|
trade = true;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case K_CAST:
|
|
|
|
|
/* dient dazu, das neben Zaubern kein weiterer Befehl
|
2004-06-21 18:45:27 +02:00
|
|
|
|
* ausgef<EFBFBD>hrt werden kann, Zaubern ist ein kurzer Befehl */
|
|
|
|
|
set_order(&u->thisorder, NULL);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
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). */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord); /* initialize token-parser */
|
|
|
|
|
skip_token();
|
2004-05-22 16:41:27 +02:00
|
|
|
|
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)) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_order(&u->thisorder, default_order(u->faction->locale));
|
2004-05-22 16:41:27 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* else fall through */
|
|
|
|
|
|
|
|
|
|
case K_ROUTE:
|
|
|
|
|
case K_WORK:
|
|
|
|
|
case K_DRIVE:
|
|
|
|
|
case K_MOVE:
|
|
|
|
|
case K_WEREWOLF:
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_order(&u->thisorder, ord);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Wird je diese Ausschliesslichkeit aufgehoben, muss man aufpassen
|
|
|
|
|
* mit der Reihenfolge von Kaufen, Verkaufen etc., damit es Spielern
|
|
|
|
|
* nicht moeglich ist, Schulden zu machen. */
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
/* Wenn die Einheit handelt, mu<6D> der Default-Befehl gel<65>scht
|
|
|
|
|
* werden. */
|
|
|
|
|
|
|
|
|
|
if (trade == true) {
|
|
|
|
|
/* fset(u, UFL_LONGACTION); */
|
|
|
|
|
set_order(&u->thisorder, NULL);
|
|
|
|
|
}
|
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 */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
|
|
|
|
|
switch (get_keyword(u->thisorder)) {
|
2004-05-22 16:41:27 +02:00
|
|
|
|
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:
|
2004-06-21 18:45:27 +02:00
|
|
|
|
set_order(&u->lastorder, u->thisorder);
|
|
|
|
|
/* Attackiere sollte niemals Default werden */
|
|
|
|
|
if (get_keyword(u->lastorder) == K_ATTACK) {
|
|
|
|
|
set_order(&u->lastorder, default_order(u->faction->locale));
|
|
|
|
|
}
|
2004-05-22 16:41:27 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2004-06-21 18:45:27 +02:00
|
|
|
|
use_item(unit * u, const item_type * itype, int amount, struct order * ord)
|
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;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (amount==0) {
|
|
|
|
|
cmistake(u, ord, 43, MSG_PRODUCE);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
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) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 76, MSG_PRODUCE);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
return EUNUSABLE;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
return itype->use(u, itype, amount, ord);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
} else {
|
|
|
|
|
if (itype->useonother==NULL) {
|
2004-06-21 18:45:27 +02:00
|
|
|
|
cmistake(u, ord, 76, MSG_PRODUCE);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
return EUNUSABLE;
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
return itype->useonother(u, target, itype, amount, ord);
|
2004-05-22 16:41:27 +02:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-08-03 17:34:26 +02:00
|
|
|
|
static double
|
|
|
|
|
heal_factor(const race *rc)
|
|
|
|
|
{
|
|
|
|
|
switch(old_race(rc)) {
|
|
|
|
|
case RC_TROLL:
|
|
|
|
|
case RC_DAEMON:
|
|
|
|
|
return 1.5;
|
|
|
|
|
case RC_GOBLIN:
|
|
|
|
|
return 2.0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2004-08-03 17:34:26 +02:00
|
|
|
|
return 1.0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2004-08-03 17:34:26 +02:00
|
|
|
|
double p = 1.0;
|
2004-06-07 23:43:55 +02:00
|
|
|
|
|
|
|
|
|
/* 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);
|
2004-08-03 17:34:26 +02:00
|
|
|
|
if (u->hp < umhp) u->hp = umhp;
|
|
|
|
|
continue;
|
2004-06-07 23:43:55 +02:00
|
|
|
|
}
|
2002-11-03 13:47:29 +01:00
|
|
|
|
|
2004-08-03 17:34:26 +02:00
|
|
|
|
if (u->race->flags & RCF_NOHEAL) continue;
|
|
|
|
|
if (fval(u, UFL_HUNGER)) continue;
|
|
|
|
|
if (fspecial(u->faction, FS_UNDEAD)) continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-08-03 17:34:26 +02:00
|
|
|
|
if (rterrain(r)==T_OCEAN && u->ship==NULL && !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-08-03 17:34:26 +02:00
|
|
|
|
p *= heal_factor(u->race);
|
|
|
|
|
if (u->hp < umhp) {
|
|
|
|
|
#ifdef NEW_DAEMONHUNGER_RULE
|
|
|
|
|
double maxheal = max(u->number, umhp/20.0);
|
|
|
|
|
#else
|
|
|
|
|
double maxheal = max(u->number, umhp/10.0);
|
|
|
|
|
#endif
|
|
|
|
|
int addhp;
|
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")) {
|
2004-08-03 17:34:26 +02:00
|
|
|
|
p *= 1.5;
|
2004-06-07 23:43:55 +02:00
|
|
|
|
}
|
2004-08-03 17:34:26 +02:00
|
|
|
|
/* pro punkt 5% h<>her */
|
|
|
|
|
p *= (1.0 + healingcurse * 0.05);
|
|
|
|
|
|
|
|
|
|
maxheal = p * maxheal;
|
|
|
|
|
addhp = (int)maxheal;
|
|
|
|
|
maxheal -= addhp;
|
|
|
|
|
if (maxheal>0.0 && chance(maxheal)) ++addhp;
|
2002-05-24 09:12:50 +02:00
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
/* Aufaddieren der geheilten HP. */
|
2004-08-03 17:34:26 +02:00
|
|
|
|
u->hp = min(u->hp + addhp, umhp);
|
|
|
|
|
|
2004-06-07 23:43:55 +02:00
|
|
|
|
/* soll man an negativer regeneration sterben k<>nnen? */
|
2004-08-03 17:34:26 +02:00
|
|
|
|
assert(u->hp > 0);
|
2004-06-07 23:43:55 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
defaultorders (void)
|
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
region *r;
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
unit *u;
|
|
|
|
|
for (u=r->units;u;u=u->next) {
|
|
|
|
|
order ** ordp = &u->orders;
|
|
|
|
|
while (*ordp!=NULL) {
|
|
|
|
|
order * ord = *ordp;
|
|
|
|
|
if (get_keyword(ord)==K_DEFAULT) {
|
2004-06-27 18:56:01 +02:00
|
|
|
|
char * cmd;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token(); /* skip the keyword */
|
2004-06-27 18:56:01 +02:00
|
|
|
|
cmd = strdup(getstrtoken());
|
|
|
|
|
set_order(&u->lastorder, parse_order(cmd, u->faction->locale));
|
|
|
|
|
free(cmd);
|
2004-06-21 18:45:27 +02:00
|
|
|
|
free_order(u->lastorder); /* parse_order & set_order have both increased the refcount */
|
|
|
|
|
*ordp = ord->next;
|
2004-06-27 14:19:58 +02:00
|
|
|
|
ord->next = NULL;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
free_order(ord);
|
|
|
|
|
}
|
|
|
|
|
else ordp = &ord->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static int
|
|
|
|
|
use_cmd(unit * u, struct order * ord)
|
2002-01-27 11:57:26 +01:00
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
const char * t;
|
|
|
|
|
int n;
|
|
|
|
|
const item_type * itype;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
init_tokens(ord);
|
|
|
|
|
skip_token();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
t = getstrtoken();
|
|
|
|
|
n = atoi(t);
|
|
|
|
|
if (n==0) {
|
|
|
|
|
n = 1;
|
|
|
|
|
} else {
|
|
|
|
|
t = getstrtoken();
|
|
|
|
|
}
|
|
|
|
|
itype = finditemtype(t, u->faction->locale);
|
|
|
|
|
|
|
|
|
|
if (itype!=NULL) {
|
|
|
|
|
int i = use_item(u, itype, n, ord);
|
|
|
|
|
assert(i<=0 || !"use_item should not return positive values.");
|
|
|
|
|
} else {
|
|
|
|
|
cmistake(u, ord, 43, MSG_PRODUCE);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2002-01-27 11:57:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
processorders (void)
|
|
|
|
|
{
|
|
|
|
|
region *r;
|
|
|
|
|
|
2004-06-23 00:00:36 +02:00
|
|
|
|
set_passw(); /* und pruefe auf illegale Befehle */
|
2002-01-27 11:57:26 +01:00
|
|
|
|
|
2004-06-23 00:00:36 +02:00
|
|
|
|
puts(" - neue Einheiten erschaffen...");
|
2002-01-27 11:57:26 +01:00
|
|
|
|
new_units();
|
|
|
|
|
|
|
|
|
|
puts(" - Defaults und Instant-Befehle...");
|
|
|
|
|
setdefaults();
|
|
|
|
|
instant_orders();
|
2004-06-27 18:56:01 +02:00
|
|
|
|
|
|
|
|
|
if (alliances!=NULL) alliancekick();
|
|
|
|
|
|
|
|
|
|
parse(K_MAIL, mail_cmd, false);
|
2002-01-27 11:57:26 +01:00
|
|
|
|
puts(" - Altern");
|
|
|
|
|
age_factions();
|
|
|
|
|
|
|
|
|
|
puts(" - Benutzen");
|
2004-06-21 18:45:27 +02:00
|
|
|
|
parse(K_USE, use_cmd, false);
|
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
|
|
|
|
|
2004-06-27 18:56:01 +02:00
|
|
|
|
if (alliances!=NULL) {
|
|
|
|
|
puts(" - Testen der Allianzbedingungen");
|
|
|
|
|
alliancevictory();
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
|
2001-04-26 19:41:06 +02:00
|
|
|
|
puts(" - GM Kommandos");
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#ifdef INFOCMD_MODULE
|
2001-04-26 19:41:06 +02:00
|
|
|
|
infocommands();
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#endif
|
2001-04-26 19:41:06 +02:00
|
|
|
|
gmcommands();
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
puts(" - Verlassen");
|
2004-06-21 18:45:27 +02:00
|
|
|
|
parse(K_LEAVE, leave_cmd, false);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
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");
|
2004-06-21 18:45:27 +02:00
|
|
|
|
parse_quit();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
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");
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#ifdef XECMD_MODULE
|
2002-04-27 21:40:31 +02:00
|
|
|
|
xecmd();
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#endif
|
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");
|
2004-06-21 18:45:27 +02:00
|
|
|
|
karma();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
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
|
2004-08-03 17:34:26 +02:00
|
|
|
|
|
|
|
|
|
#ifdef HEROES
|
|
|
|
|
puts(" - Heldenbef<65>rderung");
|
|
|
|
|
parse(K_PROMOTION, promote_cmd, false);
|
|
|
|
|
#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
|
|
|
|
|
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;
|
|
|
|
|
}
|