--- deliantra/server/common/init.C 2006/09/03 07:57:54 1.4 +++ deliantra/server/common/init.C 2010/06/18 17:31:01 1.60 @@ -1,464 +1,249 @@ /* - * static char *rcsid_init_c = - * "$Id: init.C,v 1.4 2006/09/03 07:57:54 root Exp $"; + * This file is part of Deliantra, the Roguelike Realtime MMORPG. + * + * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2002 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992 Frank Tore Johansen + * + * Deliantra is free software: you can redistribute it and/or modify it under + * the terms of the Affero GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the Affero GNU General Public License + * and the GNU General Public License along with this program. If not, see + * . + * + * The authors can be reached via e-mail to */ -/* - CrossFire, A Multiplayer game for X-windows +#define EXTERN // horrible hack - Copyright (C) 2002 Mark Wedel & Crossfire Development Team - Copyright (C) 1992 Frank Tore Johansen +#include +#include - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +dynbuf_text msg_dynbuf (65536, 65536); - The authors can be reached via e-mail at crossfire-devel@real-time.com -*/ +extern const char *const attacktype_desc[NROFATTACKS] = { +# define def(uc, lc, name, plus, change) # name, +# include "attackinc.h" +# undef def +}; -#define EXTERN -#define INIT_C -#include -#include +extern const char *const resist_plus[NROFATTACKS] = { +# define def(uc, lc, name, plus, change) # plus, +# include "attackinc.h" +# undef def +}; + +extern const char *const change_resist_msg[NROFATTACKS] = { +# define def(uc, lc, name, plus, change) # change, +# include "attackinc.h" +# undef def +}; + +int resist_table[NROFATTACKS] = { +# define def(uc, lc, name, plus, change) ATNR_ ## uc, +# include "attackinc.h" +# undef def +}; /* You unforunately need to looking in include/global.h to see what these * correspond to. */ struct Settings settings = { -LOGFILE, /* Logfile */ -CSPORT, /* Client/server port */ + LOGFILE, /* Logfile */ + CSPORT, /* Client/server port */ + llevTrace, /* Log level */ + 0, NULL, 0, /* dumpvalues, dumparg, daemonmode */ + 0, /* argc */ + NULL, /* argv */ + CONFDIR, + DATADIR, + LOCALDIR, + PLAYERDIR, MAPDIR, ARCHETYPES, REGIONS, TREASURES, + UNIQUE_DIR, "", + TMPDIR, + PK_LUCK_PENALTY, + STAT_LOSS_ON_DEATH, + PERMANENT_EXPERIENCE_RATIO, + DEATH_PENALTY_RATIO, + DEATH_PENALTY_LEVEL, + BALANCED_STAT_LOSS, + NOT_PERMADETH, + SIMPLE_EXP, + SET_TITLE, + RESURRECTION, + SEARCH_ITEMS, + SPELL_ENCUMBRANCE, + SPELL_FAILURE_EFFECTS, + SET_FRIENDLY_FIRE, + 0, + 0, + EXPLORE_MODE, + SPELLPOINT_LEVEL_DEPEND, + 0, + 1.25, -/* Debug level */ -#ifdef DEBUG - llevDebug, -#else - llevInfo, -#endif - -0, NULL, 0, /* dumpvalues, dumparg, daemonmode */ -0, /* argc */ -NULL, /* argv */ -CONFDIR, -DATADIR, -LOCALDIR, -PLAYERDIR, MAPDIR, ARCHETYPES,REGIONS,TREASURES, -UNIQUE_DIR, TEMPLATE_DIR, -TMPDIR, -STAT_LOSS_ON_DEATH, -PK_LUCK_PENALTY, -PERMANENT_EXPERIENCE_RATIO, -DEATH_PENALTY_RATIO, -DEATH_PENALTY_LEVEL, -BALANCED_STAT_LOSS, -NOT_PERMADETH, -SIMPLE_EXP, -RESET_LOCATION_TIME, -SET_TITLE, -RESURRECTION, -SEARCH_ITEMS, -SPELL_ENCUMBRANCE, -SPELL_FAILURE_EFFECTS, -CASTING_TIME, -REAL_WIZ, -RECYCLE_TMP_MAPS, -EXPLORE_MODE, -SPELLPOINT_LEVEL_DEPEND, -SET_FRIENDLY_FIRE, -"", /* Who format specifier */ -"", /* who wiz format specifier */ -MOTD, -"rules", -"news", -"", /* DM_MAIL */ -0, /* This and the next 3 values are metaserver values */ -"", -"", -0, -"", -0,0,0,0,0,0,0,0, /* worldmap settings*/ -EMERGENCY_MAPPATH, EMERGENCY_X, EMERGENCY_Y, -0, -1.0, /* Armor enchantment stuff */ -ARMOR_MAX_ENCHANT, -ARMOR_WEIGHT_REDUCTION, -ARMOR_WEIGHT_LINEAR, -ARMOR_SPEED_IMPROVEMENT, -ARMOR_SPEED_LINEAR, -1, /* no_player_stealing */ -1, /* create_home_portals */ + ARMOR_MAX_ENCHANT, + ARMOR_WEIGHT_REDUCTION, + ARMOR_WEIGHT_LINEAR, + ARMOR_SPEED_IMPROVEMENT, + ARMOR_SPEED_LINEAR, }; /* perhaps not the best place for this, but needs to be * in some file in the common area so that standalone * programs, like the random map generator, can be built. */ -const char* const spellpathnames[NRSPELLPATHS] = { - "Protection", - "Fire", - "Frost", - "Electricity", - "Missiles", - "Self", - "Summoning", - "Abjuration", - "Restoration", - "Detonation", - "Mind", - "Creation", - "Teleportation", - "Information", - "Transmutation", - "Transferrence", - "Turning", - "Wounding", - "Death", - "Light" +const char *const spellpathnames[NRSPELLPATHS] = { + "Protection", + "Fire", + "Frost", + "Electricity", + "Missiles", + "Self", + "Summoning", + "Abjuration", + "Restoration", + "Detonation", + "Mind", + "Creation", + "Teleportation", + "Information", + "Transmutation", + "Transferrence", + "Turning", + "Wounding", + "Death", + "Light" }; - -/* This loads the emergency map information from a - * .emergency file in the map directory. Doing this makes - * it easier to switch between map distributions (don't need - * to recompile. Note that there is no reason I see that - * this could not be re-loaded during play, but it seems - * like there should be little reason to do that. - */ -static void init_emergency_mappath(void) -{ - char filename[MAX_BUF], tmpbuf[MAX_BUF]; - FILE *fp; - int online=0; - - /* If this file doesn't exist, not a big deal */ - sprintf(filename,"%s/%s/.emergency",settings.datadir, settings.mapdir); - if ((fp = fopen(filename, "r"))!=NULL) { - while (fgets(tmpbuf, MAX_BUF-1, fp)) { - if (tmpbuf[0] == '#') continue; /* ignore comments */ - - if (online == 0) { - tmpbuf[strlen(tmpbuf)-1] = 0; /* kill newline */ - settings.emergency_mapname = strdup_local(tmpbuf); - } - else if (online == 1) { - settings.emergency_x = atoi(tmpbuf); - } - - else if (online == 2) { - settings.emergency_y = atoi(tmpbuf); - } - online++; - if (online>2) break; - } - fclose(fp); - if (online<=2) - LOG(llevError,"Online read partial data from %s\n", filename); - LOG(llevDebug,"Emergency mappath reset to %s (%d, %d)\n", settings.emergency_mapname, - settings.emergency_x, settings.emergency_y); - } -} - - -/* - * It is vital that init_library() is called by any functions - * using this library. - * If you want to lessen the size of the program using the library, - * you can replace the call to init_library() with init_globals() and - * init_function_pointers(). Good idea to also call init_vars and - * init_hash_table if you are doing any object loading. - */ - -void init_library(void) { - init_environ(); - init_globals(); - init_objects(); - init_vars(); - init_block(); - ReadBmapNames (); - ReadSmooth(); - init_anim(); /* Must be after we read in the bitmaps */ - init_archetypes(); /* Reads all archetypes from file */ - init_dynamic (); - init_attackmess(); - init_clocks(); - init_emergency_mappath(); - init_experience(); -} - - -/* init_environ initializes values from the environmental variables. +/* init_environ initialises values from the environmental variables. * it needs to be called very early, since command line options should * overwrite these if specified. */ -void init_environ(void) { - char *cp; +void +init_environ () +{ + const char *cp; + + if (cp = getenv ("DELIANTRA_CONFDIR" )) settings.confdir = cp; + if (cp = getenv ("DELIANTRA_LIBDIR" )) settings.datadir = cp; + if (cp = getenv ("DELIANTRA_LOCALDIR" )) settings.localdir = cp; + if (cp = getenv ("DELIANTRA_PLAYERDIR" )) settings.playerdir = cp; + if (cp = getenv ("DELIANTRA_MAPDIR" )) settings.mapdir = cp; + if (cp = getenv ("DELIANTRA_ARCHETYPES" )) settings.archetypes = cp; + if (cp = getenv ("DELIANTRA_TREASURES" )) settings.treasures = cp; + if (cp = getenv ("DELIANTRA_UNIQUEDIR" )) settings.uniquedir = cp; + if (cp = getenv ("DELIANTRA_TEMPLATEDIR")) settings.templatedir = cp; + if (cp = getenv ("DELIANTRA_TMPDIR" )) settings.tmpdir = cp; - cp=getenv("CROSSFIRE_LIBDIR"); - if (cp) settings.datadir=cp; - cp=getenv("CROSSFIRE_LOCALDIR"); - if (cp) settings.localdir=cp; - cp=getenv("CROSSFIRE_PLAYERDIR"); - if (cp) settings.playerdir=cp; - cp=getenv("CROSSFIRE_MAPDIR"); - if (cp) settings.mapdir=cp; - cp=getenv("CROSSFIRE_ARCHETYPES"); - if (cp) settings.archetypes=cp; - cp=getenv("CROSSFIRE_TREASURES"); - if (cp) settings.treasures=cp; - cp=getenv("CROSSFIRE_UNIQUEDIR"); - if (cp) settings.uniquedir=cp; - cp=getenv("CROSSFIRE_TEMPLATEDIR"); - if (cp) settings.templatedir=cp; - cp=getenv("CROSSFIRE_TMPDIR"); - if (cp) settings.tmpdir=cp; + if (cp = getenv ("DELIANTRA_LOGFILE" )) settings.logfilename = cp; } - /* * Initialises all global variables. * Might use environment-variables as default for some of them. */ - -void init_globals(void) { - if (settings.logfilename[0] == 0) { - logfile = stderr; - } - else if ((logfile=fopen(settings.logfilename, "a"))==NULL) { - fprintf(stderr,"Unable to open %s as the logfile - will use stderr instead\n", - settings.logfilename); - logfile = stderr; - } - else { - setvbuf(logfile, NULL, _IOLBF, 0); - } - exiting = 0; - first_player=NULL; - first_friendly_object=NULL; - first_map=NULL; - first_treasurelist=NULL; - first_artifactlist=NULL; - first_archetype=NULL; - *first_map_ext_path=0; - warn_archetypes=0; - nroftreasures = 0; - nrofartifacts = 0; - nrofallowedstr=0; - ring_arch = NULL; - amulet_arch = NULL; - staff_arch = NULL; - trying_emergency_save = 0; - num_animations=0; - animations_allocated=0; - init_defaults(); -} - -/* - * Sets up and initialises the linked list of free and used objects. - * Allocates a certain chunk of objects and puts them on the free list. - * Called by init_library(); - */ - -void init_objects(void) { - int i; -/* Initialize all objects: */ - objects=NULL; - active_objects = NULL; - -#ifdef MEMORY_DEBUG - free_objects=NULL; -#else - free_objects=objarray; - objarray[0].prev=NULL, - objarray[0].next= &objarray[1], - SET_FLAG(&objarray[0], FLAG_REMOVED); - SET_FLAG(&objarray[0], FLAG_FREED); - for(i=1;iclone.type == MAP) { - if (at->clone.race) { - strcpy (first_map_ext_path, at->clone.race); - } - if (EXIT_PATH (&at->clone)) { - strcpy (first_map_path, EXIT_PATH (&at->clone)); - return; - } - } - at = at->next; - } - LOG(llevDebug,"You Need a archetype called 'map' and it have to contain start map\n"); - exit (-1); -} - -unsigned long todtick; - -/* - * Write out the current time to the file so time does not - * reset every time the server reboots. - */ - -void write_todclock(void) +void +init_globals () { - char filename[MAX_BUF]; - FILE *fp; - - sprintf(filename, "%s/clockdata", settings.localdir); - if ((fp = fopen(filename, "w")) == NULL) { - LOG(llevError, "Cannot open %s for writing\n", filename); - return; + if (settings.logfilename[0] == 0) + log_setfd (-1); + else + { + int logfd = open (settings.logfilename, O_CREAT|O_WRONLY|O_APPEND, 0666); + + if (logfd >= 0) + log_setfd (logfd); + else + { + log_setfd (-1); + LOG (llevError, "Unable to open %s as the logfile - will use stderr instead", settings.logfilename); + } } - fprintf(fp, "%lu", todtick); - fclose(fp); } -/* - * Initializes the gametime and TOD counters - * Called by init_library(). - */ - -void init_clocks(void) +void +init_dynamic () { - char filename[MAX_BUF]; - FILE *fp; - static int has_been_done=0; - - if (has_been_done) - return; - else - has_been_done = 1; - - sprintf(filename, "%s/clockdata", settings.localdir); - LOG(llevDebug, "Reading clockdata from %s...", filename); - if ((fp = fopen(filename, "r")) == NULL) { - LOG(llevError, "Can't open %s.\n", filename); - todtick = 0; - write_todclock(); - return; - } - fscanf(fp, "%lu", &todtick); - LOG(llevDebug, "todtick=%lu\n", todtick); - fclose(fp); + first_map_ext_path = "/start/HallsOfSelection"; + first_map_path = "/HallOfSelection"; } /* - * Initializes the attack messages. + * initialises the attack messages. * Called by init_library(). */ //attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS]; -void init_attackmess(void){ - char buf[MAX_BUF]; - char filename[MAX_BUF]; - char *cp, *p; - FILE *fp; - static int has_been_done=0; - int mess, level, comp; - int mode=0, total=0; - - if (has_been_done) - return; - else - has_been_done = 1; - - sprintf(filename, "%s/attackmess", settings.datadir); - LOG(llevDebug, "Reading attack messages from %s...", filename); - if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) { - LOG(llevError, "Can't open %s.\n", filename); - return; - } +void +init_attackmess () +{ + object_thawer thawer (settings.datadir, "attackmess"); - level = 0; - while (fgets(buf, MAX_BUF, fp)!=NULL) { - if (*buf=='#') continue; - if((cp=strchr(buf,'\n'))!=NULL) - *cp='\0'; - cp=buf; - while(*cp==' ') /* Skip blanks */ - cp++; - - if (strncmp(cp, "TYPE:", 5)==0) { - p = strtok(buf, ":"); - p = strtok(NULL, ":"); - if (mode == 1) { - attack_mess[mess][level].level = -1; - attack_mess[mess][level].buf1 = NULL; - attack_mess[mess][level].buf2 = NULL; - attack_mess[mess][level].buf3 = NULL; + if (!thawer) + { + LOG (llevError, "Can't open %s.\n", thawer.name); + return; + } + + int msgnum = -1; + int total = 0; + + while (thawer.kw) + { + if (thawer.kw != KW_type) + if (!thawer.parse_error ("attackmess file")) + break; + + thawer.get (msgnum); + thawer.next (); + + int level = 0; + + while (thawer.kw == KW_hp) + { + // our old friend, dog-slow sscanf + int hp; + char buf1[1024]; + char buf2[1024]; + char buf3[1024]; + + if (4 != sscanf (thawer.value_nn, "%d %1023[^|]|%1023[^|]|%1023[^|]", + &hp, buf1, buf2, buf3)) + thawer.parse_error ("attackmess file"); + else + { + if (*buf2 == '-') + *buf2 = 0; // sscanf can't parse empty fields, so use "-" as marker + + attack_mess[msgnum][level].level = hp; + attack_mess[msgnum][level].buf1 = strdup (buf1); + attack_mess[msgnum][level].buf2 = strdup (buf2); + attack_mess[msgnum][level].buf3 = strdup (buf3); + + ++level; + ++total; } - level = 0; - mess = atoi(p); - mode = 1; - continue; - } - if (mode==1) { - p = strtok(buf, "="); - attack_mess[mess][level].level = atoi(buf); - p = strtok(NULL, "="); - if (p != NULL) - attack_mess[mess][level].buf1 = strdup_local(p); - else - attack_mess[mess][level].buf1 = strdup_local(""); - mode = 2; - continue; - } else if (mode==2) { - p = strtok(buf, "="); - attack_mess[mess][level].level = atoi(buf); - p = strtok(NULL, "="); - if (p != NULL) - attack_mess[mess][level].buf2 = strdup_local(p); - else - attack_mess[mess][level].buf2 = strdup_local(""); - mode = 3; - continue; - } else if (mode==3) { - p = strtok(buf, "="); - attack_mess[mess][level].level = atoi(buf); - p = strtok(NULL, "="); - if (p != NULL) - attack_mess[mess][level].buf3 = strdup_local(p); - else - attack_mess[mess][level].buf3 = strdup_local(""); - mode = 1; - level++; - total++; - continue; + + thawer.next (); } + + attack_mess[msgnum][level].level = -1; + attack_mess[msgnum][level].buf1 = 0; + attack_mess[msgnum][level].buf2 = 0; + attack_mess[msgnum][level].buf3 = 0; } - LOG(llevDebug, "got %d messages in %d categories.\n", total, mess+1); - close_and_delete(fp, comp); + + LOG (llevDebug, "got %d messages in %d categories.\n", total, msgnum + 1); } +