ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.c
Revision: 1.5
Committed: Fri Apr 21 14:40:29 2006 UTC (18 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.4: +9 -4 lines
Log Message:
Adding support for race-specific HallsOfSelection

File Contents

# User Rev Content
1 root 1.1 /*
2     * static char *rcsid_init_c =
3 elmex 1.3 * "$Id$";
4 root 1.1 */
5    
6     /*
7     CrossFire, A Multiplayer game for X-windows
8    
9     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10     Copyright (C) 1992 Frank Tore Johansen
11    
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16    
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20     GNU General Public License for more details.
21    
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25    
26     The authors can be reached via e-mail at crossfire-devel@real-time.com
27     */
28    
29     #define EXTERN
30     #define INIT_C
31     #include <global.h>
32     #include <object.h>
33    
34     /* You unforunately need to looking in include/global.h to see what these
35     * correspond to.
36     */
37     struct Settings settings = {
38     LOGFILE, /* Logfile */
39     CSPORT, /* Client/server port */
40    
41     /* Debug level */
42     #ifdef DEBUG
43     llevDebug,
44     #else
45     llevInfo,
46     #endif
47    
48     0, NULL, 0, /* dumpvalues, dumparg, daemonmode */
49     0, /* argc */
50     NULL, /* argv */
51     CONFDIR,
52     DATADIR,
53     LOCALDIR,
54     PLAYERDIR, MAPDIR, ARCHETYPES,REGIONS,TREASURES,
55     UNIQUE_DIR, TEMPLATE_DIR,
56     TMPDIR,
57     STAT_LOSS_ON_DEATH,
58     PK_LUCK_PENALTY,
59 elmex 1.4 PERMANENT_EXPERIENCE_RATIO,
60     DEATH_PENALTY_RATIO,
61     DEATH_PENALTY_LEVEL,
62 root 1.1 BALANCED_STAT_LOSS,
63     NOT_PERMADETH,
64     SIMPLE_EXP,
65     RESET_LOCATION_TIME,
66     SET_TITLE,
67     RESURRECTION,
68     SEARCH_ITEMS,
69     SPELL_ENCUMBRANCE,
70     SPELL_FAILURE_EFFECTS,
71     CASTING_TIME,
72     REAL_WIZ,
73     RECYCLE_TMP_MAPS,
74     EXPLORE_MODE,
75     SPELLPOINT_LEVEL_DEPEND,
76     SET_FRIENDLY_FIRE,
77     "", /* Who format specifier */
78     "", /* who wiz format specifier */
79     MOTD,
80     "rules",
81     "news",
82     "", /* DM_MAIL */
83     0, /* This and the next 3 values are metaserver values */
84     "",
85     "",
86     0,
87     "",
88     0,0,0,0,0,0,0,0, /* worldmap settings*/
89     EMERGENCY_MAPPATH, EMERGENCY_X, EMERGENCY_Y,
90     0,
91     1.0,
92     /* Armor enchantment stuff */
93     ARMOR_MAX_ENCHANT,
94     ARMOR_WEIGHT_REDUCTION,
95     ARMOR_WEIGHT_LINEAR,
96     ARMOR_SPEED_IMPROVEMENT,
97     ARMOR_SPEED_LINEAR,
98     1, /* no_player_stealing */
99     };
100    
101     /* perhaps not the best place for this, but needs to be
102     * in some file in the common area so that standalone
103     * programs, like the random map generator, can be built.
104     */
105 elmex 1.3 const char* const spellpathnames[NRSPELLPATHS] = {
106 root 1.1 "Protection",
107     "Fire",
108     "Frost",
109     "Electricity",
110     "Missiles",
111     "Self",
112     "Summoning",
113     "Abjuration",
114     "Restoration",
115     "Detonation",
116     "Mind",
117     "Creation",
118     "Teleportation",
119     "Information",
120     "Transmutation",
121     "Transferrence",
122     "Turning",
123     "Wounding",
124     "Death",
125     "Light"
126     };
127    
128    
129     /* This loads the emergency map information from a
130     * .emergency file in the map directory. Doing this makes
131     * it easier to switch between map distributions (don't need
132     * to recompile. Note that there is no reason I see that
133     * this could not be re-loaded during play, but it seems
134     * like there should be little reason to do that.
135     */
136     static void init_emergency_mappath(void)
137     {
138     char filename[MAX_BUF], tmpbuf[MAX_BUF];
139     FILE *fp;
140     int online=0;
141    
142     /* If this file doesn't exist, not a big deal */
143     sprintf(filename,"%s/%s/.emergency",settings.datadir, settings.mapdir);
144     if ((fp = fopen(filename, "r"))!=NULL) {
145     while (fgets(tmpbuf, MAX_BUF-1, fp)) {
146     if (tmpbuf[0] == '#') continue; /* ignore comments */
147    
148     if (online == 0) {
149     tmpbuf[strlen(tmpbuf)-1] = 0; /* kill newline */
150     settings.emergency_mapname = strdup_local(tmpbuf);
151     }
152     else if (online == 1) {
153     settings.emergency_x = atoi(tmpbuf);
154     }
155    
156     else if (online == 2) {
157     settings.emergency_y = atoi(tmpbuf);
158     }
159     online++;
160     if (online>2) break;
161     }
162     fclose(fp);
163     if (online<=2)
164     LOG(llevError,"Online read partial data from %s\n", filename);
165     LOG(llevDebug,"Emergency mappath reset to %s (%d, %d)\n", settings.emergency_mapname,
166     settings.emergency_x, settings.emergency_y);
167     }
168     }
169    
170    
171     /*
172     * It is vital that init_library() is called by any functions
173     * using this library.
174     * If you want to lessen the size of the program using the library,
175     * you can replace the call to init_library() with init_globals() and
176     * init_function_pointers(). Good idea to also call init_vars and
177     * init_hash_table if you are doing any object loading.
178     */
179    
180     void init_library(void) {
181     init_environ();
182     init_globals();
183     init_hash_table();
184     init_objects();
185     init_vars();
186     init_block();
187     ReadBmapNames ();
188     ReadSmooth();
189     init_anim(); /* Must be after we read in the bitmaps */
190     init_archetypes(); /* Reads all archetypes from file */
191     init_dynamic ();
192     init_attackmess();
193     init_clocks();
194     init_emergency_mappath();
195     init_experience();
196     }
197    
198    
199     /* init_environ initializes values from the environmental variables.
200     * it needs to be called very early, since command line options should
201     * overwrite these if specified.
202     */
203     void init_environ(void) {
204     char *cp;
205    
206     cp=getenv("CROSSFIRE_LIBDIR");
207     if (cp) settings.datadir=cp;
208     cp=getenv("CROSSFIRE_LOCALDIR");
209     if (cp) settings.localdir=cp;
210     cp=getenv("CROSSFIRE_PLAYERDIR");
211     if (cp) settings.playerdir=cp;
212     cp=getenv("CROSSFIRE_MAPDIR");
213     if (cp) settings.mapdir=cp;
214     cp=getenv("CROSSFIRE_ARCHETYPES");
215     if (cp) settings.archetypes=cp;
216     cp=getenv("CROSSFIRE_TREASURES");
217     if (cp) settings.treasures=cp;
218     cp=getenv("CROSSFIRE_UNIQUEDIR");
219     if (cp) settings.uniquedir=cp;
220     cp=getenv("CROSSFIRE_TEMPLATEDIR");
221     if (cp) settings.templatedir=cp;
222     cp=getenv("CROSSFIRE_TMPDIR");
223     if (cp) settings.tmpdir=cp;
224     }
225    
226    
227     /*
228     * Initialises all global variables.
229     * Might use environment-variables as default for some of them.
230     */
231    
232     void init_globals(void) {
233     if (settings.logfilename[0] == 0) {
234     logfile = stderr;
235     }
236     else if ((logfile=fopen(settings.logfilename, "a"))==NULL) {
237     fprintf(stderr,"Unable to open %s as the logfile - will use stderr instead\n",
238     settings.logfilename);
239     logfile = stderr;
240     }
241 elmex 1.3 else {
242     setvbuf(logfile, NULL, _IOLBF, 0);
243     }
244 root 1.1 exiting = 0;
245     first_player=NULL;
246     first_friendly_object=NULL;
247     first_map=NULL;
248     first_treasurelist=NULL;
249     first_artifactlist=NULL;
250     first_archetype=NULL;
251 pippijn 1.5 *first_map_ext_path=0;
252 root 1.1 warn_archetypes=0;
253     nroftreasures = 0;
254     nrofartifacts = 0;
255     nrofallowedstr=0;
256     ring_arch = NULL;
257     amulet_arch = NULL;
258     staff_arch = NULL;
259     undead_name = add_string("undead");
260     trying_emergency_save = 0;
261     num_animations=0;
262     animations=NULL;
263     animations_allocated=0;
264     init_defaults();
265     }
266    
267     /*
268     * Sets up and initialises the linked list of free and used objects.
269     * Allocates a certain chunk of objects and puts them on the free list.
270     * Called by init_library();
271     */
272    
273     void init_objects(void) {
274     int i;
275     /* Initialize all objects: */
276     objects=NULL;
277     active_objects = NULL;
278    
279     #ifdef MEMORY_DEBUG
280     free_objects=NULL;
281     #else
282     free_objects=objarray;
283     objarray[0].prev=NULL,
284     objarray[0].next= &objarray[1],
285     SET_FLAG(&objarray[0], FLAG_REMOVED);
286     SET_FLAG(&objarray[0], FLAG_FREED);
287     for(i=1;i<STARTMAX-1;i++) {
288     objarray[i].next= &objarray[i+1];
289     objarray[i].prev= &objarray[i-1];
290     SET_FLAG(&objarray[i], FLAG_REMOVED);
291     SET_FLAG(&objarray[i], FLAG_FREED);
292     }
293     objarray[STARTMAX-1].next=NULL;
294     objarray[STARTMAX-1].prev= &objarray[STARTMAX-2];
295     SET_FLAG(&objarray[STARTMAX-1], FLAG_REMOVED);
296     SET_FLAG(&objarray[STARTMAX-1], FLAG_FREED);
297     #endif
298     }
299    
300     /*
301     * Initialises global variables which can be changed by options.
302     * Called by init_library().
303     */
304    
305     void init_defaults(void) {
306     editor=0;
307     nroferrors=0;
308     }
309    
310    
311     void init_dynamic (void) {
312     archetype *at = first_archetype;
313     while (at) {
314 pippijn 1.5 if (at->clone.type == MAP) {
315     if (at->clone.race) {
316     strcpy (first_map_ext_path, at->clone.race);
317     }
318     if (EXIT_PATH (&at->clone)) {
319     strcpy (first_map_path, EXIT_PATH (&at->clone));
320     return;
321     }
322 root 1.1 }
323     at = at->next;
324     }
325     LOG(llevDebug,"You Need a archetype called 'map' and it have to contain start map\n");
326     exit (-1);
327     }
328    
329     unsigned long todtick;
330    
331     /*
332     * Write out the current time to the file so time does not
333     * reset every time the server reboots.
334     */
335    
336     void write_todclock(void)
337     {
338     char filename[MAX_BUF];
339     FILE *fp;
340    
341     sprintf(filename, "%s/clockdata", settings.localdir);
342     if ((fp = fopen(filename, "w")) == NULL) {
343     LOG(llevError, "Cannot open %s for writing\n", filename);
344     return;
345     }
346     fprintf(fp, "%lu", todtick);
347     fclose(fp);
348     }
349    
350     /*
351     * Initializes the gametime and TOD counters
352     * Called by init_library().
353     */
354    
355     void init_clocks(void)
356     {
357     char filename[MAX_BUF];
358     FILE *fp;
359     static int has_been_done=0;
360    
361     if (has_been_done)
362     return;
363     else
364     has_been_done = 1;
365    
366     sprintf(filename, "%s/clockdata", settings.localdir);
367     LOG(llevDebug, "Reading clockdata from %s...", filename);
368     if ((fp = fopen(filename, "r")) == NULL) {
369     LOG(llevError, "Can't open %s.\n", filename);
370     todtick = 0;
371     write_todclock();
372     return;
373     }
374     fscanf(fp, "%lu", &todtick);
375     LOG(llevDebug, "todtick=%lu\n", todtick);
376     fclose(fp);
377     }
378    
379     /*
380     * Initializes the attack messages.
381     * Called by init_library().
382     */
383    
384     attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS];
385    
386     void init_attackmess(void){
387     char buf[MAX_BUF];
388     char filename[MAX_BUF];
389     char *cp, *p;
390     FILE *fp;
391     static int has_been_done=0;
392     int mess, level, comp;
393     int mode=0, total=0;
394    
395     if (has_been_done)
396     return;
397     else
398     has_been_done = 1;
399    
400     sprintf(filename, "%s/attackmess", settings.datadir);
401     LOG(llevDebug, "Reading attack messages from %s...", filename);
402     if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
403     LOG(llevError, "Can't open %s.\n", filename);
404     return;
405     }
406    
407     level = 0;
408     while (fgets(buf, MAX_BUF, fp)!=NULL) {
409     if (*buf=='#') continue;
410     if((cp=strchr(buf,'\n'))!=NULL)
411     *cp='\0';
412     cp=buf;
413     while(*cp==' ') /* Skip blanks */
414     cp++;
415    
416     if (strncmp(cp, "TYPE:", 5)==0) {
417     p = strtok(buf, ":");
418     p = strtok(NULL, ":");
419     if (mode == 1) {
420     attack_mess[mess][level].level = -1;
421     attack_mess[mess][level].buf1 = NULL;
422     attack_mess[mess][level].buf2 = NULL;
423     attack_mess[mess][level].buf3 = NULL;
424     }
425     level = 0;
426     mess = atoi(p);
427     mode = 1;
428     continue;
429     }
430     if (mode==1) {
431     p = strtok(buf, "=");
432     attack_mess[mess][level].level = atoi(buf);
433     p = strtok(NULL, "=");
434     if (p != NULL)
435     attack_mess[mess][level].buf1 = strdup_local(p);
436     else
437     attack_mess[mess][level].buf1 = strdup_local("");
438     mode = 2;
439     continue;
440     } else if (mode==2) {
441     p = strtok(buf, "=");
442     attack_mess[mess][level].level = atoi(buf);
443     p = strtok(NULL, "=");
444     if (p != NULL)
445     attack_mess[mess][level].buf2 = strdup_local(p);
446     else
447     attack_mess[mess][level].buf2 = strdup_local("");
448     mode = 3;
449     continue;
450     } else if (mode==3) {
451     p = strtok(buf, "=");
452     attack_mess[mess][level].level = atoi(buf);
453     p = strtok(NULL, "=");
454     if (p != NULL)
455     attack_mess[mess][level].buf3 = strdup_local(p);
456     else
457     attack_mess[mess][level].buf3 = strdup_local("");
458     mode = 1;
459     level++;
460     total++;
461     continue;
462     }
463     }
464     LOG(llevDebug, "got %d messages in %d categories.\n", total, mess+1);
465     close_and_delete(fp, comp);
466     }