2001-01-25 10:37:55 +01:00
|
|
|
|
/* vi: set ts=2:
|
|
|
|
|
*
|
2003-07-29 11:48:03 +02:00
|
|
|
|
* Eressea PB(E)M host Copyright (C) 1998-2003
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* Christian Schlittchen (corwin@amber.kn-bremen.de)
|
|
|
|
|
* Katja Zedel (katze@felidae.kn-bremen.de)
|
|
|
|
|
* Henning Peters (faroul@beyond.kn-bremen.de)
|
|
|
|
|
* Enno Rehling (enno@eressea-pbem.de)
|
|
|
|
|
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
|
|
|
*
|
|
|
|
|
* based on:
|
|
|
|
|
*
|
|
|
|
|
* Atlantis v1.0 13 September 1993 Copyright 1993 by Russell Wallace
|
|
|
|
|
* Atlantis v1.7 Copyright 1996 by Alex Schr<EFBFBD>der
|
|
|
|
|
*
|
|
|
|
|
* This program may not be used, modified or distributed without
|
|
|
|
|
* prior permission by the authors of Eressea.
|
|
|
|
|
* This program may not be sold or used commercially without prior written
|
|
|
|
|
* permission from the authors.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include "eressea.h"
|
|
|
|
|
#include "save.h"
|
|
|
|
|
|
|
|
|
|
#include "faction.h"
|
|
|
|
|
#include "magic.h"
|
|
|
|
|
#include "item.h"
|
|
|
|
|
#include "unit.h"
|
|
|
|
|
#include "building.h"
|
|
|
|
|
#include "spell.h"
|
|
|
|
|
#include "race.h"
|
|
|
|
|
#include "attrib.h"
|
|
|
|
|
#include "plane.h"
|
|
|
|
|
#include "movement.h"
|
|
|
|
|
#include "alchemy.h"
|
|
|
|
|
#include "region.h"
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include "resources.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "unit.h"
|
|
|
|
|
#include "skill.h"
|
|
|
|
|
#include "message.h"
|
|
|
|
|
#include "objtypes.h"
|
|
|
|
|
#include "border.h"
|
|
|
|
|
#include "karma.h"
|
|
|
|
|
#include "ship.h"
|
|
|
|
|
#include "pathfinder.h"
|
|
|
|
|
#include "group.h"
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#ifdef USE_UGROUPS
|
|
|
|
|
#include "ugroup.h"
|
|
|
|
|
#include <attributes/ugroup.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-08-26 16:16:16 +02:00
|
|
|
|
/* modules include */
|
|
|
|
|
#ifdef ALLIANCES
|
|
|
|
|
# include <modules/alliance.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* attributes includes */
|
|
|
|
|
#include <attributes/key.h>
|
|
|
|
|
|
|
|
|
|
/* util includes */
|
|
|
|
|
#include <attrib.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include <base36.h>
|
|
|
|
|
#include <event.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include <resolve.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include <sql.h>
|
|
|
|
|
#include <umlaut.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
2001-02-13 01:41:17 +01:00
|
|
|
|
#define xisdigit(c) (((c) >= '0' && (c) <= '9') || (c) == '-')
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#define COMMENT_CHAR ';'
|
|
|
|
|
|
|
|
|
|
#define ESCAPE_FIX
|
|
|
|
|
|
|
|
|
|
int minfaction = 0;
|
|
|
|
|
const char * g_datadir;
|
|
|
|
|
/* imported symbols */
|
|
|
|
|
extern int cmsg[MAX_MSG][ML_MAX];
|
|
|
|
|
extern int quiet;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
extern int dice_rand(const char *s);
|
|
|
|
|
static region * current_region;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
int firstx = 0, firsty = 0;
|
|
|
|
|
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if RESOURCE_CONVERSION
|
2001-12-10 01:13:39 +01:00
|
|
|
|
int laen_read(attrib * a, FILE * F)
|
|
|
|
|
{
|
|
|
|
|
int laen;
|
|
|
|
|
fscanf(F, "%d", &laen);
|
|
|
|
|
read_laen(current_region, laen);
|
2002-04-07 02:44:01 +02:00
|
|
|
|
return AT_READ_FAIL;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
char *
|
|
|
|
|
rns(FILE * f, char *c, size_t size)
|
|
|
|
|
{
|
|
|
|
|
char * s = c;
|
|
|
|
|
do {
|
|
|
|
|
*s = (char) getc(f);
|
|
|
|
|
} while (*s!='"');
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
*s = (char) getc(f);
|
|
|
|
|
if (*s=='"') break;
|
|
|
|
|
if (s<c+size) ++s;
|
|
|
|
|
}
|
|
|
|
|
*s = 0;
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern unsigned int __at_hashkey(const char* s);
|
|
|
|
|
|
|
|
|
|
FILE *
|
|
|
|
|
cfopen(const char *filename, const char *mode)
|
|
|
|
|
{
|
|
|
|
|
FILE * F = fopen(filename, mode);
|
|
|
|
|
|
|
|
|
|
if (F == 0) {
|
|
|
|
|
perror(filename);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
setvbuf(F, 0, _IOFBF, 32 * 1024); /* 32 kb buffer size */
|
|
|
|
|
return F;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/* Dummy-Funktion f<>r die Kompatibilit<69>t */
|
|
|
|
|
|
2001-01-27 19:15:52 +01:00
|
|
|
|
#define rid(F) ((global.data_version<BASE36_VERSION)?ri(F):ri36(F))
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
int nextc;
|
|
|
|
|
|
|
|
|
|
#ifdef OLD_RC
|
|
|
|
|
void
|
|
|
|
|
rc(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
nextc = getc(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
#define rc(F) (nextc = getc(F))
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-12-01 12:23:17 +01:00
|
|
|
|
#undef CONVERT_DBLINK
|
2002-11-02 15:10:52 +01:00
|
|
|
|
#ifdef CONVERT_DBLINK
|
|
|
|
|
|
|
|
|
|
typedef struct uniquenode {
|
|
|
|
|
struct uniquenode * next;
|
|
|
|
|
int id;
|
|
|
|
|
faction * f;
|
|
|
|
|
} uniquenode;
|
|
|
|
|
|
|
|
|
|
#define HASHSIZE 2047
|
|
|
|
|
static uniquenode * uniquehash[HASHSIZE];
|
|
|
|
|
|
|
|
|
|
static faction *
|
|
|
|
|
uniquefaction(int id)
|
|
|
|
|
{
|
|
|
|
|
uniquenode * node = uniquehash[id%HASHSIZE];
|
|
|
|
|
while (node && node->id!=id) node=node->next;
|
|
|
|
|
return node?node->f:NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
addunique(int id, faction * f)
|
|
|
|
|
{
|
|
|
|
|
uniquenode * fnode = calloc(1, sizeof(uniquenode));
|
|
|
|
|
fnode->f = f;
|
|
|
|
|
fnode->id = id;
|
|
|
|
|
fnode->next = uniquehash[id%HASHSIZE];
|
|
|
|
|
uniquehash[id%HASHSIZE] = fnode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct mapnode {
|
|
|
|
|
struct mapnode * next;
|
|
|
|
|
int fno;
|
|
|
|
|
int subscription;
|
|
|
|
|
} mapnode;
|
|
|
|
|
|
|
|
|
|
static mapnode * subscriptions[HASHSIZE];
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
convertunique(faction * f)
|
|
|
|
|
{
|
|
|
|
|
int unique = f->subscription;
|
|
|
|
|
static FILE * F = NULL;
|
|
|
|
|
mapnode * mnode;
|
|
|
|
|
addunique(unique, f);
|
|
|
|
|
if (F==NULL) {
|
|
|
|
|
static char zText[MAX_PATH];
|
|
|
|
|
strcat(strcpy(zText, basepath()), "/subscriptions");
|
|
|
|
|
F = fopen(zText, "r");
|
|
|
|
|
if (F==NULL) {
|
|
|
|
|
log_error(("could not open %s.\n", zText));
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
for (;;) {
|
|
|
|
|
char zFaction[5];
|
|
|
|
|
int subscription, fno;
|
2002-11-03 14:40:17 +01:00
|
|
|
|
if (fscanf(F, "%d %s", &subscription, zFaction)<=0) break;
|
2002-11-02 15:10:52 +01:00
|
|
|
|
mnode = calloc(1, sizeof(mapnode));
|
|
|
|
|
fno = atoi36(zFaction);
|
|
|
|
|
mnode->next = subscriptions[fno%HASHSIZE];
|
|
|
|
|
mnode->fno = fno;
|
|
|
|
|
mnode->subscription = subscription;
|
|
|
|
|
subscriptions[fno%HASHSIZE] = mnode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mnode = subscriptions[f->no%HASHSIZE];
|
|
|
|
|
while (mnode!=NULL && mnode->fno!=f->no) mnode = mnode->next;
|
2002-11-02 16:50:51 +01:00
|
|
|
|
if (mnode) f->subscription = mnode->subscription;
|
|
|
|
|
else {
|
2002-11-02 18:38:43 +01:00
|
|
|
|
log_printf("%s %s %s %s\n",
|
2002-11-02 16:50:51 +01:00
|
|
|
|
itoa36(f->no), f->email, f->override, dbrace(f->race));
|
|
|
|
|
}
|
2002-11-02 15:10:52 +01:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
rds(FILE * F, char **ds)
|
|
|
|
|
{
|
|
|
|
|
static char buffer[DISPLAYSIZE + 1]; /*Platz f<>r null-char nicht vergessen!*/
|
|
|
|
|
char *s = &buffer[0];
|
|
|
|
|
|
|
|
|
|
while (nextc != '"') {
|
|
|
|
|
if (nextc == EOF) {
|
|
|
|
|
*s = 0;
|
|
|
|
|
fprintf(stderr, "Die Datei bricht vorzeitig ab.\n");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
assert(s <= buffer + DISPLAYSIZE + 1);
|
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc(F);
|
|
|
|
|
|
|
|
|
|
while (nextc != '"') {
|
|
|
|
|
if (nextc == EOF) {
|
|
|
|
|
assert(s <= buffer + DISPLAYSIZE + 1);
|
|
|
|
|
*s = 0;
|
|
|
|
|
fprintf(stderr, "Die Datei bricht vorzeitig ab.\n");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
*s++ = (char)nextc;
|
|
|
|
|
if (s - buffer > DISPLAYSIZE) {
|
|
|
|
|
assert(s <= buffer + DISPLAYSIZE + 1);
|
|
|
|
|
*s = 0;
|
|
|
|
|
printf("\nDer String %s wurde nicht terminiert.\n", s);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc(F);
|
|
|
|
|
assert(s <= buffer + DISPLAYSIZE + 1);
|
|
|
|
|
*s = 0;
|
|
|
|
|
(*ds) = realloc(*ds, sizeof(char) * (strlen(buffer) + 1));
|
|
|
|
|
|
|
|
|
|
strcpy(*ds, buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define rcf(F) (getc(F));
|
|
|
|
|
void
|
|
|
|
|
rsf(FILE * F, char *s, size_t len)
|
|
|
|
|
{
|
|
|
|
|
char * begin = s;
|
|
|
|
|
int nextc;
|
|
|
|
|
do {
|
|
|
|
|
nextc = rcf(F);
|
|
|
|
|
if (nextc == EOF) {
|
|
|
|
|
puts("Die Datei bricht vorzeitig ab.");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
} while (nextc != '"');
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
nextc = rcf(F);
|
|
|
|
|
if (nextc == '"') break;
|
|
|
|
|
else if (nextc == EOF) {
|
|
|
|
|
puts("Die Datei bricht vorzeitig ab.");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
if (s-begin<(int)len-1)
|
|
|
|
|
*s++ = (char)nextc;
|
|
|
|
|
}
|
|
|
|
|
*s = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
rs(FILE * F, char *s)
|
|
|
|
|
{
|
2001-02-25 20:31:40 +01:00
|
|
|
|
boolean apos = false;
|
|
|
|
|
while (isspace(nextc)) rc(F);
|
|
|
|
|
if (nextc=='"') {
|
|
|
|
|
apos=true;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rc(F);
|
|
|
|
|
}
|
2001-02-25 20:31:40 +01:00
|
|
|
|
for (;;) {
|
|
|
|
|
if (nextc=='"') {
|
|
|
|
|
rc(F);
|
|
|
|
|
break;
|
|
|
|
|
} else if (!apos && isspace(nextc)) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
*s++ = (char)nextc;
|
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
*s = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
ri(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
int i = 0, vz = 1;
|
|
|
|
|
|
|
|
|
|
while (!xisdigit(nextc)) {
|
|
|
|
|
if (nextc == EOF) {
|
|
|
|
|
puts("Die Datei bricht vorzeitig ab.");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (xisdigit(nextc)) {
|
|
|
|
|
if (nextc == '-')
|
|
|
|
|
vz = -1;
|
|
|
|
|
else
|
|
|
|
|
i = 10 * i + (nextc - '0');
|
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return i * vz;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
ri36(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
char buf[64];
|
|
|
|
|
int i = 0;
|
|
|
|
|
rc(F);
|
|
|
|
|
while (!isalnum(nextc)) rc(F);
|
|
|
|
|
while (isalnum(nextc)) {
|
|
|
|
|
buf[i++]=(char)nextc;
|
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
buf[i]=0;
|
|
|
|
|
i = atoi36(buf);
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define MAXLINE 4096*16
|
2002-03-10 13:04:12 +01:00
|
|
|
|
char *
|
2001-01-25 10:37:55 +01:00
|
|
|
|
getbuf(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
char lbuf[MAXLINE];
|
|
|
|
|
boolean cont = false;
|
|
|
|
|
boolean quote = false;
|
|
|
|
|
boolean comment = false;
|
|
|
|
|
char * cp = buf;
|
|
|
|
|
|
|
|
|
|
lbuf[MAXLINE-1] = '@';
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
boolean eatwhite = true;
|
|
|
|
|
boolean start = true;
|
|
|
|
|
unsigned char * end;
|
|
|
|
|
unsigned char * bp = (unsigned char * )fgets(lbuf, MAXLINE, F);
|
|
|
|
|
|
|
|
|
|
comment = (boolean)(comment && cont);
|
|
|
|
|
|
|
|
|
|
if (!bp) return NULL;
|
|
|
|
|
|
|
|
|
|
end = bp + strlen((const char *)bp);
|
|
|
|
|
if (*(end-1)=='\n') *(--end) = 0;
|
|
|
|
|
else {
|
|
|
|
|
while (bp && !lbuf[MAXLINE-1] && lbuf[MAXLINE-2]!='\n') {
|
|
|
|
|
/* wenn die zeile l<>nger als erlaubt war,
|
|
|
|
|
* wird der rest weggeworfen: */
|
|
|
|
|
bp = (unsigned char *)fgets(buf, 1024, F);
|
|
|
|
|
comment = false;
|
|
|
|
|
}
|
|
|
|
|
bp = (unsigned char *)lbuf;
|
|
|
|
|
}
|
|
|
|
|
cont = false;
|
|
|
|
|
while (cp!=buf+MAXLINE && (char*)bp!=lbuf+MAXLINE && *bp) {
|
|
|
|
|
if (isspace(*bp)) {
|
|
|
|
|
if (eatwhite)
|
|
|
|
|
{
|
|
|
|
|
do { ++bp; } while ((char*)bp!=lbuf+MAXLINE && isspace(*bp));
|
|
|
|
|
if (!quote && !start && !comment) *(cp++)=' ';
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
do {
|
|
|
|
|
if (!comment) *(cp++)=SPACE_REPLACEMENT;
|
|
|
|
|
++bp;
|
|
|
|
|
} while (cp!=buf+MAXLINE && (char*)bp!=lbuf+MAXLINE && isspace(*bp));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (iscntrl(*bp)) {
|
|
|
|
|
*(cp++) = '?';
|
|
|
|
|
++bp;
|
|
|
|
|
} else {
|
|
|
|
|
cont = false;
|
|
|
|
|
if (*bp==COMMENT_CHAR && !quote) {
|
2003-09-21 18:15:39 +02:00
|
|
|
|
/* bp = max(end-1, bp+1); */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
comment=true;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (*bp=='"') {
|
|
|
|
|
quote = (boolean)!quote;
|
|
|
|
|
eatwhite=true;
|
|
|
|
|
}
|
|
|
|
|
else if (*bp=='\\') cont=true;
|
|
|
|
|
else {
|
|
|
|
|
if (!comment) *(cp++) = *bp;
|
|
|
|
|
eatwhite = (boolean)!quote;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-09-21 18:15:39 +02:00
|
|
|
|
++bp;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
start = false;
|
|
|
|
|
}
|
|
|
|
|
if (cp==buf+MAXLINE) {
|
|
|
|
|
--cp;
|
|
|
|
|
}
|
|
|
|
|
*cp=0;
|
|
|
|
|
} while (cont || cp==buf);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-18 01:34:19 +01:00
|
|
|
|
#ifdef REGIONOWNERS
|
|
|
|
|
static void
|
|
|
|
|
read_enemies(FILE * F, faction * f)
|
|
|
|
|
{
|
|
|
|
|
if (global.data_version<REGIONOWNERS_VERSION) return;
|
|
|
|
|
f->enemies = NULL;
|
|
|
|
|
for (;;) {
|
|
|
|
|
char zText[32];
|
|
|
|
|
fscanf(F, "%s", zText);
|
|
|
|
|
if (strcmp(zText, "end")==0) break;
|
|
|
|
|
else {
|
|
|
|
|
int fno = atoi36(zText);
|
|
|
|
|
faction_list * flist = malloc(sizeof(faction_list));
|
|
|
|
|
flist->next = f->enemies;
|
|
|
|
|
f->enemies = flist;
|
|
|
|
|
ur_add((void*)fno, (void**)&flist->data, resolve_faction);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_enemies(FILE * F, const faction_list * flist)
|
|
|
|
|
{
|
|
|
|
|
#if RELEASE_VERSION>=REGIONOWNERS_VERSION
|
|
|
|
|
while (flist) {
|
|
|
|
|
fprintf(F, "%s ", itoa36(flist->data->no));
|
|
|
|
|
}
|
|
|
|
|
fputs("end\n", F);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static unit *
|
2002-03-03 16:16:28 +01:00
|
|
|
|
unitorders(FILE * F, struct faction * f)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int p;
|
|
|
|
|
unit *u;
|
|
|
|
|
strlist *S, **SP;
|
|
|
|
|
|
|
|
|
|
if (!f) return NULL;
|
|
|
|
|
|
|
|
|
|
i = getid();
|
|
|
|
|
u = findunitg(i, NULL);
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (u && old_race(u->race) == RC_SPELL) return NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (u && u->faction == f) {
|
|
|
|
|
/* SP zeigt nun auf den Pointer zur ersten StrListe. Auf die
|
|
|
|
|
* erste StrListe wird mit u->orders gezeigt. Deswegen also
|
|
|
|
|
* &u->orders, denn SP zeigt nicht auf die selbe stelle wie
|
|
|
|
|
* u->orders, sondern auf die stelle VON u->orders! */
|
|
|
|
|
|
|
|
|
|
freestrlist(u->orders);
|
|
|
|
|
u->orders = 0;
|
|
|
|
|
|
|
|
|
|
SP = &u->orders;
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
|
|
|
|
|
/* Erst wenn wir sicher sind, dass kein Befehl
|
|
|
|
|
* eingegeben wurde, checken wir, ob nun eine neue
|
|
|
|
|
* Einheit oder ein neuer Spieler drankommt */
|
|
|
|
|
|
|
|
|
|
if (!getbuf(F))
|
|
|
|
|
break;
|
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (igetkeyword(buf, u->faction->locale) == NOKEYWORD) {
|
|
|
|
|
p = igetparam(buf, u->faction->locale);
|
2001-09-05 21:40:40 +02:00
|
|
|
|
if (p == P_UNIT || p == P_FACTION || p == P_NEXT || p == P_GAMENAME)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (buf[0]) {
|
|
|
|
|
/* Nun wird eine StrListe S mit dem Inhalt buf2
|
|
|
|
|
* angelegt. S->next zeigt nirgends hin. */
|
|
|
|
|
|
|
|
|
|
S = makestrlist(buf);
|
|
|
|
|
|
|
|
|
|
/* Nun werden zwei Operationen ausgefuehrt
|
|
|
|
|
* (addlist2 ist ein #definiertes macro!):
|
|
|
|
|
* *SP = S Der Pointer, auf den SP zeigte, zeigt nun auf S! Also
|
|
|
|
|
* entweder u->orders oder S(alt)->next zeigen nun auf das neue S!
|
|
|
|
|
*
|
|
|
|
|
* SP = &S->next SP zeigt nun auf den Pointer S->next. Nicht auf
|
|
|
|
|
* dieselbe Stelle wie S->next, sondern auf die Stelle VON S->next! */
|
|
|
|
|
|
|
|
|
|
addlist2(SP, S);
|
|
|
|
|
|
|
|
|
|
/* Und das letzte S->next darf nat<61>rlich nirgends mehr hinzeigen, es
|
|
|
|
|
* wird auf null gesetzt. Warum das nicht bei addlist2 getan wird, ist
|
|
|
|
|
* mir schleierhaft. So wie es jetzt implementiert ist, kann man es
|
|
|
|
|
* (hier auf alle F<EFBFBD>lle) hinter addlist2 schreiben, oder auch nur am
|
|
|
|
|
* Ende einmal aufrufen - das w<EFBFBD>re aber bei allen returns, und am ende
|
|
|
|
|
* des for (;;) blockes. Grmpf. Dann lieber hier, immer, und daf<EFBFBD>r
|
|
|
|
|
* sauberer... */
|
|
|
|
|
|
|
|
|
|
*SP = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u->botschaften = NULL; /* Sicherheitshalber */
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
/* cmistake(?, gc_add(strdup(buf)), 160, MSG_EVENT); */
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return u;
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------ */
|
|
|
|
|
|
|
|
|
|
static faction *
|
2002-03-03 16:16:28 +01:00
|
|
|
|
factionorders(void)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
char b[16];
|
2002-05-01 21:08:32 +02:00
|
|
|
|
char * fid = strnzcpy(b, getstrtoken(), 15);
|
2003-06-22 10:38:55 +02:00
|
|
|
|
const char * pass = getstrtoken();
|
2001-01-25 10:37:55 +01:00
|
|
|
|
faction *f;
|
|
|
|
|
|
2002-03-10 09:39:56 +01:00
|
|
|
|
f = findfaction(atoi36(fid));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if (f!=NULL) {
|
|
|
|
|
/* Kontrolliere, ob das Passwort richtig eingegeben wurde. Es
|
|
|
|
|
* mu<EFBFBD> in "G<EFBFBD>nsef<EFBFBD><EFBFBD>chen" stehen!! */
|
|
|
|
|
|
|
|
|
|
/* War vorher in main.c:getgarbage() */
|
2001-09-05 21:40:40 +02:00
|
|
|
|
if (!quiet) {
|
2001-02-17 16:02:50 +01:00
|
|
|
|
printf(" %4s;", factionid(f));
|
2001-09-05 21:40:40 +02:00
|
|
|
|
fflush(stdout);
|
2001-02-17 16:02:50 +01:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
freestrlist(f->mistakes);
|
|
|
|
|
f->mistakes = 0;
|
|
|
|
|
|
2003-06-22 10:38:55 +02:00
|
|
|
|
if (checkpasswd(f, pass, true) == false) {
|
2004-03-21 22:29:37 +01:00
|
|
|
|
log_warning(("Invalid password for faction %s\n", fid));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
addstrlist(&f->mistakes, "Das Passwort wurde falsch eingegeben");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* Die Partei hat sich zumindest gemeldet, so da<64> sie noch
|
|
|
|
|
* nicht als unt<EFBFBD>tig gilt */
|
|
|
|
|
|
2003-12-28 16:30:43 +01:00
|
|
|
|
/* TODO: +1 ist ein Workaround, weil turn erst in process_orders
|
|
|
|
|
* incrementiert wird. */
|
2004-01-04 23:29:33 +01:00
|
|
|
|
f->lastorders = global.data_turn+1;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
} else
|
2001-03-04 19:41:27 +01:00
|
|
|
|
log_warning(("Befehle f<>r die ung<6E>ltige Partei %s\n", fid));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
return f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
version(void)
|
|
|
|
|
{
|
|
|
|
|
return RELEASE_VERSION * 0.1;
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
readorders(const char *filename)
|
|
|
|
|
{
|
2003-07-29 11:48:03 +02:00
|
|
|
|
FILE * F = NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
char *b;
|
2001-02-17 16:02:50 +01:00
|
|
|
|
int nfactions=0;
|
|
|
|
|
struct faction *f = NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (filename) F = cfopen(filename, "rt");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (F==NULL) return 0;
|
|
|
|
|
|
2001-02-17 16:02:50 +01:00
|
|
|
|
puts(" - lese Befehlsdatei...\n");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
b = getbuf(F);
|
|
|
|
|
|
|
|
|
|
/* Auffinden der ersten Partei, und danach abarbeiten bis zur letzten
|
|
|
|
|
* Partei */
|
|
|
|
|
|
|
|
|
|
while (b) {
|
2001-09-05 21:40:40 +02:00
|
|
|
|
const struct locale * lang = f?f->locale:default_locale;
|
2001-02-17 16:02:50 +01:00
|
|
|
|
int p;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
const char * s;
|
|
|
|
|
|
|
|
|
|
switch (igetparam(b, lang)) {
|
|
|
|
|
case P_LOCALE:
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
#define LOCALES
|
|
|
|
|
#ifdef LOCALES
|
|
|
|
|
if (f && find_locale(s)) {
|
|
|
|
|
f->locale = find_locale(s);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
if(strcmp(s, "de") == 0) {
|
|
|
|
|
f->locale = find_locale(s);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-02-17 16:02:50 +01:00
|
|
|
|
|
2001-04-16 16:34:19 +02:00
|
|
|
|
b = getbuf(F);
|
|
|
|
|
break;
|
2001-09-05 21:40:40 +02:00
|
|
|
|
case P_GAMENAME:
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case P_FACTION:
|
2002-03-03 16:16:28 +01:00
|
|
|
|
f = factionorders();
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (f) {
|
|
|
|
|
++nfactions;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
b = getbuf(F);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
2002-03-03 16:16:28 +01:00
|
|
|
|
/* in factionorders wird nur eine zeile gelesen:
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* diejenige mit dem passwort. Die befehle der units
|
|
|
|
|
* werden geloescht, und die Partei wird als aktiv
|
|
|
|
|
* vermerkt. */
|
|
|
|
|
|
|
|
|
|
case P_UNIT:
|
2002-03-03 16:16:28 +01:00
|
|
|
|
if (!f || !unitorders(F, f)) do {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
b = getbuf(F);
|
|
|
|
|
if (!b) break;
|
2001-04-16 16:34:19 +02:00
|
|
|
|
p = igetparam(b, lang);
|
2001-09-05 21:40:40 +02:00
|
|
|
|
} while ((p != P_UNIT || !f) && p != P_FACTION && p != P_NEXT && p != P_GAMENAME);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
2002-03-03 16:16:28 +01:00
|
|
|
|
/* Falls in unitorders() abgebrochen wird, steht dort entweder eine neue
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* Partei, eine neue Einheit oder das File-Ende. Das switch() wird erneut
|
|
|
|
|
* durchlaufen, und die entsprechende Funktion aufgerufen. Man darf buf
|
|
|
|
|
* auf alle F<EFBFBD>lle nicht <EFBFBD>berschreiben! Bei allen anderen Eintr<EFBFBD>gen hier
|
|
|
|
|
* mu<EFBFBD> buf erneut gef<EFBFBD>llt werden, da die betreffende Information in nur
|
|
|
|
|
* einer Zeile steht, und nun die n<EFBFBD>chste gelesen werden mu<EFBFBD>. */
|
|
|
|
|
|
|
|
|
|
case P_NEXT:
|
2001-04-16 16:34:19 +02:00
|
|
|
|
f = NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
default:
|
|
|
|
|
b = getbuf(F);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(F);
|
2001-02-17 16:02:50 +01:00
|
|
|
|
puts("\n");
|
|
|
|
|
printf(" %d Befehlsdateien gelesen\n", nfactions);
|
2001-02-05 17:11:59 +01:00
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/* #define INNER_WORLD */
|
|
|
|
|
/* f<>rs debuggen nur den inneren Teil der Welt laden */
|
|
|
|
|
/* -9;-27;-1;-19;Sumpfloch */
|
|
|
|
|
int
|
|
|
|
|
inner_world(region * r)
|
|
|
|
|
{
|
|
|
|
|
static int xy[2] =
|
|
|
|
|
{18, -45};
|
|
|
|
|
static int size[2] =
|
|
|
|
|
{27, 27};
|
|
|
|
|
|
|
|
|
|
if (r->x >= xy[0] && r->x < xy[0] + size[0] && r->y >= xy[1] && r->y < xy[1] + size[1])
|
|
|
|
|
return 2;
|
|
|
|
|
if (r->x >= xy[0] - 9 && r->x < xy[0] + size[0] + 9 && r->y >= xy[1] - 9 && r->y < xy[1] + size[1] + 9)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int maxregions = -1;
|
2002-05-05 11:34:36 +02:00
|
|
|
|
int loadplane = 0;
|
|
|
|
|
|
2001-09-05 21:40:40 +02:00
|
|
|
|
boolean dirtyload = false;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
U_MAN,
|
|
|
|
|
U_UNDEAD,
|
|
|
|
|
U_ILLUSION,
|
|
|
|
|
U_FIREDRAGON,
|
|
|
|
|
U_DRAGON,
|
|
|
|
|
U_WYRM,
|
|
|
|
|
U_SPELL,
|
|
|
|
|
U_TAVERNE,
|
|
|
|
|
U_MONSTER,
|
|
|
|
|
U_BIRTHDAYDRAGON,
|
|
|
|
|
U_TREEMAN,
|
|
|
|
|
MAXTYPES
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
race_t
|
|
|
|
|
typus2race(unsigned char typus)
|
|
|
|
|
{
|
|
|
|
|
if (typus>0 && typus <=11) return (race_t)(typus-1);
|
|
|
|
|
return NORACE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean
|
2001-05-17 22:24:28 +02:00
|
|
|
|
is_persistent(const char *s, const struct locale *lang)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2001-05-17 22:24:28 +02:00
|
|
|
|
if (s==NULL) return false;
|
2001-09-05 21:40:40 +02:00
|
|
|
|
#ifdef AT_PERSISTENT
|
2001-05-17 22:24:28 +02:00
|
|
|
|
if(*s == '@') return true;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#endif /* Nur kurze Befehle! */
|
2001-04-16 16:34:19 +02:00
|
|
|
|
switch(igetkeyword(s, lang)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
case K_KOMMENTAR:
|
|
|
|
|
case K_LIEFERE:
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
create_backup(char *file)
|
|
|
|
|
{
|
|
|
|
|
#if defined(HAVE_ACCESS)
|
2001-02-03 14:45:35 +01:00
|
|
|
|
char bfile[MAX_PATH];
|
|
|
|
|
char command[MAX_PATH*2+10];
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int c = 1;
|
|
|
|
|
do {
|
|
|
|
|
sprintf(bfile, "%s.backup%d", file, c);
|
|
|
|
|
c++;
|
|
|
|
|
} while(access(bfile, R_OK) == 0);
|
|
|
|
|
sprintf(command, "cp %s %s", file, bfile);
|
|
|
|
|
system(command);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2001-09-05 21:40:40 +02:00
|
|
|
|
const char *
|
2001-01-25 10:37:55 +01:00
|
|
|
|
datapath(void)
|
|
|
|
|
{
|
2001-02-03 14:45:35 +01:00
|
|
|
|
static char zText[MAX_PATH];
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (g_datadir) return g_datadir;
|
|
|
|
|
return strcat(strcpy(zText, basepath()), "/data");
|
|
|
|
|
}
|
2001-09-05 21:40:40 +02:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
read_items(FILE *F, item **ilist)
|
|
|
|
|
{
|
|
|
|
|
for (;;) {
|
2003-12-14 11:10:30 +01:00
|
|
|
|
const item_type * itype;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rs(F, buf);
|
|
|
|
|
if (!strcmp("end", buf)) break;
|
2003-12-14 11:10:30 +01:00
|
|
|
|
itype = it_find(buf);
|
|
|
|
|
if (itype!=NULL) i_change(ilist, itype, ri(F));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-15 13:26:04 +01:00
|
|
|
|
#if RESOURCE_CONVERSION
|
2002-05-02 23:19:45 +02:00
|
|
|
|
struct attrib_type at_resources = {
|
|
|
|
|
"resources", NULL, NULL, NULL, NULL, NULL, ATF_UNIQUE
|
2001-12-10 01:13:39 +01:00
|
|
|
|
};
|
|
|
|
|
|
2002-05-02 23:19:45 +02:00
|
|
|
|
void
|
2001-12-10 01:13:39 +01:00
|
|
|
|
read_iron(struct region * r, int iron)
|
|
|
|
|
{
|
|
|
|
|
attrib * a = a_find(r->attribs, &at_resources);
|
|
|
|
|
assert(iron>=0);
|
|
|
|
|
if (a==NULL) {
|
|
|
|
|
a = a_add(&r->attribs, a_new(&at_resources));
|
|
|
|
|
a->data.sa[1] = -1;
|
|
|
|
|
}
|
|
|
|
|
a->data.sa[0] = (short)iron;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-02 23:19:45 +02:00
|
|
|
|
void
|
2001-12-10 01:13:39 +01:00
|
|
|
|
read_laen(struct region * r, int laen)
|
|
|
|
|
{
|
|
|
|
|
attrib * a = a_find(r->attribs, &at_resources);
|
|
|
|
|
assert(laen>=0);
|
|
|
|
|
if (a==NULL) {
|
|
|
|
|
a = a_add(&r->attribs, a_new(&at_resources));
|
|
|
|
|
a->data.sa[0] = -1;
|
|
|
|
|
}
|
|
|
|
|
a->data.sa[1] = (short)laen;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef USE_UGROUPS
|
|
|
|
|
void
|
|
|
|
|
read_ugroups(FILE *file)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
faction *f;
|
|
|
|
|
ugroup *ug;
|
|
|
|
|
int fno, ugid, ugmem;
|
|
|
|
|
|
|
|
|
|
while(1) {
|
|
|
|
|
fno = ri(file);
|
|
|
|
|
if(fno == -1) break;
|
|
|
|
|
f = findfaction(fno);
|
|
|
|
|
while(1) {
|
|
|
|
|
ugid = ri(file);
|
|
|
|
|
if(ugid == -1) break;
|
|
|
|
|
ugmem = ri(file);
|
|
|
|
|
ug = malloc(sizeof(ugroup));
|
|
|
|
|
ug->id = ugid;
|
|
|
|
|
ug->members = ugmem;
|
|
|
|
|
ug->unit_array = malloc(ug->members * sizeof(unit *));
|
|
|
|
|
for(i=0; i<ugmem; i++) {
|
|
|
|
|
unit *u = findunitg(ri36(file), NULL);
|
|
|
|
|
ug->unit_array[i] = u;
|
|
|
|
|
a_add(&u->attribs, a_new(&at_ugroup))->data.i = ugid;
|
|
|
|
|
}
|
|
|
|
|
ug->next = f->ugroups;
|
|
|
|
|
f->ugroups = ug;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-08-26 16:16:16 +02:00
|
|
|
|
#ifdef ALLIANCES
|
2002-11-25 16:30:51 +01:00
|
|
|
|
void
|
2002-08-26 16:16:16 +02:00
|
|
|
|
read_alliances(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
char pbuf[32];
|
2002-09-29 22:36:15 +02:00
|
|
|
|
rs(F, pbuf);
|
2002-08-26 16:16:16 +02:00
|
|
|
|
while (strcmp(pbuf, "end")!=0) {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
makealliance(atoi36(pbuf), buf);
|
2002-09-29 22:36:15 +02:00
|
|
|
|
rs(F, pbuf);
|
2002-08-26 16:16:16 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int
|
2003-12-17 11:28:23 +01:00
|
|
|
|
readgame(const char * filename, int backup)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int i, n, p;
|
|
|
|
|
faction *f, **fp;
|
|
|
|
|
region *r;
|
|
|
|
|
building *b, **bp;
|
|
|
|
|
ship *sh, **shp;
|
|
|
|
|
unit *u;
|
|
|
|
|
FILE * F;
|
2002-04-07 23:12:41 +02:00
|
|
|
|
int rmax = maxregions;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2003-12-14 20:17:59 +01:00
|
|
|
|
sprintf(buf, "%s/%s", datapath(), filename);
|
2004-02-21 23:25:00 +01:00
|
|
|
|
log_printf("- reading game data from %s\n", filename);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (backup) create_backup(buf);
|
|
|
|
|
F = cfopen(buf, "r");
|
|
|
|
|
if (F==NULL) {
|
|
|
|
|
printf("Keine Spieldaten gefunden.\n");
|
|
|
|
|
#if 0
|
|
|
|
|
printf("Neues Spiel (j/n)? ");
|
|
|
|
|
if (tolower(getchar()) != 'j') {
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
return creategame();
|
|
|
|
|
#else
|
|
|
|
|
return -1;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc(F);
|
|
|
|
|
|
|
|
|
|
/* globale Variablen */
|
|
|
|
|
|
2001-01-27 19:15:52 +01:00
|
|
|
|
global.data_version = ri(F);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
assert(global.data_version>=MIN_VERSION || !"unsupported data format");
|
|
|
|
|
assert(global.data_version<=RELEASE_VERSION || !"unsupported data format");
|
2001-01-28 09:01:52 +01:00
|
|
|
|
assert(global.data_version >= NEWSOURCE_VERSION);
|
2004-01-11 11:05:03 +01:00
|
|
|
|
if(global.data_version >= SAVEXMLNAME_VERSION) {
|
|
|
|
|
char basefile[1024];
|
2004-01-12 17:22:14 +01:00
|
|
|
|
const char *basearg = "(null)";
|
2004-01-11 11:05:03 +01:00
|
|
|
|
|
|
|
|
|
rs(F, basefile);
|
2004-01-18 21:29:47 +01:00
|
|
|
|
assert(xmlfile != NULL);
|
|
|
|
|
basearg = strrchr(xmlfile, '/');
|
|
|
|
|
if (basearg==NULL) {
|
|
|
|
|
basearg = xmlfile;
|
|
|
|
|
} else {
|
|
|
|
|
++basearg;
|
2004-01-11 11:05:03 +01:00
|
|
|
|
}
|
2004-01-12 17:22:14 +01:00
|
|
|
|
if (strcmp(basearg, basefile)!=0) {
|
2004-01-11 11:05:03 +01:00
|
|
|
|
printf("WARNING: xmlfile mismatch:\n");
|
|
|
|
|
printf("WARNING: datafile contains %s\n", basefile);
|
|
|
|
|
printf("WARNING: argument/default is %s\n", basearg);
|
|
|
|
|
printf("WARNING: any key to continue, Ctrl-C to stop\n");
|
|
|
|
|
getchar();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (global.data_version >= GLOBAL_ATTRIB_VERSION) {
|
|
|
|
|
a_read(F, &global.attribs);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifndef COMPATIBILITY
|
2001-01-27 19:15:52 +01:00
|
|
|
|
if (global.data_version < ITEMTYPE_VERSION) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
fprintf(stderr, "kann keine alten datenfiles einlesen");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2004-01-04 23:29:33 +01:00
|
|
|
|
global.data_turn = turn = ri(F);
|
2002-03-29 05:23:51 +01:00
|
|
|
|
/* read_dynamictypes(); */
|
2002-11-02 15:10:52 +01:00
|
|
|
|
/* max_unique_id = */ ri(F);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
nextborder = ri(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Planes */
|
|
|
|
|
planes = NULL;
|
|
|
|
|
n = ri(F);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
while(--n >= 0) {
|
|
|
|
|
plane *pl = calloc(1, sizeof(plane));
|
|
|
|
|
pl->id = ri(F);
|
|
|
|
|
rds(F, &pl->name);
|
|
|
|
|
pl->minx = ri(F);
|
|
|
|
|
pl->maxx = ri(F);
|
|
|
|
|
pl->miny = ri(F);
|
|
|
|
|
pl->maxy = ri(F);
|
|
|
|
|
pl->flags = ri(F);
|
2002-02-18 22:41:11 +01:00
|
|
|
|
if (global.data_version>WATCHERS_VERSION) {
|
2002-03-03 17:58:10 +01:00
|
|
|
|
rs(F, buf);
|
|
|
|
|
while (strcmp(buf, "end")!=0) {
|
2002-02-18 22:41:11 +01:00
|
|
|
|
watcher * w = calloc(sizeof(watcher),1);
|
2002-03-03 17:58:10 +01:00
|
|
|
|
int fno = atoi36(buf);
|
2002-02-18 22:41:11 +01:00
|
|
|
|
w->mode = (unsigned char)ri(F);
|
|
|
|
|
w->next = pl->watchers;
|
|
|
|
|
pl->watchers = w;
|
2002-02-23 12:27:19 +01:00
|
|
|
|
ur_add((void*)fno, (void**)&w->faction, resolve_faction);
|
2002-03-10 08:23:45 +01:00
|
|
|
|
rs(F, buf);
|
2002-02-18 22:41:11 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
a_read(F, &pl->attribs);
|
|
|
|
|
addlist(&planes, pl);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read factions */
|
2002-08-26 16:16:16 +02:00
|
|
|
|
#ifdef ALLIANCES
|
2002-09-29 22:36:15 +02:00
|
|
|
|
if (global.data_version>=ALLIANCES_VERSION) {
|
2002-08-26 16:16:16 +02:00
|
|
|
|
read_alliances(F);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
n = ri(F);
|
|
|
|
|
printf(" - Einzulesende Parteien: %d\n", n);
|
|
|
|
|
fp = &factions;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
while (*fp) fp=&(*fp)->next;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* fflush (stdout); */
|
|
|
|
|
|
|
|
|
|
while (--n >= 0) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
faction * f = readfaction(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
addlist2(fp, f);
|
|
|
|
|
}
|
|
|
|
|
*fp = 0;
|
|
|
|
|
|
|
|
|
|
/* Benutzte Faction-Ids */
|
|
|
|
|
|
2002-09-02 22:36:12 +02:00
|
|
|
|
no_used_faction_ids = ri(F);
|
|
|
|
|
/* used_faction_ids = gc_add(malloc(no_used_faction_ids*sizeof(int))); */
|
|
|
|
|
used_faction_ids = malloc(no_used_faction_ids*sizeof(int));
|
|
|
|
|
for(i=0; i < no_used_faction_ids; i++) {
|
|
|
|
|
used_faction_ids[i] = ri(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Regionen */
|
|
|
|
|
|
|
|
|
|
n = ri(F);
|
2002-04-07 23:12:41 +02:00
|
|
|
|
if (rmax<0) rmax = n;
|
|
|
|
|
printf(" - Einzulesende Regionen: %d/%d\r", rmax, n);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
while (--n >= 0) {
|
|
|
|
|
unit **up;
|
|
|
|
|
boolean skip = false;
|
|
|
|
|
int x = ri(F);
|
|
|
|
|
int y = ri(F);
|
2002-05-05 11:34:36 +02:00
|
|
|
|
plane * pl = findplane(x, y);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if (firstx && firsty) {
|
|
|
|
|
if (x!=firstx || y!=firsty) {
|
|
|
|
|
skip = true;
|
|
|
|
|
} else {
|
|
|
|
|
firstx=0;
|
|
|
|
|
firsty=0;
|
2002-04-07 23:12:41 +02:00
|
|
|
|
if (rmax>0) rmax = min(n, rmax)-1;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-05-05 11:34:36 +02:00
|
|
|
|
if (loadplane && (!pl || pl->id!=loadplane)) skip = true;
|
2002-04-07 23:12:41 +02:00
|
|
|
|
if (rmax==0) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
if (dirtyload) break;
|
2001-09-05 21:40:40 +02:00
|
|
|
|
skip = true;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if ((n%1024)==0) { /* das spart extrem Zeit */
|
2002-04-07 23:12:41 +02:00
|
|
|
|
printf(" - Einzulesende Regionen: %d/%d ", rmax, n);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
printf("* %d,%d \r", x, y);
|
|
|
|
|
}
|
|
|
|
|
if (skip) {
|
|
|
|
|
char * r;
|
|
|
|
|
do {
|
|
|
|
|
r = fgets(buf, BUFSIZE, F); /* skip region */
|
|
|
|
|
} while (r && buf[0]!='\n');
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2002-04-07 23:12:41 +02:00
|
|
|
|
--rmax;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-03-03 16:16:28 +01:00
|
|
|
|
r = readregion(F, x, y);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Burgen */
|
|
|
|
|
p = ri(F);
|
|
|
|
|
bp = &r->buildings;
|
|
|
|
|
|
|
|
|
|
while (--p >= 0) {
|
|
|
|
|
|
|
|
|
|
b = (building *) calloc(1, sizeof(building));
|
2002-09-02 22:36:12 +02:00
|
|
|
|
b->no = rid(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
bhash(b);
|
|
|
|
|
rds(F, &b->name);
|
|
|
|
|
rds(F, &b->display);
|
|
|
|
|
b->size = ri(F);
|
2001-01-27 19:15:52 +01:00
|
|
|
|
if (global.data_version < TYPES_VERSION) {
|
2002-03-27 22:49:27 +01:00
|
|
|
|
assert(!"data format is no longer supported");
|
|
|
|
|
/* b->type = oldbuildings[ri(F)]; */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
b->type = bt_find(buf);
|
|
|
|
|
}
|
|
|
|
|
b->region = r;
|
|
|
|
|
a_read(F, &b->attribs);
|
|
|
|
|
addlist2(bp, b);
|
|
|
|
|
}
|
|
|
|
|
/* Schiffe */
|
|
|
|
|
|
|
|
|
|
p = ri(F);
|
|
|
|
|
shp = &r->ships;
|
|
|
|
|
|
|
|
|
|
while (--p >= 0) {
|
|
|
|
|
sh = (ship *) calloc(1, sizeof(ship));
|
|
|
|
|
|
2001-02-18 11:06:10 +01:00
|
|
|
|
sh->region = r;
|
2002-09-02 22:36:12 +02:00
|
|
|
|
sh->no = rid(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
shash(sh);
|
|
|
|
|
rds(F, &sh->name);
|
|
|
|
|
rds(F, &sh->display);
|
|
|
|
|
|
2002-09-02 22:36:12 +02:00
|
|
|
|
rs(F, buf);
|
|
|
|
|
sh->type = st_find(buf);
|
|
|
|
|
assert(sh->type || !"ship_type not registered!");
|
|
|
|
|
sh->size = ri(F);
|
|
|
|
|
sh->damage = ri(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* Attribute rekursiv einlesen */
|
|
|
|
|
|
|
|
|
|
sh->coast = (direction_t)ri(F);
|
|
|
|
|
a_read(F, &sh->attribs);
|
|
|
|
|
|
|
|
|
|
addlist2(shp, sh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*shp = 0;
|
|
|
|
|
|
|
|
|
|
/* Einheiten */
|
|
|
|
|
|
|
|
|
|
p = ri(F);
|
|
|
|
|
up = &r->units;
|
|
|
|
|
|
|
|
|
|
while (--p >= 0) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
unit * u = readunit(F);
|
|
|
|
|
assert(u->region==NULL);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
u->region = r;
|
2001-02-05 17:11:59 +01:00
|
|
|
|
addlist2(up,u);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-04-07 02:44:01 +02:00
|
|
|
|
printf("\n");
|
2001-09-05 21:40:40 +02:00
|
|
|
|
if (!dirtyload) {
|
2002-09-02 22:36:12 +02:00
|
|
|
|
read_borders(F);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#ifdef USE_UGROUPS
|
|
|
|
|
if (global.data_version >= UGROUPS_VERSION) read_ugroups(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#endif
|
2001-09-05 21:40:40 +02:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
#ifdef WEATHER
|
|
|
|
|
|
|
|
|
|
/* Wetter lesen */
|
|
|
|
|
|
|
|
|
|
weathers = NULL;
|
|
|
|
|
|
2001-01-27 19:15:52 +01:00
|
|
|
|
if (global.data_version >= 81) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
n = ri(F);
|
|
|
|
|
while(--n >= 0) {
|
|
|
|
|
weather *w;
|
|
|
|
|
|
|
|
|
|
w = calloc(1, sizeof(weather));
|
|
|
|
|
|
|
|
|
|
w->type = ri(F);
|
|
|
|
|
w->radius = ri(F);
|
|
|
|
|
w->center[0] = ri(F);
|
|
|
|
|
w->center[1] = ri(F);
|
|
|
|
|
w->move[0] = ri(F);
|
|
|
|
|
w->move[1] = ri(F);
|
|
|
|
|
|
|
|
|
|
addlist(&weathers, w);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-12-10 01:13:39 +01:00
|
|
|
|
fclose(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#ifdef AMIGA
|
|
|
|
|
fputs("Ok.", stderr);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Unaufgeloeste Zeiger initialisieren */
|
|
|
|
|
printf("\n - Referenzen initialisieren...\n");
|
|
|
|
|
resolve();
|
|
|
|
|
resolve_IDs();
|
|
|
|
|
|
|
|
|
|
printf("\n - Leere Gruppen l<>schen...\n");
|
|
|
|
|
for (f=factions; f; f=f->next) {
|
|
|
|
|
group ** gp = &f->groups;
|
|
|
|
|
while (*gp) {
|
|
|
|
|
group * g = *gp;
|
|
|
|
|
if (g->members==0) {
|
|
|
|
|
*gp = g->next;
|
|
|
|
|
free_group(g);
|
|
|
|
|
} else
|
|
|
|
|
gp = &g->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
resolve_IDs();
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* speziell f<>r Runde 199->200 */
|
|
|
|
|
printf("Actions korrigieren...\n");
|
|
|
|
|
iuw_fix_rest();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
building * b;
|
2002-03-27 22:49:27 +01:00
|
|
|
|
for (b=r->buildings;b;b=b->next) update_lighthouse(b);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
printf(" - Regionen initialisieren & verbinden...\n");
|
|
|
|
|
for (r = regions; r; r = r->next) {
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
u->faction->alive = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-09-05 21:40:40 +02:00
|
|
|
|
if(findfaction(0)) {
|
|
|
|
|
findfaction(0)->alive = 1;
|
|
|
|
|
}
|
2002-05-05 11:34:36 +02:00
|
|
|
|
if (loadplane || maxregions>=0) {
|
2002-05-02 01:47:32 +02:00
|
|
|
|
remove_empty_factions(false);
|
2002-04-07 02:44:01 +02:00
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2004-02-22 15:42:24 +01:00
|
|
|
|
#if 0
|
|
|
|
|
/* what is this doing here? ageing happens at the end of the turn. goddamn it. */
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* Regionen */
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
2004-02-22 15:42:24 +01:00
|
|
|
|
building ** bp;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
unit ** up;
|
|
|
|
|
ship ** sp;
|
|
|
|
|
|
|
|
|
|
a_age(&r->attribs);
|
|
|
|
|
handle_event(&r->attribs, "create", r);
|
|
|
|
|
/* Einheiten */
|
|
|
|
|
for (up=&r->units;*up;) {
|
|
|
|
|
unit * u = *up;
|
|
|
|
|
a_age(&u->attribs);
|
|
|
|
|
if (u==*up) handle_event(&u->attribs, "create", 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, "create", 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, "create", b);
|
|
|
|
|
if (b==*bp) bp = &(*bp)->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-02-22 15:42:24 +01:00
|
|
|
|
#endif
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2002-02-17 17:59:29 +01:00
|
|
|
|
#define wc(F, c) putc(c, F);
|
|
|
|
|
#define wnl(F) putc('\n', F);
|
|
|
|
|
#define whs(F, s) fputs(s, F); putc(' ', F)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
wsn(FILE * F, const char *s)
|
|
|
|
|
{
|
|
|
|
|
if (!s)
|
|
|
|
|
return;
|
|
|
|
|
while (*s)
|
|
|
|
|
wc(F, *s++);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ws(FILE * F, const char *s)
|
|
|
|
|
{
|
2002-02-15 17:13:30 +01:00
|
|
|
|
fputc('"', F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
wsn(F, s);
|
2002-02-17 17:59:29 +01:00
|
|
|
|
fputs("\" ", F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
wi(FILE * F, int n)
|
|
|
|
|
{
|
2002-02-16 11:37:18 +01:00
|
|
|
|
fprintf(F, "%d ", n);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void wi36(FILE * F, int n)
|
|
|
|
|
{
|
2002-02-16 11:37:18 +01:00
|
|
|
|
fprintf(F, "%s ", itoa36(n));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-08-26 16:16:16 +02:00
|
|
|
|
#ifdef ALLIANCES
|
|
|
|
|
void
|
|
|
|
|
write_alliances(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
alliance * al = alliances;
|
|
|
|
|
while (al) {
|
2002-09-02 22:36:12 +02:00
|
|
|
|
wi36(F, al->id);
|
2002-08-26 16:16:16 +02:00
|
|
|
|
ws(F, al->name);
|
|
|
|
|
al = al->next;
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
fprintf(F, "end");
|
2002-08-26 16:16:16 +02:00
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
void
|
|
|
|
|
write_items(FILE *F, item *ilist)
|
|
|
|
|
{
|
|
|
|
|
item * itm;
|
|
|
|
|
for (itm=ilist;itm;itm=itm->next) if (itm->number) {
|
2001-04-22 07:36:50 +02:00
|
|
|
|
whs(F, resourcename(itm->type->rtype, 0));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
wi(F, itm->number);
|
|
|
|
|
}
|
2002-02-24 14:06:05 +01:00
|
|
|
|
fputs("end ", F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#ifdef USE_UGROUPS
|
|
|
|
|
void
|
|
|
|
|
write_ugroups(FILE *file)
|
|
|
|
|
{
|
|
|
|
|
faction *f;
|
|
|
|
|
ugroup *ug;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for(f=factions; f; f=f->next) if(f->ugroups) {
|
|
|
|
|
wi(file, f->no);
|
|
|
|
|
for(ug = f->ugroups; ug; ug=ug->next) {
|
|
|
|
|
wi(file, ug->id);
|
|
|
|
|
wi(file, ug->members);
|
|
|
|
|
for(i=0; i<ug->members; i++) {
|
2002-02-16 11:37:18 +01:00
|
|
|
|
wi36(file, ug->unit_array[i]->no);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fputs("-1\n", file);
|
|
|
|
|
}
|
|
|
|
|
fputs("-1\n", file);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef USE_PLAYERS
|
2001-04-26 19:41:06 +02:00
|
|
|
|
static void
|
|
|
|
|
export_players(const char * path)
|
|
|
|
|
{
|
|
|
|
|
FILE * F;
|
|
|
|
|
player * p = get_players();
|
|
|
|
|
if (p==NULL) return;
|
|
|
|
|
|
|
|
|
|
F = cfopen(path, "w");
|
|
|
|
|
if (F==NULL) return;
|
|
|
|
|
|
|
|
|
|
fputs("name;email;passwd;faction;info\n", F);
|
|
|
|
|
while (p) {
|
|
|
|
|
/* name */
|
|
|
|
|
fputc('\"', F);
|
2001-09-05 21:40:40 +02:00
|
|
|
|
if (p->name) fputs(p->name, F);
|
2001-04-26 19:41:06 +02:00
|
|
|
|
|
|
|
|
|
/* email */
|
|
|
|
|
fputs("\";\"", F);
|
|
|
|
|
if (p->email) fputs(p->email, F);
|
2001-09-05 21:40:40 +02:00
|
|
|
|
else if (p->faction) fputs(p->faction->email, F);
|
2001-04-26 19:41:06 +02:00
|
|
|
|
fputs("\";\"", F);
|
|
|
|
|
|
|
|
|
|
/* passwd */
|
|
|
|
|
fputs("\";\"", F);
|
|
|
|
|
if (p->faction) fputs(p->faction->passw, F);
|
|
|
|
|
|
|
|
|
|
/* faction */
|
|
|
|
|
fputs("\";\"", F);
|
|
|
|
|
if (p->faction) fputs(itoa36(p->faction->no), F);
|
|
|
|
|
|
|
|
|
|
/* info */
|
|
|
|
|
fputs("\";\"", F);
|
|
|
|
|
if (p->info) fputs(p->info, F);
|
2001-09-05 21:40:40 +02:00
|
|
|
|
else if (p->faction) fputs(p->faction->banner, F);
|
2001-04-26 19:41:06 +02:00
|
|
|
|
|
|
|
|
|
fputs("\"\n", F);
|
|
|
|
|
|
|
|
|
|
p = next_player(p);
|
|
|
|
|
}
|
|
|
|
|
fclose(F);
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2001-04-26 19:41:06 +02:00
|
|
|
|
|
2003-12-28 11:54:47 +01:00
|
|
|
|
int
|
2003-12-14 20:17:59 +01:00
|
|
|
|
writegame(const char *filename, char quiet)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-01-11 11:05:03 +01:00
|
|
|
|
char *base;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
int i,n;
|
|
|
|
|
faction *f;
|
|
|
|
|
region *r;
|
|
|
|
|
building *b;
|
|
|
|
|
ship *sh;
|
|
|
|
|
unit *u;
|
|
|
|
|
plane *pl;
|
|
|
|
|
FILE * F;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#ifdef USE_PLAYERS
|
2001-04-26 19:41:06 +02:00
|
|
|
|
char playerfile[MAX_PATH];
|
2002-11-03 09:39:04 +01:00
|
|
|
|
#endif
|
2001-04-26 19:41:06 +02:00
|
|
|
|
|
2002-11-03 09:39:04 +01:00
|
|
|
|
#ifdef USE_PLAYERS
|
2001-04-26 19:41:06 +02:00
|
|
|
|
sprintf(buf, "%s/%d.players", datapath(), turn);
|
|
|
|
|
export_players(playerfile);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#endif
|
2002-11-03 09:39:04 +01:00
|
|
|
|
|
2002-03-29 05:23:51 +01:00
|
|
|
|
/* write_dynamictypes(); */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2003-12-28 11:58:26 +01:00
|
|
|
|
sprintf(buf, "%s/%s", datapath(), filename);
|
|
|
|
|
F = cfopen(buf, "w");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (F==NULL)
|
2003-12-28 11:54:47 +01:00
|
|
|
|
return -1;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
if (!quiet)
|
|
|
|
|
printf("Schreibe die %d. Runde...\n", turn);
|
|
|
|
|
|
|
|
|
|
/* globale Variablen */
|
|
|
|
|
|
|
|
|
|
wi(F, RELEASE_VERSION);
|
|
|
|
|
wnl(F);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
|
2004-01-11 11:05:03 +01:00
|
|
|
|
base = strrchr(xmlfile, '/');
|
|
|
|
|
if(base) {
|
|
|
|
|
ws(F, base+1);
|
|
|
|
|
} else {
|
|
|
|
|
ws(F, xmlfile);
|
|
|
|
|
}
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
a_write(F, global.attribs);
|
2001-01-27 19:15:52 +01:00
|
|
|
|
wnl(F);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
wi(F, turn);
|
2002-11-02 15:10:52 +01:00
|
|
|
|
wi(F, 0/*max_unique_id*/);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
wi(F, nextborder);
|
|
|
|
|
|
|
|
|
|
/* Write planes */
|
|
|
|
|
wnl(F);
|
|
|
|
|
wi(F, listlen(planes));
|
2001-01-28 09:01:52 +01:00
|
|
|
|
wnl(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
for(pl = planes; pl; pl=pl->next) {
|
2002-02-18 22:41:11 +01:00
|
|
|
|
watcher * w;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
wi(F, pl->id);
|
|
|
|
|
ws(F, pl->name);
|
|
|
|
|
wi(F, pl->minx);
|
|
|
|
|
wi(F, pl->maxx);
|
|
|
|
|
wi(F, pl->miny);
|
|
|
|
|
wi(F, pl->maxy);
|
|
|
|
|
wi(F, pl->flags);
|
2002-02-18 22:41:11 +01:00
|
|
|
|
w = pl->watchers;
|
|
|
|
|
while (w) {
|
|
|
|
|
if (w->faction) {
|
|
|
|
|
wi36(F, w->faction->no);
|
|
|
|
|
wi(F, w->mode);
|
|
|
|
|
}
|
|
|
|
|
w = w->next;
|
|
|
|
|
}
|
2002-02-24 14:06:05 +01:00
|
|
|
|
fputs("end ", F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
a_write(F, pl->attribs);
|
2001-01-28 09:01:52 +01:00
|
|
|
|
wnl(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Write factions */
|
2002-08-26 16:16:16 +02:00
|
|
|
|
#if defined(ALLIANCES) && RELEASE_VERSION>=ALLIANCES_VERSION
|
|
|
|
|
write_alliances(F);
|
|
|
|
|
#endif
|
2001-01-25 10:37:55 +01:00
|
|
|
|
n=listlen(factions);
|
|
|
|
|
wi(F, n);
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
printf(" - Schreibe %d Parteien...\n",n);
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
writefaction(F, f);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wi(F, no_used_faction_ids);
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
for(i=0; i<no_used_faction_ids; i++) {
|
|
|
|
|
wi(F, used_faction_ids[i]);
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
/* Write regions */
|
|
|
|
|
|
|
|
|
|
n=listlen(regions);
|
|
|
|
|
wi(F, n);
|
|
|
|
|
wnl(F);
|
|
|
|
|
printf(" - Schreibe Regionen: %d \r", n);
|
|
|
|
|
|
|
|
|
|
for (r = regions; r; r = r->next, --n) {
|
|
|
|
|
/* plus leerzeile */
|
|
|
|
|
if ((n%1024)==0) { /* das spart extrem Zeit */
|
|
|
|
|
printf(" - Schreibe Regionen: %d \r", n);
|
2001-02-10 16:27:10 +01:00
|
|
|
|
fflush(stdout);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
wnl(F);
|
|
|
|
|
wi(F, r->x);
|
|
|
|
|
wi(F, r->y);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
writeregion(F, r);
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
wi(F, listlen(r->buildings));
|
|
|
|
|
wnl(F);
|
|
|
|
|
for (b = r->buildings; b; b = b->next) {
|
2002-02-16 11:37:18 +01:00
|
|
|
|
wi36(F, b->no);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
ws(F, b->name);
|
|
|
|
|
ws(F, b->display);
|
|
|
|
|
wi(F, b->size);
|
|
|
|
|
ws(F, b->type->_name);
|
|
|
|
|
wnl(F);
|
|
|
|
|
a_write(F, b->attribs);
|
2001-01-28 09:01:52 +01:00
|
|
|
|
wnl(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wi(F, listlen(r->ships));
|
|
|
|
|
wnl(F);
|
|
|
|
|
for (sh = r->ships; sh; sh = sh->next) {
|
2001-02-18 11:06:10 +01:00
|
|
|
|
assert(sh->region == r);
|
2002-02-16 11:37:18 +01:00
|
|
|
|
wi36(F, sh->no);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
ws(F, sh->name);
|
|
|
|
|
ws(F, sh->display);
|
|
|
|
|
ws(F, sh->type->name[0]);
|
|
|
|
|
wi(F, sh->size);
|
|
|
|
|
wi(F, sh->damage);
|
|
|
|
|
wi(F, sh->coast);
|
|
|
|
|
wnl(F);
|
|
|
|
|
a_write(F, sh->attribs);
|
2001-01-28 09:01:52 +01:00
|
|
|
|
wnl(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wi(F, listlen(r->units));
|
|
|
|
|
wnl(F);
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
writeunit(F, u);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wnl(F);
|
|
|
|
|
write_borders(F);
|
2001-01-28 09:01:52 +01:00
|
|
|
|
wnl(F);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#if RELEASE_VERSION >= UGROUPS_VERSION
|
|
|
|
|
write_ugroups(F);
|
|
|
|
|
wnl(F);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#endif
|
|
|
|
|
fclose(F);
|
|
|
|
|
printf("\nOk.\n");
|
2003-12-28 11:54:47 +01:00
|
|
|
|
return 0;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
struct fjord { int size; faction * f; } fjord[3];
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
lastturn(void)
|
|
|
|
|
{
|
|
|
|
|
int turn = 0;
|
|
|
|
|
#ifdef HAVE_READDIR
|
|
|
|
|
DIR *data_dir = NULL;
|
|
|
|
|
struct dirent *entry = NULL;
|
|
|
|
|
const char * dir = datapath();
|
|
|
|
|
data_dir = opendir(dir);
|
|
|
|
|
if (data_dir != NULL) {
|
|
|
|
|
entry = readdir(data_dir);
|
|
|
|
|
}
|
|
|
|
|
if (data_dir != NULL && entry != NULL) {
|
|
|
|
|
turn = 0;
|
|
|
|
|
do {
|
|
|
|
|
int i = atoi(entry->d_name);
|
|
|
|
|
if (i > turn)
|
|
|
|
|
turn = i;
|
|
|
|
|
entry = readdir(data_dir);
|
|
|
|
|
} while (entry != NULL);
|
|
|
|
|
#ifdef HAVE_CLOSEDIR
|
|
|
|
|
closedir(data_dir);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
# error "requires dirent.h or an equivalent to compile!"
|
|
|
|
|
#endif
|
|
|
|
|
return turn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
read_faction_reference(faction ** f, FILE * F)
|
|
|
|
|
{
|
|
|
|
|
int id;
|
|
|
|
|
if (global.data_version >= BASE36IDS_VERSION) {
|
|
|
|
|
char zText[10];
|
|
|
|
|
fscanf(F, "%s ", zText);
|
|
|
|
|
id = atoi36(zText);
|
|
|
|
|
} else {
|
|
|
|
|
fscanf(F, "%d ", &id);
|
|
|
|
|
}
|
2002-04-07 02:44:01 +02:00
|
|
|
|
if (id<0) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
*f = NULL;
|
2002-04-07 02:44:01 +02:00
|
|
|
|
return AT_READ_FAIL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
*f = findfaction(id);
|
|
|
|
|
if (*f==NULL) ur_add((void*)id, (void**)f, resolve_faction);
|
2002-04-07 02:44:01 +02:00
|
|
|
|
return AT_READ_OK;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2001-09-05 21:40:40 +02:00
|
|
|
|
void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
write_faction_reference(const faction * f, FILE * F)
|
|
|
|
|
{
|
|
|
|
|
fprintf(F, "%s ", itoa36(f->no));
|
|
|
|
|
}
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
|
|
|
|
unit *
|
|
|
|
|
readunit(FILE * F)
|
|
|
|
|
{
|
|
|
|
|
skill_t sk;
|
|
|
|
|
item_t item;
|
|
|
|
|
herb_t herb;
|
|
|
|
|
potion_t potion;
|
|
|
|
|
unit * u;
|
|
|
|
|
int number, n;
|
|
|
|
|
|
|
|
|
|
n = rid(F);
|
|
|
|
|
u = findunit(n);
|
|
|
|
|
if (u==NULL) {
|
|
|
|
|
u = calloc(sizeof(unit), 1);
|
|
|
|
|
u->no = n;
|
|
|
|
|
uhash(u);
|
|
|
|
|
} else {
|
|
|
|
|
while (u->attribs) a_remove(&u->attribs, u->attribs);
|
|
|
|
|
while (u->items) i_free(i_remove(&u->items, u->items));
|
|
|
|
|
free(u->skills);
|
|
|
|
|
u->skills = 0;
|
|
|
|
|
u->skill_size = 0;
|
|
|
|
|
u_setfaction(u, NULL);
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
{
|
2002-03-03 16:16:28 +01:00
|
|
|
|
faction * f;
|
2002-09-02 22:36:12 +02:00
|
|
|
|
int n = rid(F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
f = findfaction(n);
|
|
|
|
|
if (f!=u->faction) u_setfaction(u, f);
|
|
|
|
|
}
|
|
|
|
|
rds(F, &u->name);
|
|
|
|
|
rds(F, &u->display);
|
|
|
|
|
number = ri(F);
|
|
|
|
|
if (global.data_version<ITEMTYPE_VERSION)
|
|
|
|
|
set_money(u, ri(F));
|
|
|
|
|
u->age = (short)ri(F);
|
|
|
|
|
if (global.data_version<NEWRACE_VERSION) {
|
|
|
|
|
u->race = new_race[(race_t)ri(F)];
|
|
|
|
|
u->irace = new_race[(race_t)ri(F)];
|
|
|
|
|
} else {
|
|
|
|
|
rs(F, buf);
|
2002-03-22 10:33:46 +01:00
|
|
|
|
if (strcmp(buf, "giant turtle")==0) strcpy(buf, "giantturtle");
|
2002-03-03 16:16:28 +01:00
|
|
|
|
u->race = rc_find(buf);
|
2002-03-22 10:33:46 +01:00
|
|
|
|
assert(u->race);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
rs(F, buf);
|
|
|
|
|
if (strlen(buf)) u->irace = rc_find(buf);
|
|
|
|
|
else u->irace = u->race;
|
|
|
|
|
}
|
|
|
|
|
if (u->faction == NULL) {
|
|
|
|
|
log_error(("unit %s has faction == NULL\n", unitname(u)));
|
2002-05-23 09:19:54 +02:00
|
|
|
|
#if 0
|
2002-03-03 16:16:28 +01:00
|
|
|
|
abort();
|
2002-05-23 09:19:54 +02:00
|
|
|
|
#else
|
|
|
|
|
u_setfaction(u, findfaction(MONSTER_FACTION));
|
|
|
|
|
set_number(u, 0);
|
|
|
|
|
#endif
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
|
|
|
|
if (playerrace(u->race)) {
|
|
|
|
|
u->faction->no_units++;
|
|
|
|
|
}
|
|
|
|
|
set_number(u, number);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
u->building = findbuilding(rid(F));
|
|
|
|
|
u->ship = findship(rid(F));
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
|
|
|
|
if (global.data_version <= 73) {
|
|
|
|
|
if (ri(F)) {
|
2003-07-29 11:48:03 +02:00
|
|
|
|
fset(u, UFL_OWNER);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
} else {
|
2003-07-29 11:48:03 +02:00
|
|
|
|
freset(u, UFL_OWNER);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
u->status = (status_t) ri(F);
|
|
|
|
|
if (global.data_version < NEWSTATUS_VERSION) {
|
|
|
|
|
switch (u->status) {
|
|
|
|
|
case 0: u->status = ST_FIGHT; break;
|
|
|
|
|
case 1: u->status = ST_BEHIND; break;
|
|
|
|
|
case 2: u->status = ST_AVOID; break;
|
|
|
|
|
case 3: u->status = ST_FLEE; break;
|
|
|
|
|
default: assert(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (global.data_version <= 73) {
|
|
|
|
|
if (ri(F)) {
|
|
|
|
|
guard(u, GUARD_ALL);
|
|
|
|
|
} else {
|
|
|
|
|
guard(u, GUARD_NONE);
|
|
|
|
|
}
|
|
|
|
|
} else
|
2002-03-11 22:20:31 +01:00
|
|
|
|
u->flags = ri(F) & ~UFL_DEBUG;
|
2002-03-03 16:16:28 +01:00
|
|
|
|
/* Kurze persistente Befehle einlesen */
|
|
|
|
|
if (u->orders) {
|
|
|
|
|
freestrlist(u->orders);
|
|
|
|
|
u->orders = NULL;
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
rs(F, buf);
|
|
|
|
|
while(*buf != 0) {
|
|
|
|
|
strlist *S = makestrlist(buf);
|
|
|
|
|
addlist(&u->orders,S);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
rs(F, buf);
|
|
|
|
|
}
|
|
|
|
|
rds(F, &u->lastorder);
|
|
|
|
|
set_string(&u->thisorder, "");
|
|
|
|
|
if (global.data_version < EFFSTEALTH_VERSION)
|
|
|
|
|
u_seteffstealth(u, ri(F));
|
|
|
|
|
|
|
|
|
|
assert(u->number >= 0);
|
|
|
|
|
assert(u->race);
|
|
|
|
|
if (global.data_version<NEWSKILL_VERSION) {
|
|
|
|
|
/* convert old data */
|
|
|
|
|
while ((sk = (skill_t) ri(F)) != NOSKILL) {
|
|
|
|
|
int days = ri(F) / u->number;
|
|
|
|
|
int lvl = level(days);
|
|
|
|
|
int weeks = lvl + 1 - (days - level_days(lvl))/30;
|
|
|
|
|
assert(weeks>0 && weeks<=lvl+1);
|
|
|
|
|
if (lvl) {
|
|
|
|
|
skill * sv = add_skill(u, sk);
|
|
|
|
|
sv->level = sv->old = (unsigned char)lvl;
|
|
|
|
|
sv->weeks = (unsigned char)weeks;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
while ((sk = (skill_t) ri(F)) != NOSKILL) {
|
|
|
|
|
int level = ri(F);
|
|
|
|
|
int weeks = ri(F);
|
|
|
|
|
if (level) {
|
|
|
|
|
skill * sv = add_skill(u, sk);
|
|
|
|
|
sv->level = sv->old = (unsigned char)level;
|
|
|
|
|
sv->weeks = (unsigned char)weeks;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (global.data_version>=ITEMTYPE_VERSION) {
|
|
|
|
|
read_items(F, &u->items);
|
|
|
|
|
} else {
|
|
|
|
|
while ((item = (item_t) ri(F)) >= 0) {
|
|
|
|
|
i_change(&u->items, olditemtype[item], ri(F));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while ((potion = (potion_t) ri(F)) >= 0) {
|
|
|
|
|
i_change(&u->items, oldpotiontype[potion]->itype, ri(F));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while ((herb = (herb_t) ri(F)) >= 0) {
|
|
|
|
|
i_change(&u->items, oldherbtype[herb]->itype, ri(F));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
u->hp = ri(F);
|
2002-10-20 10:57:37 +02:00
|
|
|
|
if (u->hp < u->number) {
|
|
|
|
|
log_error(("Einheit %s hat %u Personen, und %u Trefferpunkte\n", itoa36(u->no),
|
|
|
|
|
u->number, u->hp));
|
|
|
|
|
u->hp=u->number;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-03 16:16:28 +01:00
|
|
|
|
if (global.data_version < MAGE_ATTRIB_VERSION) {
|
2002-09-02 22:36:12 +02:00
|
|
|
|
int i = ri(F);
|
|
|
|
|
if (i != -1){
|
|
|
|
|
attrib * a;
|
|
|
|
|
int csp = 0;
|
|
|
|
|
|
|
|
|
|
sc_mage * mage = calloc(1, sizeof(sc_mage));
|
|
|
|
|
mage->magietyp = (magic_t) i;
|
|
|
|
|
mage->spellpoints = ri(F);
|
|
|
|
|
mage->spchange = ri(F);
|
|
|
|
|
while ((i = ri(F)) != -1) {
|
|
|
|
|
mage->combatspell[csp] = (spellid_t) i;
|
|
|
|
|
mage->combatspelllevel[csp] = ri(F);
|
|
|
|
|
csp++;
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
while ((i = ri(F)) != -1) {
|
|
|
|
|
addspell(u, (spellid_t) i);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
mage->spellcount = 0;
|
|
|
|
|
a = a_add(&u->attribs, a_new(&at_mage));
|
|
|
|
|
a->data.v = mage;
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a_read(F, &u->attribs);
|
|
|
|
|
return u;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
writeunit(FILE * F, const unit * u)
|
|
|
|
|
{
|
|
|
|
|
strlist *S;
|
|
|
|
|
int i;
|
|
|
|
|
wi36(F, u->no);
|
|
|
|
|
wi36(F, u->faction->no);
|
|
|
|
|
ws(F, u->name);
|
|
|
|
|
ws(F, u->display);
|
|
|
|
|
wi(F, u->number);
|
|
|
|
|
wi(F, u->age);
|
|
|
|
|
ws(F, u->race->_name[0]);
|
|
|
|
|
ws(F, u->irace!=u->race?u->irace->_name[0]:"");
|
|
|
|
|
if (u->building)
|
|
|
|
|
wi36(F, u->building->no);
|
|
|
|
|
else
|
|
|
|
|
wi(F, 0);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
if (u->ship) wi36(F, u->ship->no);
|
|
|
|
|
else wi36(F, 0);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
wi(F, u->status);
|
|
|
|
|
wi(F, u->flags & UFL_SAVEMASK);
|
|
|
|
|
for(S=u->orders; S; S=S->next) {
|
|
|
|
|
if (is_persistent(S->s, u->faction->locale)) {
|
|
|
|
|
ws(F, S->s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ws(F, ""); /* Abschlu<6C> der persistenten Befehle */
|
|
|
|
|
ws(F, u->lastorder);
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
assert(u->number >= 0);
|
|
|
|
|
#ifdef MONEY_BUG
|
|
|
|
|
if (get_money(u) < 0)
|
|
|
|
|
printf("Einheit %s hat %d silber", unitname(u), get_money(u));
|
|
|
|
|
#else
|
|
|
|
|
assert(u->race);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
for (i=0;i!=u->skill_size;++i) {
|
|
|
|
|
skill * sv = u->skills+i;
|
2002-03-03 16:26:17 +01:00
|
|
|
|
assert(sv->weeks<=sv->level*2+1);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
if (sv->level>0) {
|
|
|
|
|
wi(F, sv->id);
|
|
|
|
|
wi(F, sv->level);
|
|
|
|
|
wi(F, sv->weeks);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wi(F, -1);
|
|
|
|
|
wnl(F);
|
|
|
|
|
write_items(F, u->items);
|
|
|
|
|
wnl(F);
|
|
|
|
|
if (u->hp == 0) {
|
|
|
|
|
log_error(("Einheit %s hat 0 Trefferpunkte\n", itoa36(u->no)));
|
|
|
|
|
((unit*)u)->hp = 1;
|
|
|
|
|
}
|
|
|
|
|
wi(F, u->hp);
|
|
|
|
|
wnl(F);
|
|
|
|
|
a_write(F, u->attribs);
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
region *
|
|
|
|
|
readregion(FILE * F, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
region * r = findregion(x, y);
|
|
|
|
|
int ter;
|
|
|
|
|
|
|
|
|
|
if (r==NULL) {
|
|
|
|
|
r = new_region(x, y);
|
|
|
|
|
} else {
|
|
|
|
|
current_region = r;
|
|
|
|
|
while (r->attribs) a_remove(&r->attribs, r->attribs);
|
|
|
|
|
if (r->land) {
|
|
|
|
|
free(r->land); /* mem leak */
|
2002-03-03 16:26:17 +01:00
|
|
|
|
r->land->demands = 0; /* mem leak */
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
|
|
|
|
while (r->resources) {
|
|
|
|
|
rawmaterial * rm = r->resources;
|
|
|
|
|
r->resources = rm->next;
|
|
|
|
|
free(rm);
|
|
|
|
|
}
|
|
|
|
|
r->land = 0;
|
|
|
|
|
}
|
|
|
|
|
rds(F, &r->display);
|
|
|
|
|
ter = ri(F);
|
|
|
|
|
if (global.data_version < NOFOREST_VERSION) {
|
|
|
|
|
if (ter>T_PLAIN) --ter;
|
|
|
|
|
}
|
|
|
|
|
rsetterrain(r, (terrain_t)ter);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
r->flags = (char) ri(F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
|
|
|
|
if (global.data_version >= REGIONAGE_VERSION)
|
|
|
|
|
r->age = (unsigned short) ri(F);
|
|
|
|
|
else
|
|
|
|
|
r->age = 0;
|
|
|
|
|
|
2002-09-02 22:36:12 +02:00
|
|
|
|
if (landregion(rterrain(r))) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
r->land = calloc(1, sizeof(land_region));
|
|
|
|
|
rds(F, &r->land->name);
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
if (r->land) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
int i;
|
|
|
|
|
#if GROWING_TREES
|
|
|
|
|
if(global.data_version < GROWTREE_VERSION) {
|
|
|
|
|
i = ri(F); rsettrees(r, 2, i);
|
|
|
|
|
} else {
|
2002-12-14 15:25:37 +01:00
|
|
|
|
i = ri(F);
|
|
|
|
|
if (i<0) {
|
|
|
|
|
log_error(("number of trees in %s is %d.\n",
|
|
|
|
|
regionname(r, NULL), i));
|
|
|
|
|
i=0;
|
|
|
|
|
}
|
|
|
|
|
rsettrees(r, 0, i);
|
|
|
|
|
i = ri(F);
|
|
|
|
|
if (i<0) {
|
|
|
|
|
log_error(("number of young trees in %s is %d.\n",
|
|
|
|
|
regionname(r, NULL), i));
|
|
|
|
|
i=0;
|
|
|
|
|
}
|
|
|
|
|
rsettrees(r, 1, i);
|
|
|
|
|
i = ri(F);
|
|
|
|
|
if (i<0) {
|
|
|
|
|
log_error(("number of seeds in %s is %d.\n",
|
|
|
|
|
regionname(r, NULL), i));
|
|
|
|
|
i=0;
|
|
|
|
|
}
|
|
|
|
|
rsettrees(r, 2, i);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
i = ri(F); rsettrees(r, i);
|
|
|
|
|
#endif
|
|
|
|
|
i = ri(F); rsethorses(r, i);
|
|
|
|
|
#if NEW_RESOURCEGROWTH
|
|
|
|
|
if (global.data_version < NEWRESOURCE_VERSION) {
|
2002-05-02 23:19:45 +02:00
|
|
|
|
i = ri(F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
#if RESOURCE_CONVERSION
|
|
|
|
|
if (i!=0) read_iron(r, i);
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
rawmaterial ** pres = &r->resources;
|
|
|
|
|
assert(*pres==NULL);
|
|
|
|
|
for (;;) {
|
|
|
|
|
rawmaterial * res;
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
if (strcmp(buf, "end")==0) break;
|
|
|
|
|
res = calloc(sizeof(rawmaterial), 1);
|
|
|
|
|
res->type = rmt_find(buf);
|
|
|
|
|
assert(res->type!=NULL);
|
|
|
|
|
res->level = ri(F);
|
|
|
|
|
res->amount = ri(F);
|
|
|
|
|
|
|
|
|
|
if(global.data_version >= RANDOMIZED_RESOURCES_VERSION) {
|
|
|
|
|
res->startlevel = ri(F);
|
|
|
|
|
res->base = ri(F);
|
|
|
|
|
res->divisor = ri(F);
|
|
|
|
|
} else {
|
|
|
|
|
int i;
|
|
|
|
|
res->startlevel = 1;
|
|
|
|
|
for (i=0; i<3; i++) {
|
|
|
|
|
if(res->type == terrain[rterrain(r)].rawmaterials[i].type) break;
|
|
|
|
|
}
|
|
|
|
|
assert(i<=2);
|
|
|
|
|
res->base = dice_rand(terrain[rterrain(r)].rawmaterials[i].base);
|
|
|
|
|
res->divisor = dice_rand(terrain[rterrain(r)].rawmaterials[i].divisor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pres = res;
|
|
|
|
|
pres=&res->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
i = ri(F); rsetiron(r, i);
|
|
|
|
|
#endif
|
|
|
|
|
if (global.data_version>=ITEMTYPE_VERSION) {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
if (strcmp(buf, "noherb") != 0) {
|
|
|
|
|
rsetherbtype(r, ht_find(buf));
|
|
|
|
|
} else {
|
|
|
|
|
rsetherbtype(r, NULL);
|
|
|
|
|
}
|
|
|
|
|
rsetherbs(r, (short)ri(F));
|
2002-09-02 22:36:12 +02:00
|
|
|
|
} else {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
int i = ri(F);
|
|
|
|
|
terrain_t ter = rterrain(r);
|
|
|
|
|
if (ter == T_ICEBERG || ter == T_ICEBERG_SLEEP) ter = T_GLACIER;
|
|
|
|
|
if (ter > T_GLACIER || ter == T_OCEAN)
|
|
|
|
|
rsetherbtype(r, NULL);
|
|
|
|
|
else
|
|
|
|
|
rsetherbtype(r, oldherbtype[(i-1)+3*(ter-1)]);
|
|
|
|
|
rsetherbs(r, (short)ri(F));
|
|
|
|
|
}
|
|
|
|
|
rsetpeasants(r, ri(F));
|
|
|
|
|
rsetmoney(r, ri(F));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(rterrain(r) != NOTERRAIN);
|
|
|
|
|
assert(rhorses(r) >= 0);
|
|
|
|
|
assert(rpeasants(r) >= 0);
|
|
|
|
|
assert(rmoney(r) >= 0);
|
|
|
|
|
|
2002-09-02 22:36:12 +02:00
|
|
|
|
if (r->land) {
|
2002-03-03 16:16:28 +01:00
|
|
|
|
if (global.data_version<ITEMTYPE_VERSION) {
|
|
|
|
|
int i, p = 0;
|
|
|
|
|
for (i = 0; oldluxurytype[i]!=NULL; i++) {
|
|
|
|
|
int k = ri(F);
|
|
|
|
|
r_setdemand(r, oldluxurytype[i], k);
|
|
|
|
|
if (k==0) {
|
|
|
|
|
/* Pr<50>fung ob nur ein Luxusgut verkauft wird. */
|
|
|
|
|
if (p == 1) {
|
|
|
|
|
/* Zuviele ... Wir setzen den Demand. */
|
|
|
|
|
r_setdemand(r, oldluxurytype[i], (char) (1 + rand() % 5));
|
|
|
|
|
} else ++p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (;;) {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
if (!strcmp(buf, "end")) break;
|
|
|
|
|
r_setdemand(r, lt_find(buf), ri(F));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a_read(F, &r->attribs);
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
writeregion(FILE * F, const region * r)
|
|
|
|
|
{
|
|
|
|
|
ws(F, r->display);
|
|
|
|
|
wi(F, rterrain(r));
|
|
|
|
|
wi(F, r->flags & RF_SAVEMASK);
|
|
|
|
|
wi(F, r->age);
|
|
|
|
|
wnl(F);
|
|
|
|
|
if (landregion(rterrain(r))) {
|
|
|
|
|
const herb_type *rht;
|
|
|
|
|
struct demand * demand;
|
|
|
|
|
ws(F, r->land->name);
|
|
|
|
|
#if GROWING_TREES
|
2002-12-14 15:25:37 +01:00
|
|
|
|
assert(rtrees(r,0)>=0);
|
|
|
|
|
assert(rtrees(r,1)>=0);
|
|
|
|
|
assert(rtrees(r,2)>=0);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
wi(F, rtrees(r,0));
|
|
|
|
|
wi(F, rtrees(r,1));
|
|
|
|
|
wi(F, rtrees(r,2));
|
|
|
|
|
#else
|
|
|
|
|
wi(F, rtrees(r));
|
|
|
|
|
#endif
|
|
|
|
|
wi(F, rhorses(r));
|
|
|
|
|
#if NEW_RESOURCEGROWTH == 0
|
|
|
|
|
wi(F, riron(r));
|
|
|
|
|
#elif RELEASE_VERSION>=NEWRESOURCE_VERSION
|
|
|
|
|
{
|
|
|
|
|
rawmaterial * res = r->resources;
|
|
|
|
|
while (res) {
|
|
|
|
|
ws(F, res->type->name);
|
|
|
|
|
wi(F, res->level);
|
|
|
|
|
wi(F, res->amount);
|
|
|
|
|
wi(F, res->startlevel);
|
|
|
|
|
wi(F, res->base);
|
|
|
|
|
wi(F, res->divisor);
|
|
|
|
|
res = res->next;
|
|
|
|
|
}
|
|
|
|
|
fputs("end ", F);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
assert(!"invalid defines");
|
|
|
|
|
#endif
|
|
|
|
|
rht = rherbtype(r);
|
|
|
|
|
if (rht) {
|
|
|
|
|
ws(F, resourcename(rht->itype->rtype, 0));
|
|
|
|
|
} else {
|
|
|
|
|
ws(F, "noherb");
|
|
|
|
|
}
|
|
|
|
|
wi(F, rherbs(r));
|
|
|
|
|
wi(F, rpeasants(r));
|
|
|
|
|
wi(F, rmoney(r));
|
|
|
|
|
if (r->land) for (demand=r->land->demands; demand; demand=demand->next) {
|
|
|
|
|
ws(F, resourcename(demand->type->itype->rtype, 0));
|
|
|
|
|
wi(F, demand->value);
|
|
|
|
|
}
|
|
|
|
|
fputs("end\n", F);
|
|
|
|
|
}
|
|
|
|
|
a_write(F, r->attribs);
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-02 22:36:12 +02:00
|
|
|
|
static void
|
|
|
|
|
addally(const faction * f, ally ** sfp, int aid, int state)
|
|
|
|
|
{
|
|
|
|
|
struct faction * af = findfaction(aid);
|
|
|
|
|
ally * sf;
|
|
|
|
|
state &= ~HELP_OBSERVE;
|
magicskillboost
-- implementiert. Kann nur einmal pro Partei verwendet werden, und nur von einem Magier. Müssen wir erklären.
Amulett des wahren Sehens und Ring der Unsichtbarkeit geben lediglich einen Bonus auf Wahrnehmung (+2) und Tarnung (+4).
-- das define war nicht aktiviert
Halblinge haben Armbrustschiessen +0 (statt +1).
-- spearates Rassenfile für WDW
Es gibt spezielle Regeln für Allianzen, und der HELFE und KONTAKTIERE Befehl sind eingeschränkt. Konkret kann kein HELP_FIGHT HELP_GUARD HELP_FSTEALTH HELP_MONEY gegeben werden (die anderen sind erlaubt).
-- mit #defeine ALLIES_ONLY definiert
Jede Allianz kann bis zu 15 Magier und 15 Alchemisten haben. Jede einzelne Partei der Allianz kann dabei nicht mehr als 15/Anzahl_Parteien (aufgerundet) Magier bzw. Alchemisten haben, und die Gesamtsumme darf 15 nicht übersteigen.
-- mit #define ALLIANCE_LIMITS gemacht.
Die Startgeschenke (Personen, Silber, ...) werden pro Allianz, nicht pro Spieler verteilt. Größere Allianzen bekommen also weniger pro Spieler.
-- Nochmal geändert: Die Allianzen kriegen jede 168 Personen zum Start, weil sich das gut aufteilen lässt. Das wird auf 28 Einheiten pro Partei gesplittet, jede Einheit hat eines der Talente, außer der Starteinheit, die hat den magicskillboost. Einige Skills kommen öfter vor als andere, das ist nicht einfach vermeidbar. Sollte aber auch wurscht sein, es geht primär darum, lehren zu können.
Es gibt ein Einheitenlimit von 1000 Einheiten pro Allianz.
-- die Regel sparen wir uns einfach mal.
2003-12-14 22:45:47 +01:00
|
|
|
|
#ifndef REGIONOWNERS
|
|
|
|
|
state &= ~HELP_TRAVEL;
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#endif
|
|
|
|
|
#ifdef ALLIANCES
|
magicskillboost
-- implementiert. Kann nur einmal pro Partei verwendet werden, und nur von einem Magier. Müssen wir erklären.
Amulett des wahren Sehens und Ring der Unsichtbarkeit geben lediglich einen Bonus auf Wahrnehmung (+2) und Tarnung (+4).
-- das define war nicht aktiviert
Halblinge haben Armbrustschiessen +0 (statt +1).
-- spearates Rassenfile für WDW
Es gibt spezielle Regeln für Allianzen, und der HELFE und KONTAKTIERE Befehl sind eingeschränkt. Konkret kann kein HELP_FIGHT HELP_GUARD HELP_FSTEALTH HELP_MONEY gegeben werden (die anderen sind erlaubt).
-- mit #defeine ALLIES_ONLY definiert
Jede Allianz kann bis zu 15 Magier und 15 Alchemisten haben. Jede einzelne Partei der Allianz kann dabei nicht mehr als 15/Anzahl_Parteien (aufgerundet) Magier bzw. Alchemisten haben, und die Gesamtsumme darf 15 nicht übersteigen.
-- mit #define ALLIANCE_LIMITS gemacht.
Die Startgeschenke (Personen, Silber, ...) werden pro Allianz, nicht pro Spieler verteilt. Größere Allianzen bekommen also weniger pro Spieler.
-- Nochmal geändert: Die Allianzen kriegen jede 168 Personen zum Start, weil sich das gut aufteilen lässt. Das wird auf 28 Einheiten pro Partei gesplittet, jede Einheit hat eines der Talente, außer der Starteinheit, die hat den magicskillboost. Einige Skills kommen öfter vor als andere, das ist nicht einfach vermeidbar. Sollte aber auch wurscht sein, es geht primär darum, lehren zu können.
Es gibt ein Einheitenlimit von 1000 Einheiten pro Allianz.
-- die Regel sparen wir uns einfach mal.
2003-12-14 22:45:47 +01:00
|
|
|
|
# ifdef ALLIES_ONLY
|
|
|
|
|
if (af!=NULL && af->alliance!=f->alliance) state &= ~ALLIES_ONLY;;
|
|
|
|
|
# else
|
|
|
|
|
# endif
|
2002-09-02 22:36:12 +02:00
|
|
|
|
if (af!=NULL && af->alliance!=f->alliance) return;
|
|
|
|
|
#endif
|
magicskillboost
-- implementiert. Kann nur einmal pro Partei verwendet werden, und nur von einem Magier. Müssen wir erklären.
Amulett des wahren Sehens und Ring der Unsichtbarkeit geben lediglich einen Bonus auf Wahrnehmung (+2) und Tarnung (+4).
-- das define war nicht aktiviert
Halblinge haben Armbrustschiessen +0 (statt +1).
-- spearates Rassenfile für WDW
Es gibt spezielle Regeln für Allianzen, und der HELFE und KONTAKTIERE Befehl sind eingeschränkt. Konkret kann kein HELP_FIGHT HELP_GUARD HELP_FSTEALTH HELP_MONEY gegeben werden (die anderen sind erlaubt).
-- mit #defeine ALLIES_ONLY definiert
Jede Allianz kann bis zu 15 Magier und 15 Alchemisten haben. Jede einzelne Partei der Allianz kann dabei nicht mehr als 15/Anzahl_Parteien (aufgerundet) Magier bzw. Alchemisten haben, und die Gesamtsumme darf 15 nicht übersteigen.
-- mit #define ALLIANCE_LIMITS gemacht.
Die Startgeschenke (Personen, Silber, ...) werden pro Allianz, nicht pro Spieler verteilt. Größere Allianzen bekommen also weniger pro Spieler.
-- Nochmal geändert: Die Allianzen kriegen jede 168 Personen zum Start, weil sich das gut aufteilen lässt. Das wird auf 28 Einheiten pro Partei gesplittet, jede Einheit hat eines der Talente, außer der Starteinheit, die hat den magicskillboost. Einige Skills kommen öfter vor als andere, das ist nicht einfach vermeidbar. Sollte aber auch wurscht sein, es geht primär darum, lehren zu können.
Es gibt ein Einheitenlimit von 1000 Einheiten pro Allianz.
-- die Regel sparen wir uns einfach mal.
2003-12-14 22:45:47 +01:00
|
|
|
|
if (state==0) return;
|
|
|
|
|
|
|
|
|
|
sf = calloc(1, sizeof(ally));
|
2002-09-02 22:36:12 +02:00
|
|
|
|
sf->faction = af;
|
|
|
|
|
if (!sf->faction) ur_add((void*)aid, (void**)&sf->faction, resolve_faction);
|
|
|
|
|
sf->status = state;
|
|
|
|
|
sf->next = *sfp;
|
|
|
|
|
|
|
|
|
|
*sfp = sf;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-03 16:16:28 +01:00
|
|
|
|
/** Reads a faction from a file.
|
|
|
|
|
* This function requires no context, can be called in any state. The
|
|
|
|
|
* faction may not already exist, however.
|
|
|
|
|
*/
|
|
|
|
|
faction *
|
|
|
|
|
readfaction(FILE * F)
|
|
|
|
|
{
|
2004-04-10 22:25:40 +02:00
|
|
|
|
ally **sfp;
|
|
|
|
|
int planes;
|
|
|
|
|
int i = rid(F);
|
|
|
|
|
faction * f = findfaction(i);
|
|
|
|
|
if (f==NULL) {
|
|
|
|
|
f = (faction *) calloc(1, sizeof(faction));
|
|
|
|
|
f->no = i;
|
|
|
|
|
} else {
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#ifdef MSG_LEVELS
|
2004-04-10 22:25:40 +02:00
|
|
|
|
f->warnings = NULL; /* mem leak */
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#endif
|
2004-04-10 22:25:40 +02:00
|
|
|
|
f->allies = NULL; /* mem leak */
|
|
|
|
|
while (f->attribs) a_remove(&f->attribs, f->attribs);
|
|
|
|
|
}
|
|
|
|
|
f->subscription = ri(F);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#ifdef ALLIANCES
|
2004-04-10 22:25:40 +02:00
|
|
|
|
if (global.data_version>=ALLIANCES_VERSION) {
|
|
|
|
|
int allianceid = rid(F);
|
|
|
|
|
if (allianceid!=0) f->alliance = findalliance(allianceid);
|
|
|
|
|
if (f->alliance) {
|
|
|
|
|
faction_list * flist = malloc(sizeof(faction_list));
|
|
|
|
|
flist->data = f;
|
|
|
|
|
flist->next = f->alliance->members;
|
|
|
|
|
f->alliance->members = flist;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#endif
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
2004-04-10 22:25:40 +02:00
|
|
|
|
rds(F, &f->name);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
|
|
|
|
#ifndef AMIGA
|
2004-04-10 22:25:40 +02:00
|
|
|
|
if (!quiet) printf(" - Lese Partei %s (%s)\n", f->name, factionid(f));
|
2002-03-03 16:16:28 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
2004-04-10 22:25:40 +02:00
|
|
|
|
rds(F, &f->banner);
|
|
|
|
|
rds(F, &f->email);
|
|
|
|
|
rds(F, &f->passw);
|
|
|
|
|
if (global.data_version >= OVERRIDE_VERSION) {
|
|
|
|
|
rds(F, &f->override);
|
|
|
|
|
} else {
|
|
|
|
|
f->override = strdup(itoa36(rand()));
|
|
|
|
|
}
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
2004-04-10 22:25:40 +02:00
|
|
|
|
if (global.data_version < LOCALE_VERSION) {
|
|
|
|
|
f->locale = find_locale("de");
|
|
|
|
|
} else {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
f->locale = find_locale(buf);
|
|
|
|
|
}
|
|
|
|
|
f->lastorders = ri(F);
|
|
|
|
|
f->age = ri(F);
|
|
|
|
|
if (global.data_version < NEWRACE_VERSION) {
|
|
|
|
|
race_t rc = (char) ri(F);
|
|
|
|
|
f->race = new_race[rc];
|
|
|
|
|
} else {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
f->race = rc_find(buf);
|
|
|
|
|
assert(f->race);
|
|
|
|
|
}
|
2002-11-02 16:50:51 +01:00
|
|
|
|
#ifdef CONVERT_DBLINK
|
2004-04-10 22:25:40 +02:00
|
|
|
|
convertunique(f);
|
2002-11-02 16:50:51 +01:00
|
|
|
|
#endif
|
2004-04-10 22:25:40 +02:00
|
|
|
|
f->magiegebiet = (magic_t)ri(F);
|
|
|
|
|
if (!playerrace(f->race)) {
|
|
|
|
|
f->lastorders = turn+1;
|
|
|
|
|
}
|
|
|
|
|
f->karma = ri(F);
|
|
|
|
|
f->flags = ri(F);
|
|
|
|
|
freset(f, FFL_OVERRIDE);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
2004-04-10 22:25:40 +02:00
|
|
|
|
a_read(F, &f->attribs);
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#ifdef MSG_LEVELS
|
2004-04-10 22:25:40 +02:00
|
|
|
|
read_msglevels(&f->warnings, F);
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#else
|
2004-04-10 22:25:40 +02:00
|
|
|
|
for (;;) {
|
|
|
|
|
int level;
|
|
|
|
|
fscanf(F, "%s", buf);
|
|
|
|
|
if (strcmp("end", buf)==0) break;
|
|
|
|
|
fscanf(F, "%d ", &level);
|
|
|
|
|
}
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#endif
|
2004-04-10 22:25:40 +02:00
|
|
|
|
planes = ri(F);
|
|
|
|
|
while(--planes >= 0) {
|
|
|
|
|
int id = ri(F);
|
|
|
|
|
int ux = ri(F);
|
|
|
|
|
int uy = ri(F);
|
|
|
|
|
set_ursprung(f, id, ux, uy);
|
|
|
|
|
}
|
|
|
|
|
f->newbies = 0;
|
|
|
|
|
|
|
|
|
|
i = f->options = ri(F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
2004-04-10 22:25:40 +02:00
|
|
|
|
if ((i & Pow(O_REPORT))==0 && (i & Pow(O_COMPUTER))==0) {
|
|
|
|
|
/* Kein Report eingestellt, Fehler */
|
|
|
|
|
f->options = f->options | Pow(O_REPORT) | Pow(O_ZUGVORLAGE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (global.data_version < TYPES_VERSION) {
|
|
|
|
|
int sk = ri(F); /* f->seenspell <20>berspringen */
|
|
|
|
|
spell_list * slist;
|
|
|
|
|
for (slist=spells;slist!=NULL;slist=slist->next) {
|
|
|
|
|
spell * sp = slist->data;
|
|
|
|
|
|
|
|
|
|
if (sp->magietyp==f->magiegebiet && sp->level<=sk) {
|
|
|
|
|
a_add(&f->attribs, a_new(&at_seenspell))->data.i = sp->id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sfp = &f->allies;
|
|
|
|
|
if (global.data_version<ALLIANCES_VERSION) {
|
|
|
|
|
int p = ri(F);
|
|
|
|
|
while (--p >= 0) {
|
|
|
|
|
int aid = rid(F);
|
|
|
|
|
int state = ri(F);
|
|
|
|
|
addally(f, sfp, aid, state);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (;;) {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
if (strcmp(buf, "end")==0) break;
|
|
|
|
|
else {
|
|
|
|
|
int aid = atoi36(buf);
|
|
|
|
|
int state = ri(F);
|
|
|
|
|
addally(f, sfp, aid, state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
read_groups(F, f);
|
2002-12-18 01:34:19 +01:00
|
|
|
|
#ifdef REGIONOWNERS
|
|
|
|
|
read_enemies(F, f);
|
|
|
|
|
#endif
|
2004-04-10 22:25:40 +02:00
|
|
|
|
return f;
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
writefaction(FILE * F, const faction * f)
|
|
|
|
|
{
|
|
|
|
|
ally *sf;
|
|
|
|
|
ursprung *ur;
|
|
|
|
|
|
|
|
|
|
wi36(F, f->no);
|
2002-11-02 15:10:52 +01:00
|
|
|
|
wi(F, f->subscription);
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#if defined(ALLIANCES) && RELEASE_VERSION>=ALLIANCES_VERSION
|
|
|
|
|
if (f->alliance) wi36(F, f->alliance->id);
|
|
|
|
|
else wi36(F, 0);
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-03-03 16:16:28 +01:00
|
|
|
|
ws(F, f->name);
|
|
|
|
|
ws(F, f->banner);
|
|
|
|
|
ws(F, f->email);
|
|
|
|
|
ws(F, f->passw);
|
|
|
|
|
ws(F, f->override);
|
|
|
|
|
ws(F, locale_name(f->locale));
|
|
|
|
|
wi(F, f->lastorders);
|
|
|
|
|
wi(F, f->age);
|
|
|
|
|
ws(F, f->race->_name[0]);
|
|
|
|
|
wnl(F);
|
|
|
|
|
wi(F, f->magiegebiet);
|
|
|
|
|
wi(F, f->karma);
|
|
|
|
|
wi(F, f->flags);
|
|
|
|
|
a_write(F, f->attribs);
|
|
|
|
|
wnl(F);
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#ifdef MSG_LEVELS
|
2002-03-03 16:16:28 +01:00
|
|
|
|
write_msglevels(f->warnings, F);
|
2004-03-28 22:53:47 +02:00
|
|
|
|
#else
|
|
|
|
|
fputs("end ", F);
|
|
|
|
|
#endif
|
|
|
|
|
wnl(F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
wi(F, listlen(f->ursprung));
|
|
|
|
|
for(ur = f->ursprung;ur;ur=ur->next) {
|
|
|
|
|
wi(F, ur->id);
|
|
|
|
|
wi(F, ur->x);
|
|
|
|
|
wi(F, ur->y);
|
|
|
|
|
}
|
|
|
|
|
wnl(F);
|
|
|
|
|
wi(F, f->options & ~Pow(O_DEBUG));
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
for (sf = f->allies; sf; sf = sf->next) {
|
|
|
|
|
int no = (sf->faction!=NULL)?sf->faction->no:0;
|
2002-09-02 22:36:12 +02:00
|
|
|
|
int status = alliedfaction(NULL, f, sf->faction, HELP_ALL);
|
|
|
|
|
if (status!=0) {
|
|
|
|
|
wi36(F, no);
|
|
|
|
|
wi(F, sf->status);
|
|
|
|
|
}
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
fprintf(F, "end");
|
2002-03-03 16:16:28 +01:00
|
|
|
|
wnl(F);
|
|
|
|
|
write_groups(F, f->groups);
|
2002-12-18 01:34:19 +01:00
|
|
|
|
#ifdef REGIONOWNERS
|
|
|
|
|
write_enemies(F, f->enemies);
|
|
|
|
|
#endif
|
2002-03-03 16:26:17 +01:00
|
|
|
|
}
|