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"
|
|
|
|
|
|
2004-06-27 18:56:01 +02:00
|
|
|
|
#include "alliance.h"
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#include "alchemy.h"
|
|
|
|
|
#include "attrib.h"
|
|
|
|
|
#include "border.h"
|
|
|
|
|
#include "building.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "faction.h"
|
|
|
|
|
#include "item.h"
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#include "karma.h"
|
|
|
|
|
#include "magic.h"
|
|
|
|
|
#include "message.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "movement.h"
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#include "objtypes.h"
|
|
|
|
|
#include "order.h"
|
|
|
|
|
#include "pathfinder.h"
|
|
|
|
|
#include "plane.h"
|
|
|
|
|
#include "race.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "region.h"
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include "resources.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "ship.h"
|
2004-06-21 18:45:27 +02:00
|
|
|
|
#include "skill.h"
|
|
|
|
|
#include "spell.h"
|
|
|
|
|
#include "unit.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "group.h"
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#ifdef USE_UGROUPS
|
|
|
|
|
#include "ugroup.h"
|
|
|
|
|
#include <attributes/ugroup.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>
|
2004-08-22 11:33:15 +02:00
|
|
|
|
#include <util/goodies.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include <resolve.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include <sql.h>
|
2004-04-12 01:56:47 +02:00
|
|
|
|
#include <rand.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#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
|
2005-07-27 13:48:16 +02:00
|
|
|
|
#define MAXORDERS 256
|
2005-07-28 15:20:36 +02:00
|
|
|
|
#define MAXPERSISTENT 128
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-04-12 01:56:47 +02:00
|
|
|
|
/* exported symbols symbols */
|
|
|
|
|
const char * xmlfile = "eressea.xml";
|
2001-01-25 10:37:55 +01:00
|
|
|
|
const char * g_datadir;
|
2004-04-12 01:56:47 +02:00
|
|
|
|
int firstx = 0, firsty = 0;
|
|
|
|
|
|
|
|
|
|
/* local symbols */
|
2001-12-10 01:13:39 +01:00
|
|
|
|
static region * current_region;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
|
2004-06-14 00:16:12 +02:00
|
|
|
|
#define rid(F) ri36(F)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-14 00:16:12 +02:00
|
|
|
|
static int nextc;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#define rc(F) (nextc = getc(F))
|
|
|
|
|
|
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;
|
|
|
|
|
|
2004-05-26 08:42:58 +02:00
|
|
|
|
#define HASHSIZE 2039
|
2002-11-02 15:10:52 +01:00
|
|
|
|
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) {
|
2004-05-31 13:50:32 +02:00
|
|
|
|
log_warning(("could not open %s.\n", zText));
|
2002-11-02 15:10:52 +01:00
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc(F);
|
|
|
|
|
|
|
|
|
|
while (nextc != '"') {
|
|
|
|
|
if (nextc == EOF) {
|
|
|
|
|
*s = 0;
|
|
|
|
|
fprintf(stderr, "Die Datei bricht vorzeitig ab.\n");
|
|
|
|
|
abort();
|
|
|
|
|
}
|
2005-06-17 20:12:58 +02:00
|
|
|
|
if (s - buffer < DISPLAYSIZE) {
|
|
|
|
|
*s++ = (char)nextc;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
rc(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc(F);
|
|
|
|
|
*s = 0;
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (ds) {
|
2005-06-17 20:12:58 +02:00
|
|
|
|
*ds = realloc(*ds, sizeof(char) * (strlen(buffer) + 1));
|
2005-04-23 11:47:03 +02:00
|
|
|
|
strcpy(*ds, buffer);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#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
|
2004-07-02 07:41:47 +02:00
|
|
|
|
static 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;
|
2004-07-02 07:41:47 +02:00
|
|
|
|
else {
|
2004-10-15 00:37:16 +02:00
|
|
|
|
/* wenn die zeile l<>nger als erlaubt war, ist sie ung<6E>ltig,
|
|
|
|
|
* und wird mit dem rest weggeworfen: */
|
2004-12-14 22:16:54 +01:00
|
|
|
|
for (;;) {
|
2004-10-15 00:37:16 +02:00
|
|
|
|
bp = (unsigned char *)fgets(lbuf, MAXLINE, F);
|
2004-12-14 22:16:54 +01:00
|
|
|
|
if (bp==NULL) break;
|
2004-10-15 00:37:16 +02:00
|
|
|
|
end = bp + strlen((const char *)bp);
|
|
|
|
|
if (*(end-1)=='\n') break;
|
|
|
|
|
lbuf[MAXLINE-1] = 0;
|
2004-07-02 07:41:47 +02:00
|
|
|
|
}
|
2004-10-15 00:37:16 +02:00
|
|
|
|
comment = false;
|
|
|
|
|
bp = NULL;
|
2004-07-02 07:41:47 +02:00
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
cont = false;
|
2004-10-15 00:37:16 +02:00
|
|
|
|
while (bp!=NULL && *bp && cp!=buf+MAXLINE && (char*)bp!=lbuf+MAXLINE) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (isspace(*bp)) {
|
2004-07-02 07:41:47 +02:00
|
|
|
|
if (eatwhite) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
do { ++bp; } while ((char*)bp!=lbuf+MAXLINE && isspace(*bp));
|
|
|
|
|
if (!quote && !start && !comment) *(cp++)=' ';
|
|
|
|
|
}
|
|
|
|
|
else {
|
2004-07-02 07:41:47 +02:00
|
|
|
|
if (!comment) *(cp++)=*(bp++);
|
|
|
|
|
while (cp!=buf+MAXLINE && (char*)bp!=lbuf+MAXLINE && isspace(*bp)) {
|
|
|
|
|
if (!comment) *(cp++)=*bp;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
++bp;
|
2004-07-02 07:41:47 +02:00
|
|
|
|
}
|
|
|
|
|
if (*bp==0) --cp;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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;
|
2004-07-02 07:41:47 +02:00
|
|
|
|
*cp++ = *bp;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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));
|
|
|
|
|
}
|
2004-05-31 14:19:26 +02:00
|
|
|
|
fputs("end \n", F);
|
2002-12-18 01:34:19 +01:00
|
|
|
|
#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
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
int i;
|
|
|
|
|
unit *u;
|
|
|
|
|
|
|
|
|
|
if (!f) return NULL;
|
|
|
|
|
|
|
|
|
|
i = getid();
|
|
|
|
|
u = findunitg(i, NULL);
|
|
|
|
|
|
2005-05-27 23:04:13 +02:00
|
|
|
|
if (u && u->race == new_race[RC_SPELL]) return NULL;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
if (u && u->faction == f) {
|
|
|
|
|
order ** ordp;
|
|
|
|
|
|
2004-10-03 14:18:39 +02:00
|
|
|
|
if (!quiet) {
|
|
|
|
|
printf(",_%4s_", itoa36(u->no));
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
}
|
2005-05-01 13:32:24 +02:00
|
|
|
|
|
|
|
|
|
if (!fval(u, UFL_ORDERS)) {
|
|
|
|
|
/* alle wiederholbaren, langen befehle werden gesichert: */
|
|
|
|
|
fset(u, UFL_ORDERS);
|
|
|
|
|
u->old_orders = u->orders;
|
|
|
|
|
ordp = &u->old_orders;
|
|
|
|
|
while (*ordp) {
|
|
|
|
|
order * ord = *ordp;
|
|
|
|
|
if (!is_repeated(ord)) {
|
2005-05-01 13:38:06 +02:00
|
|
|
|
*ordp = ord->next;
|
2005-05-01 15:33:34 +02:00
|
|
|
|
ord->next = NULL;
|
2005-05-01 13:32:24 +02:00
|
|
|
|
free_order(ord);
|
|
|
|
|
} else {
|
|
|
|
|
ordp = &ord->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
free_orders(&u->orders);
|
|
|
|
|
}
|
2004-06-21 18:45:27 +02:00
|
|
|
|
u->orders = 0;
|
|
|
|
|
|
|
|
|
|
ordp = &u->orders;
|
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
const char * s;
|
|
|
|
|
/* 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;
|
|
|
|
|
|
|
|
|
|
init_tokens_str(buf);
|
|
|
|
|
s = getstrtoken();
|
|
|
|
|
|
|
|
|
|
if (findkeyword(s, u->faction->locale) == NOKEYWORD) {
|
|
|
|
|
boolean quit = false;
|
|
|
|
|
switch (findparam(s, u->faction->locale)) {
|
|
|
|
|
case P_UNIT:
|
2004-06-26 23:03:42 +02:00
|
|
|
|
case P_REGION:
|
2004-06-21 18:45:27 +02:00
|
|
|
|
case P_FACTION:
|
|
|
|
|
case P_NEXT:
|
|
|
|
|
case P_GAMENAME:
|
|
|
|
|
quit = true;
|
|
|
|
|
}
|
|
|
|
|
if (quit) break;
|
|
|
|
|
}
|
|
|
|
|
if (buf[0]) {
|
|
|
|
|
/* Nun wird der Befehl erzeut und eingeh<65>ngt */
|
|
|
|
|
*ordp = parse_order(buf, u->faction->locale);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (*ordp) ordp = &(*ordp)->next;
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
} else {
|
2005-06-10 00:10:35 +02:00
|
|
|
|
/* cmistake(?, buf, 160, MSG_EVENT); */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return u;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
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));
|
2005-05-08 01:53:23 +02:00
|
|
|
|
ADDMSG(&f->msgs, msg_message("msg_errors", "string",
|
|
|
|
|
"Das Passwort wurde falsch eingegeben"));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
/* ------------------------------------------------------------- */
|
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
static param_t
|
|
|
|
|
igetparam (const char *s, const struct locale *lang)
|
|
|
|
|
{
|
|
|
|
|
return findparam (igetstrtoken (s), lang);
|
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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();
|
2004-05-09 12:18:09 +02:00
|
|
|
|
#undef LOCALE_CHANGE
|
|
|
|
|
#ifdef LOCALE_CHANGE
|
2001-04-16 16:34:19 +02:00
|
|
|
|
if (f && find_locale(s)) {
|
|
|
|
|
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;
|
2005-04-23 11:47:03 +02:00
|
|
|
|
b = getbuf(F);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2001-01-25 10:37:55 +01:00
|
|
|
|
b = getbuf(F);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(F);
|
2001-02-17 16:02:50 +01:00
|
|
|
|
puts("\n");
|
2004-05-25 23:50:23 +02:00
|
|
|
|
log_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;
|
2005-01-03 22:28:57 +01:00
|
|
|
|
boolean incomplete_data = 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2004-06-27 18:56:01 +02:00
|
|
|
|
static void
|
2002-08-26 16:16:16 +02:00
|
|
|
|
read_alliances(FILE * F)
|
|
|
|
|
{
|
2004-06-27 18:56:01 +02:00
|
|
|
|
char pbuf[32];
|
|
|
|
|
|
|
|
|
|
if (global.data_version<SAVEALLIANCE_VERSION) {
|
|
|
|
|
if (!AllianceRestricted() && !AllianceAuto()) return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2004-06-14 00:16:12 +02:00
|
|
|
|
static void
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2004-06-14 00:16:12 +02:00
|
|
|
|
static void
|
|
|
|
|
wi36(FILE * F, int n)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
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
|
|
|
|
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);
|
|
|
|
|
}
|
2004-05-31 14:19:26 +02:00
|
|
|
|
fprintf(F, "end ");
|
2002-08-26 16:16:16 +02:00
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
2004-06-14 00:16:12 +02:00
|
|
|
|
fprintf(F, "%s %i ", resourcename(itm->type->rtype, 0), itm->number);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
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
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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)
|
|
|
|
|
{
|
2005-06-10 00:10:35 +02:00
|
|
|
|
variant id;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (global.data_version >= BASE36IDS_VERSION) {
|
|
|
|
|
char zText[10];
|
|
|
|
|
fscanf(F, "%s ", zText);
|
2005-06-10 00:10:35 +02:00
|
|
|
|
id.i = atoi36(zText);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} else {
|
2005-06-10 00:10:35 +02:00
|
|
|
|
fscanf(F, "%d ", &id.i);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2005-06-10 00:10:35 +02:00
|
|
|
|
if (id.i<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
|
|
|
|
}
|
2005-06-10 00:10:35 +02:00
|
|
|
|
*f = findfaction(id.i);
|
|
|
|
|
if (*f==NULL) ur_add(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
|
|
|
|
|
2004-06-21 18:45:27 +02:00
|
|
|
|
void
|
2004-07-02 21:08:53 +02:00
|
|
|
|
fwriteorder(FILE * F, const order * ord, const struct locale * lang)
|
2004-06-21 18:45:27 +02:00
|
|
|
|
{
|
2004-07-02 21:08:53 +02:00
|
|
|
|
write_order(ord, lang, buf, sizeof(buf));
|
2005-08-07 15:48:18 +02:00
|
|
|
|
if (buf[0]) fwritestr(F, buf);
|
2004-06-21 18:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
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;
|
2005-07-27 13:48:16 +02:00
|
|
|
|
int number, n, p;
|
2005-07-27 14:09:53 +02:00
|
|
|
|
order ** orderp;
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2005-01-19 21:33:13 +01:00
|
|
|
|
int n = rid(F);
|
|
|
|
|
faction * f = findfaction(n);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
if (f!=u->faction) u_setfaction(u, f);
|
|
|
|
|
}
|
|
|
|
|
rds(F, &u->name);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (lomem) rds(F, 0);
|
|
|
|
|
else rds(F, &u->display);
|
2004-09-12 11:51:36 +02:00
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
if (strlen(u->name)>=NAMESIZE) u->name[NAMESIZE] = 0;
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (u->display && strlen(u->display)>=DISPLAYSIZE) u->display[DISPLAYSIZE] = 0;
|
2004-09-12 11:51:36 +02:00
|
|
|
|
#endif
|
2002-03-03 16:16:28 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
2005-05-28 10:59:14 +02:00
|
|
|
|
} else {
|
2002-03-11 22:20:31 +01:00
|
|
|
|
u->flags = ri(F) & ~UFL_DEBUG;
|
2005-05-28 10:59:14 +02:00
|
|
|
|
u->flags &= UFL_SAVEMASK;
|
|
|
|
|
}
|
2005-04-30 19:07:46 +02:00
|
|
|
|
/* Persistente Befehle einlesen */
|
2004-06-21 18:45:27 +02:00
|
|
|
|
free_orders(&u->orders);
|
2004-07-02 21:08:53 +02:00
|
|
|
|
freadstr(F, buf, sizeof(buf));
|
2005-07-27 13:48:16 +02:00
|
|
|
|
p = n = 0;
|
2005-07-27 14:09:53 +02:00
|
|
|
|
orderp = &u->orders;
|
2004-07-03 21:16:17 +02:00
|
|
|
|
while (*buf != 0) {
|
2004-06-26 22:51:19 +02:00
|
|
|
|
order * ord = parse_order(buf, u->faction->locale);
|
2005-07-27 13:48:16 +02:00
|
|
|
|
if (ord!=NULL) {
|
|
|
|
|
if (++n<MAXORDERS) {
|
|
|
|
|
if (!is_persistent(ord) || ++p<MAXPERSISTENT) {
|
2005-07-27 14:09:53 +02:00
|
|
|
|
*orderp = ord;
|
|
|
|
|
orderp = &ord->next;
|
2005-07-27 13:48:16 +02:00
|
|
|
|
} else if (p==MAXPERSISTENT) {
|
|
|
|
|
log_error(("%s had %d or more persistent orders\n", unitname(u), MAXPERSISTENT));
|
|
|
|
|
}
|
|
|
|
|
} else if (n==MAXORDERS) {
|
2005-07-31 03:07:07 +02:00
|
|
|
|
log_error(("%s had %d or more orders\n", unitname(u), MAXORDERS));
|
2005-07-27 13:48:16 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-07-02 21:08:53 +02:00
|
|
|
|
freadstr(F, buf, sizeof(buf));
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
2005-04-30 19:07:46 +02:00
|
|
|
|
if (global.data_version<NOLASTORDER_VERSION) {
|
|
|
|
|
order * ord;
|
|
|
|
|
freadstr(F, buf, sizeof(buf));
|
|
|
|
|
ord = parse_order(buf, u->faction->locale);
|
|
|
|
|
if (ord!=NULL) {
|
|
|
|
|
#ifdef LASTORDER
|
|
|
|
|
set_order(&u->lastorder, ord);
|
|
|
|
|
#else
|
|
|
|
|
addlist(&u->orders, ord);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
2004-06-26 22:51:19 +02:00
|
|
|
|
set_order(&u->thisorder, NULL);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
2005-05-01 00:03:47 +02:00
|
|
|
|
assert(u->number <= UNIT_MAXSIZE);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
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) {
|
2004-09-11 21:26:58 +02:00
|
|
|
|
add_spell(mage, (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)
|
|
|
|
|
{
|
2004-06-21 18:45:27 +02:00
|
|
|
|
order * ord;
|
2002-03-03 16:16:28 +01:00
|
|
|
|
int i;
|
|
|
|
|
wi36(F, u->no);
|
|
|
|
|
wi36(F, u->faction->no);
|
|
|
|
|
ws(F, u->name);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
ws(F, u->display?u->display:"");
|
2002-03-03 16:16:28 +01:00
|
|
|
|
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);
|
2004-06-21 18:45:27 +02:00
|
|
|
|
wnl(F);
|
2005-05-01 13:32:24 +02:00
|
|
|
|
#ifndef LASTORDER
|
|
|
|
|
for (ord = u->old_orders; ord; ord=ord->next) {
|
|
|
|
|
fwriteorder(F, ord, u->faction->locale);
|
|
|
|
|
fputc(' ', F);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2005-08-07 15:48:18 +02:00
|
|
|
|
for (ord = u->orders; ord; ord=ord->next) {
|
2005-06-05 18:48:22 +02:00
|
|
|
|
if (u->old_orders && is_repeated(ord)) continue; /* has new defaults */
|
2005-08-07 15:48:18 +02:00
|
|
|
|
if (is_persistent(ord)) {
|
2004-07-02 21:08:53 +02:00
|
|
|
|
fwriteorder(F, ord, u->faction->locale);
|
|
|
|
|
fputc(' ', F);
|
2005-08-07 15:48:18 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-07-03 21:16:17 +02:00
|
|
|
|
/* write an empty string to terminate the list */
|
2005-08-07 15:48:18 +02:00
|
|
|
|
fputs("\"\"", F);
|
|
|
|
|
wnl(F);
|
2005-04-30 19:07:46 +02:00
|
|
|
|
#if RELEASE_VERSION<NOLASTORDER_VERSION
|
2004-07-03 21:16:17 +02:00
|
|
|
|
/* the current default order */
|
2005-08-07 15:48:18 +02:00
|
|
|
|
fwriteorder(F, u->lastorder, u->faction->locale);
|
|
|
|
|
wnl(F);
|
2005-04-30 19:07:46 +02:00
|
|
|
|
#endif
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
2005-05-01 00:03:47 +02:00
|
|
|
|
assert(u->number <= UNIT_MAXSIZE);
|
2005-08-07 15:48:18 +02:00
|
|
|
|
assert(u->race);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
|
|
|
|
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 *
|
2005-06-10 00:10:35 +02:00
|
|
|
|
readregion(FILE * F, short x, short y)
|
2002-03-03 16:16:28 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (lomem) rds(F, 0);
|
|
|
|
|
else rds(F, &r->display);
|
|
|
|
|
|
|
|
|
|
ter = ri(F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
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);
|
2004-09-12 11:51:36 +02:00
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
if (strlen(r->land->name)>=NAMESIZE) r->land->name[NAMESIZE] = 0;
|
|
|
|
|
#endif
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
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)
|
|
|
|
|
{
|
2005-04-23 11:47:03 +02:00
|
|
|
|
ws(F, r->display?r->display:"");
|
2002-03-03 16:16:28 +01:00
|
|
|
|
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);
|
|
|
|
|
}
|
2004-05-31 14:19:26 +02:00
|
|
|
|
fputs("end \n", F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
}
|
|
|
|
|
a_write(F, r->attribs);
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-04 21:24:03 +02:00
|
|
|
|
static ally **
|
2002-09-02 22:36:12 +02:00
|
|
|
|
addally(const faction * f, ally ** sfp, int aid, int state)
|
|
|
|
|
{
|
2004-05-04 21:24:03 +02:00
|
|
|
|
struct faction * af = findfaction(aid);
|
|
|
|
|
ally * sf;
|
2005-06-10 00:10:35 +02:00
|
|
|
|
|
2004-05-04 21:24:03 +02:00
|
|
|
|
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
|
2004-05-04 21:24:03 +02:00
|
|
|
|
state &= ~HELP_TRAVEL;
|
2002-09-02 22:36:12 +02:00
|
|
|
|
#endif
|
2004-06-27 18:56:01 +02:00
|
|
|
|
|
2004-05-04 21:34:35 +02:00
|
|
|
|
if (state==0) return sfp;
|
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
|
|
|
|
|
|
|
|
|
sf = calloc(1, sizeof(ally));
|
2004-05-04 21:24:03 +02:00
|
|
|
|
sf->faction = af;
|
2005-06-10 00:10:35 +02:00
|
|
|
|
if (!sf->faction) {
|
|
|
|
|
variant id;
|
|
|
|
|
id.i = aid;
|
|
|
|
|
ur_add(id, (void**)&sf->faction, resolve_faction);
|
|
|
|
|
}
|
2005-02-27 15:44:21 +01:00
|
|
|
|
sf->status = state & HELP_ALL;
|
2002-09-02 22:36:12 +02:00
|
|
|
|
|
2004-05-04 21:24:03 +02:00
|
|
|
|
while (*sfp) sfp=&(*sfp)->next;
|
|
|
|
|
*sfp = sf;
|
2004-05-04 21:34:35 +02:00
|
|
|
|
return &sf->next;
|
2002-09-02 22:36:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
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);
|
2004-08-22 11:54:39 +02:00
|
|
|
|
char * email = NULL;
|
2004-08-22 11:33:15 +02:00
|
|
|
|
|
2004-04-10 22:25:40 +02:00
|
|
|
|
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);
|
2004-06-27 18:56:01 +02:00
|
|
|
|
|
|
|
|
|
if (alliances!=NULL) {
|
2004-04-10 22:25:40 +02:00
|
|
|
|
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-03-03 16:16:28 +01:00
|
|
|
|
|
2004-04-10 22:25:40 +02:00
|
|
|
|
rds(F, &f->name);
|
2004-09-12 11:51:36 +02:00
|
|
|
|
rds(F, &f->banner);
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
if (strlen(f->name)>=NAMESIZE) f->name[NAMESIZE] = 0;
|
|
|
|
|
if (strlen(f->banner)>=DISPLAYSIZE) f->banner[DISPLAYSIZE] = 0;
|
|
|
|
|
#endif
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
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
|
|
|
|
|
2004-08-22 11:33:15 +02:00
|
|
|
|
rds(F, &email);
|
|
|
|
|
if (set_email(&f->email, email)!=0) {
|
2004-08-29 01:06:15 +02:00
|
|
|
|
log_error(("Invalid email address for faction %s: %s\n", itoa36(f->no), email));
|
2004-08-22 11:33:15 +02:00
|
|
|
|
set_email(&f->email, "");
|
|
|
|
|
}
|
2005-04-30 15:21:20 +02:00
|
|
|
|
free(email);
|
2004-04-10 22:25:40 +02:00
|
|
|
|
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);
|
|
|
|
|
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-12-22 01:53:12 +01:00
|
|
|
|
if (global.data_version>=CLAIM_VERSION) {
|
|
|
|
|
read_items(F, &f->items);
|
|
|
|
|
}
|
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);
|
2005-06-10 00:10:35 +02:00
|
|
|
|
short ux = (short)ri(F);
|
|
|
|
|
short uy = (short)ri(F);
|
2004-04-10 22:25:40 +02:00
|
|
|
|
set_ursprung(f, id, ux, uy);
|
|
|
|
|
}
|
|
|
|
|
f->newbies = 0;
|
|
|
|
|
|
|
|
|
|
i = f->options = ri(F);
|
2002-03-03 16:16:28 +01:00
|
|
|
|
|
2005-07-22 19:13:51 +02:00
|
|
|
|
if ((i & ((1<<O_REPORT)|(1<<O_COMPUTER)))==0 && f->no!=MONSTER_FACTION) {
|
2004-04-10 22:25:40 +02:00
|
|
|
|
/* 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);
|
2004-05-04 21:24:03 +02:00
|
|
|
|
sfp = addally(f, sfp, aid, state);
|
2004-04-10 22:25:40 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (;;) {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
if (strcmp(buf, "end")==0) break;
|
|
|
|
|
else {
|
|
|
|
|
int aid = atoi36(buf);
|
|
|
|
|
int state = ri(F);
|
2004-05-04 21:24:03 +02:00
|
|
|
|
sfp = addally(f, sfp, aid, state);
|
2004-04-10 22:25:40 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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);
|
2004-06-27 18:56:01 +02:00
|
|
|
|
if (alliances!=NULL) {
|
|
|
|
|
if (f->alliance) wi36(F, f->alliance->id);
|
|
|
|
|
else wi36(F, 0);
|
|
|
|
|
}
|
2002-09-02 22:36:12 +02:00
|
|
|
|
|
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-12-22 19:16:59 +01:00
|
|
|
|
#if RELEASE_VERSION>=CLAIM_VERSION
|
|
|
|
|
write_items(F, f->items);
|
|
|
|
|
wnl(F);
|
|
|
|
|
#endif
|
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
|
|
|
|
}
|
2004-05-31 14:19:26 +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
|
|
|
|
}
|
2004-04-12 01:56:47 +02:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
readgame(const char * filename, int backup)
|
|
|
|
|
{
|
|
|
|
|
int i, n, p;
|
|
|
|
|
faction *f, **fp;
|
|
|
|
|
region *r;
|
|
|
|
|
building *b, **bp;
|
|
|
|
|
ship *sh, **shp;
|
|
|
|
|
unit *u;
|
|
|
|
|
FILE * F;
|
|
|
|
|
int rmax = maxregions;
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "%s/%s", datapath(), filename);
|
|
|
|
|
log_printf("- reading game data from %s\n", filename);
|
|
|
|
|
if (backup) create_backup(buf);
|
|
|
|
|
F = cfopen(buf, "r");
|
|
|
|
|
if (F==NULL) {
|
2004-05-25 23:50:23 +02:00
|
|
|
|
log_error(("Keine Spieldaten gefunden.\n"));
|
2004-04-12 01:56:47 +02:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc(F);
|
|
|
|
|
|
|
|
|
|
/* globale Variablen */
|
|
|
|
|
|
|
|
|
|
global.data_version = ri(F);
|
|
|
|
|
assert(global.data_version>=MIN_VERSION || !"unsupported data format");
|
|
|
|
|
assert(global.data_version<=RELEASE_VERSION || !"unsupported data format");
|
|
|
|
|
assert(global.data_version >= NEWSOURCE_VERSION);
|
|
|
|
|
if(global.data_version >= SAVEXMLNAME_VERSION) {
|
|
|
|
|
char basefile[1024];
|
|
|
|
|
const char *basearg = "(null)";
|
|
|
|
|
|
|
|
|
|
rs(F, basefile);
|
|
|
|
|
assert(xmlfile != NULL);
|
|
|
|
|
basearg = strrchr(xmlfile, '/');
|
|
|
|
|
if (basearg==NULL) {
|
|
|
|
|
basearg = xmlfile;
|
|
|
|
|
} else {
|
|
|
|
|
++basearg;
|
|
|
|
|
}
|
|
|
|
|
if (strcmp(basearg, basefile)!=0) {
|
2004-05-25 23:50:23 +02:00
|
|
|
|
log_warning(("xmlfile mismatch: datafile contains %s, argument/default is %s\n", basefile, basearg));
|
2004-04-12 01:56:47 +02:00
|
|
|
|
printf("WARNING: any key to continue, Ctrl-C to stop\n");
|
|
|
|
|
getchar();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (global.data_version >= GLOBAL_ATTRIB_VERSION) {
|
|
|
|
|
a_read(F, &global.attribs);
|
|
|
|
|
}
|
|
|
|
|
if (global.data_version < ITEMTYPE_VERSION) {
|
|
|
|
|
fprintf(stderr, "kann keine alten datenfiles einlesen");
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
global.data_turn = turn = ri(F);
|
|
|
|
|
ri(F); /* max_unique_id = */
|
|
|
|
|
nextborder = ri(F);
|
|
|
|
|
|
|
|
|
|
/* Planes */
|
|
|
|
|
planes = NULL;
|
|
|
|
|
n = ri(F);
|
|
|
|
|
while(--n >= 0) {
|
|
|
|
|
plane *pl = calloc(1, sizeof(plane));
|
|
|
|
|
pl->id = ri(F);
|
|
|
|
|
rds(F, &pl->name);
|
2005-06-10 00:10:35 +02:00
|
|
|
|
pl->minx = (short)ri(F);
|
|
|
|
|
pl->maxx = (short)ri(F);
|
|
|
|
|
pl->miny = (short)ri(F);
|
|
|
|
|
pl->maxy = (short)ri(F);
|
2004-04-12 01:56:47 +02:00
|
|
|
|
pl->flags = ri(F);
|
|
|
|
|
if (global.data_version>WATCHERS_VERSION) {
|
|
|
|
|
rs(F, buf);
|
|
|
|
|
while (strcmp(buf, "end")!=0) {
|
|
|
|
|
watcher * w = calloc(sizeof(watcher),1);
|
2005-06-10 00:10:35 +02:00
|
|
|
|
variant fno;
|
|
|
|
|
fno.i = atoi36(buf);
|
2004-04-12 01:56:47 +02:00
|
|
|
|
w->mode = (unsigned char)ri(F);
|
|
|
|
|
w->next = pl->watchers;
|
|
|
|
|
pl->watchers = w;
|
2005-06-10 00:10:35 +02:00
|
|
|
|
ur_add(fno, (void**)&w->faction, resolve_faction);
|
2004-04-12 01:56:47 +02:00
|
|
|
|
rs(F, buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
a_read(F, &pl->attribs);
|
|
|
|
|
addlist(&planes, pl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read factions */
|
|
|
|
|
if (global.data_version>=ALLIANCES_VERSION) {
|
|
|
|
|
read_alliances(F);
|
|
|
|
|
}
|
|
|
|
|
n = ri(F);
|
|
|
|
|
printf(" - Einzulesende Parteien: %d\n", n);
|
|
|
|
|
fp = &factions;
|
|
|
|
|
while (*fp) fp=&(*fp)->next;
|
|
|
|
|
|
|
|
|
|
/* fflush (stdout); */
|
|
|
|
|
|
|
|
|
|
while (--n >= 0) {
|
|
|
|
|
faction * f = readfaction(F);
|
|
|
|
|
addlist2(fp, f);
|
2005-01-19 21:33:13 +01:00
|
|
|
|
fhash(f);
|
2004-04-12 01:56:47 +02:00
|
|
|
|
}
|
|
|
|
|
*fp = 0;
|
|
|
|
|
|
|
|
|
|
/* Benutzte Faction-Ids */
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Regionen */
|
|
|
|
|
|
|
|
|
|
n = ri(F);
|
|
|
|
|
if (rmax<0) rmax = n;
|
|
|
|
|
printf(" - Einzulesende Regionen: %d/%d\r", rmax, n);
|
2005-01-03 22:28:57 +01:00
|
|
|
|
if (loadplane || dirtyload || firstx || firsty || maxregions>=0) {
|
|
|
|
|
incomplete_data = true;
|
|
|
|
|
}
|
2004-04-12 01:56:47 +02:00
|
|
|
|
while (--n >= 0) {
|
|
|
|
|
unit **up;
|
|
|
|
|
boolean skip = false;
|
2005-06-10 00:10:35 +02:00
|
|
|
|
short x = (short)ri(F);
|
|
|
|
|
short y = (short)ri(F);
|
2004-04-12 01:56:47 +02:00
|
|
|
|
plane * pl = findplane(x, y);
|
|
|
|
|
|
2005-01-03 22:28:21 +01:00
|
|
|
|
if (firstx || firsty) {
|
2004-04-12 01:56:47 +02:00
|
|
|
|
if (x!=firstx || y!=firsty) {
|
|
|
|
|
skip = true;
|
|
|
|
|
} else {
|
|
|
|
|
firstx=0;
|
|
|
|
|
firsty=0;
|
|
|
|
|
if (rmax>0) rmax = min(n, rmax)-1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (loadplane && (!pl || pl->id!=loadplane)) skip = true;
|
|
|
|
|
if (rmax==0) {
|
|
|
|
|
if (dirtyload) break;
|
|
|
|
|
skip = true;
|
|
|
|
|
}
|
|
|
|
|
if ((n%1024)==0) { /* das spart extrem Zeit */
|
|
|
|
|
printf(" - Einzulesende Regionen: %d/%d ", rmax, n);
|
|
|
|
|
printf("* %d,%d \r", x, y);
|
|
|
|
|
}
|
|
|
|
|
if (skip) {
|
|
|
|
|
char * r;
|
|
|
|
|
do {
|
|
|
|
|
r = fgets(buf, BUFSIZE, F); /* skip region */
|
|
|
|
|
} while (r && buf[0]!='\n');
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
--rmax;
|
|
|
|
|
|
|
|
|
|
r = readregion(F, x, y);
|
|
|
|
|
|
|
|
|
|
/* Burgen */
|
|
|
|
|
p = ri(F);
|
|
|
|
|
bp = &r->buildings;
|
|
|
|
|
|
|
|
|
|
while (--p >= 0) {
|
|
|
|
|
|
|
|
|
|
b = (building *) calloc(1, sizeof(building));
|
|
|
|
|
b->no = rid(F);
|
|
|
|
|
bhash(b);
|
|
|
|
|
rds(F, &b->name);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (lomem) rds(F, 0);
|
|
|
|
|
else rds(F, &b->display);
|
2004-09-12 11:51:36 +02:00
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
if (strlen(b->name)>=NAMESIZE) b->name[NAMESIZE] = 0;
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (b->display && strlen(b->display)>=DISPLAYSIZE) b->display[DISPLAYSIZE] = 0;
|
2004-09-12 11:51:36 +02:00
|
|
|
|
#endif
|
2004-04-12 01:56:47 +02:00
|
|
|
|
b->size = ri(F);
|
|
|
|
|
if (global.data_version < TYPES_VERSION) {
|
|
|
|
|
assert(!"data format is no longer supported");
|
|
|
|
|
/* b->type = oldbuildings[ri(F)]; */
|
|
|
|
|
}
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
sh->region = r;
|
|
|
|
|
sh->no = rid(F);
|
|
|
|
|
shash(sh);
|
|
|
|
|
rds(F, &sh->name);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (lomem) rds(F, 0);
|
|
|
|
|
else rds(F, &sh->display);
|
2004-09-12 11:51:36 +02:00
|
|
|
|
#ifndef NDEBUG
|
2005-04-23 11:47:03 +02:00
|
|
|
|
if (sh->name && strlen(sh->name)>=NAMESIZE) sh->name[NAMESIZE] = 0;
|
|
|
|
|
if (sh->display && strlen(sh->display)>=DISPLAYSIZE) sh->display[DISPLAYSIZE] = 0;
|
2004-09-12 11:51:36 +02:00
|
|
|
|
#endif
|
2004-04-12 01:56:47 +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);
|
|
|
|
|
|
|
|
|
|
/* 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) {
|
|
|
|
|
unit * u = readunit(F);
|
|
|
|
|
assert(u->region==NULL);
|
|
|
|
|
u->region = r;
|
|
|
|
|
addlist2(up,u);
|
2005-04-28 09:04:10 +02:00
|
|
|
|
update_interval(u->faction, u->region);
|
2004-04-12 01:56:47 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf("\n");
|
|
|
|
|
if (!dirtyload) {
|
|
|
|
|
read_borders(F);
|
|
|
|
|
#ifdef USE_UGROUPS
|
|
|
|
|
if (global.data_version >= UGROUPS_VERSION) read_ugroups(F);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose(F);
|
|
|
|
|
|
|
|
|
|
/* Unaufgeloeste Zeiger initialisieren */
|
|
|
|
|
printf("\n - Referenzen initialisieren...\n");
|
|
|
|
|
resolve();
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (r=regions;r;r=r->next) {
|
|
|
|
|
building * b;
|
|
|
|
|
for (b=r->buildings;b;b=b->next) update_lighthouse(b);
|
|
|
|
|
}
|
|
|
|
|
printf(" - Regionen initialisieren & verbinden...\n");
|
2004-07-02 07:41:47 +02:00
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
for (u = f->units; u; u = u->nextF) {
|
|
|
|
|
if (u->number>0) {
|
|
|
|
|
f->alive = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2004-04-12 01:56:47 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-07-02 07:41:47 +02:00
|
|
|
|
if (findfaction(0)) {
|
2004-04-12 01:56:47 +02:00
|
|
|
|
findfaction(0)->alive = 1;
|
|
|
|
|
}
|
|
|
|
|
if (loadplane || maxregions>=0) {
|
|
|
|
|
remove_empty_factions(false);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
writegame(const char *filename, char quiet)
|
|
|
|
|
{
|
|
|
|
|
char *base;
|
|
|
|
|
int i,n;
|
|
|
|
|
faction *f;
|
|
|
|
|
region *r;
|
|
|
|
|
building *b;
|
|
|
|
|
ship *sh;
|
|
|
|
|
unit *u;
|
|
|
|
|
plane *pl;
|
|
|
|
|
FILE * F;
|
|
|
|
|
#ifdef USE_PLAYERS
|
|
|
|
|
char playerfile[MAX_PATH];
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef USE_PLAYERS
|
|
|
|
|
sprintf(buf, "%s/%d.players", datapath(), turn);
|
|
|
|
|
export_players(playerfile);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "%s/%s", datapath(), filename);
|
|
|
|
|
F = cfopen(buf, "w");
|
|
|
|
|
if (F==NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (!quiet)
|
|
|
|
|
printf("Schreibe die %d. Runde...\n", turn);
|
|
|
|
|
|
|
|
|
|
/* globale Variablen */
|
|
|
|
|
|
|
|
|
|
wi(F, RELEASE_VERSION);
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
base = strrchr(xmlfile, '/');
|
|
|
|
|
if(base) {
|
|
|
|
|
ws(F, base+1);
|
|
|
|
|
} else {
|
|
|
|
|
ws(F, xmlfile);
|
|
|
|
|
}
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
a_write(F, global.attribs);
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
wi(F, turn);
|
|
|
|
|
wi(F, 0/*max_unique_id*/);
|
|
|
|
|
wi(F, nextborder);
|
|
|
|
|
|
|
|
|
|
/* Write planes */
|
|
|
|
|
wnl(F);
|
|
|
|
|
wi(F, listlen(planes));
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
for(pl = planes; pl; pl=pl->next) {
|
|
|
|
|
watcher * w;
|
|
|
|
|
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);
|
|
|
|
|
w = pl->watchers;
|
|
|
|
|
while (w) {
|
|
|
|
|
if (w->faction) {
|
|
|
|
|
wi36(F, w->faction->no);
|
|
|
|
|
wi(F, w->mode);
|
|
|
|
|
}
|
|
|
|
|
w = w->next;
|
|
|
|
|
}
|
|
|
|
|
fputs("end ", F);
|
|
|
|
|
a_write(F, pl->attribs);
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Write factions */
|
2004-06-27 18:56:01 +02:00
|
|
|
|
#if RELEASE_VERSION>=ALLIANCES_VERSION
|
2004-04-12 01:56:47 +02:00
|
|
|
|
write_alliances(F);
|
|
|
|
|
#endif
|
2004-06-27 18:56:01 +02:00
|
|
|
|
n = listlen(factions);
|
2004-04-12 01:56:47 +02:00
|
|
|
|
wi(F, n);
|
|
|
|
|
wnl(F);
|
|
|
|
|
|
|
|
|
|
printf(" - Schreibe %d Parteien...\n",n);
|
|
|
|
|
for (f = factions; f; f = f->next) {
|
|
|
|
|
writefaction(F, f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
}
|
|
|
|
|
wnl(F);
|
|
|
|
|
wi(F, r->x);
|
|
|
|
|
wi(F, r->y);
|
|
|
|
|
writeregion(F, r);
|
|
|
|
|
|
|
|
|
|
wi(F, listlen(r->buildings));
|
|
|
|
|
wnl(F);
|
|
|
|
|
for (b = r->buildings; b; b = b->next) {
|
|
|
|
|
wi36(F, b->no);
|
|
|
|
|
ws(F, b->name);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
ws(F, b->display?b->display:"");
|
2004-04-12 01:56:47 +02:00
|
|
|
|
wi(F, b->size);
|
|
|
|
|
ws(F, b->type->_name);
|
|
|
|
|
wnl(F);
|
|
|
|
|
a_write(F, b->attribs);
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wi(F, listlen(r->ships));
|
|
|
|
|
wnl(F);
|
|
|
|
|
for (sh = r->ships; sh; sh = sh->next) {
|
|
|
|
|
assert(sh->region == r);
|
|
|
|
|
wi36(F, sh->no);
|
|
|
|
|
ws(F, sh->name);
|
2005-04-23 11:47:03 +02:00
|
|
|
|
ws(F, sh->display?sh->display:"");
|
2004-04-12 01:56:47 +02:00
|
|
|
|
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);
|
|
|
|
|
wnl(F);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wi(F, listlen(r->units));
|
|
|
|
|
wnl(F);
|
|
|
|
|
for (u = r->units; u; u = u->next) {
|
|
|
|
|
writeunit(F, u);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wnl(F);
|
|
|
|
|
write_borders(F);
|
|
|
|
|
wnl(F);
|
|
|
|
|
#if RELEASE_VERSION >= UGROUPS_VERSION
|
|
|
|
|
write_ugroups(F);
|
|
|
|
|
wnl(F);
|
|
|
|
|
#endif
|
|
|
|
|
fclose(F);
|
|
|
|
|
printf("\nOk.\n");
|
|
|
|
|
return 0;
|
2004-04-12 03:47:03 +02:00
|
|
|
|
}
|