ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.c
Revision: 1.6
Committed: Fri Apr 28 13:56:25 2006 UTC (18 years ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: LAST_C_VERSION, difficulty_fix_merge_060810_2300
Branch point for: difficulty_fix
Changes since 1.5: +1 -0 lines
Log Message:
Adding setting to allow for portals in apartments and other personal maps.

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 pippijn 1.6 1, /* create_home_portals */
100 root 1.1 };
101    
102     /* perhaps not the best place for this, but needs to be
103     * in some file in the common area so that standalone
104     * programs, like the random map generator, can be built.
105     */
106 elmex 1.3 const char* const spellpathnames[NRSPELLPATHS] = {
107 root 1.1 "Protection",
108     "Fire",
109     "Frost",
110     "Electricity",
111     "Missiles",
112     "Self",
113     "Summoning",
114     "Abjuration",
115     "Restoration",
116     "Detonation",
117     "Mind",
118     "Creation",
119     "Teleportation",
120     "Information",
121     "Transmutation",
122     "Transferrence",
123     "Turning",
124     "Wounding",
125     "Death",
126     "Light"
127     };
128    
129    
130     /* This loads the emergency map information from a
131     * .emergency file in the map directory. Doing this makes
132     * it easier to switch between map distributions (don't need
133     * to recompile. Note that there is no reason I see that
134     * this could not be re-loaded during play, but it seems
135     * like there should be little reason to do that.
136     */
137     static void init_emergency_mappath(void)
138     {
139     char filename[MAX_BUF], tmpbuf[MAX_BUF];
140     FILE *fp;
141     int online=0;
142    
143     /* If this file doesn't exist, not a big deal */
144     sprintf(filename,"%s/%s/.emergency",settings.datadir, settings.mapdir);
145     if ((fp = fopen(filename, "r"))!=NULL) {
146     while (fgets(tmpbuf, MAX_BUF-1, fp)) {
147     if (tmpbuf[0] == '#') continue; /* ignore comments */
148    
149     if (online == 0) {
150     tmpbuf[strlen(tmpbuf)-1] = 0; /* kill newline */
151     settings.emergency_mapname = strdup_local(tmpbuf);
152     }
153     else if (online == 1) {
154     settings.emergency_x = atoi(tmpbuf);
155     }
156    
157     else if (online == 2) {
158     settings.emergency_y = atoi(tmpbuf);
159     }
160     online++;
161     if (online>2) break;
162     }
163     fclose(fp);
164     if (online<=2)
165     LOG(llevError,"Online read partial data from %s\n", filename);
166     LOG(llevDebug,"Emergency mappath reset to %s (%d, %d)\n", settings.emergency_mapname,
167     settings.emergency_x, settings.emergency_y);
168     }
169     }
170    
171    
172     /*
173     * It is vital that init_library() is called by any functions
174     * using this library.
175     * If you want to lessen the size of the program using the library,
176     * you can replace the call to init_library() with init_globals() and
177     * init_function_pointers(). Good idea to also call init_vars and
178     * init_hash_table if you are doing any object loading.
179     */
180    
181     void init_library(void) {
182     init_environ();
183     init_globals();
184     init_hash_table();
185     init_objects();
186     init_vars();
187     init_block();
188     ReadBmapNames ();
189     ReadSmooth();
190     init_anim(); /* Must be after we read in the bitmaps */
191     init_archetypes(); /* Reads all archetypes from file */
192     init_dynamic ();
193     init_attackmess();
194     init_clocks();
195     init_emergency_mappath();
196     init_experience();
197     }
198    
199    
200     /* init_environ initializes values from the environmental variables.
201     * it needs to be called very early, since command line options should
202     * overwrite these if specified.
203     */
204     void init_environ(void) {
205     char *cp;
206    
207     cp=getenv("CROSSFIRE_LIBDIR");
208     if (cp) settings.datadir=cp;
209     cp=getenv("CROSSFIRE_LOCALDIR");
210     if (cp) settings.localdir=cp;
211     cp=getenv("CROSSFIRE_PLAYERDIR");
212     if (cp) settings.playerdir=cp;
213     cp=getenv("CROSSFIRE_MAPDIR");
214     if (cp) settings.mapdir=cp;
215     cp=getenv("CROSSFIRE_ARCHETYPES");
216     if (cp) settings.archetypes=cp;
217     cp=getenv("CROSSFIRE_TREASURES");
218     if (cp) settings.treasures=cp;
219     cp=getenv("CROSSFIRE_UNIQUEDIR");
220     if (cp) settings.uniquedir=cp;
221     cp=getenv("CROSSFIRE_TEMPLATEDIR");
222     if (cp) settings.templatedir=cp;
223     cp=getenv("CROSSFIRE_TMPDIR");
224     if (cp) settings.tmpdir=cp;
225     }
226    
227    
228     /*
229     * Initialises all global variables.
230     * Might use environment-variables as default for some of them.
231     */
232    
233     void init_globals(void) {
234     if (settings.logfilename[0] == 0) {
235     logfile = stderr;
236     }
237     else if ((logfile=fopen(settings.logfilename, "a"))==NULL) {
238     fprintf(stderr,"Unable to open %s as the logfile - will use stderr instead\n",
239     settings.logfilename);
240     logfile = stderr;
241     }
242 elmex 1.3 else {
243     setvbuf(logfile, NULL, _IOLBF, 0);
244     }
245 root 1.1 exiting = 0;
246     first_player=NULL;
247     first_friendly_object=NULL;
248     first_map=NULL;
249     first_treasurelist=NULL;
250     first_artifactlist=NULL;
251     first_archetype=NULL;
252 pippijn 1.5 *first_map_ext_path=0;
253 root 1.1 warn_archetypes=0;
254     nroftreasures = 0;
255     nrofartifacts = 0;
256     nrofallowedstr=0;
257     ring_arch = NULL;
258     amulet_arch = NULL;
259     staff_arch = NULL;
260     undead_name = add_string("undead");
261     trying_emergency_save = 0;
262     num_animations=0;
263     animations=NULL;
264     animations_allocated=0;
265     init_defaults();
266     }
267    
268     /*
269     * Sets up and initialises the linked list of free and used objects.
270     * Allocates a certain chunk of objects and puts them on the free list.
271     * Called by init_library();
272     */
273    
274     void init_objects(void) {
275     int i;
276     /* Initialize all objects: */
277     objects=NULL;
278     active_objects = NULL;
279    
280     #ifdef MEMORY_DEBUG
281     free_objects=NULL;
282     #else
283     free_objects=objarray;
284     objarray[0].prev=NULL,
285     objarray[0].next= &objarray[1],
286     SET_FLAG(&objarray[0], FLAG_REMOVED);
287     SET_FLAG(&objarray[0], FLAG_FREED);
288     for(i=1;i<STARTMAX-1;i++) {
289     objarray[i].next= &objarray[i+1];
290     objarray[i].prev= &objarray[i-1];
291     SET_FLAG(&objarray[i], FLAG_REMOVED);
292     SET_FLAG(&objarray[i], FLAG_FREED);
293     }
294     objarray[STARTMAX-1].next=NULL;
295     objarray[STARTMAX-1].prev= &objarray[STARTMAX-2];
296     SET_FLAG(&objarray[STARTMAX-1], FLAG_REMOVED);
297     SET_FLAG(&objarray[STARTMAX-1], FLAG_FREED);
298     #endif
299     }
300    
301     /*
302     * Initialises global variables which can be changed by options.
303     * Called by init_library().
304     */
305    
306     void init_defaults(void) {
307     editor=0;
308     nroferrors=0;
309     }
310    
311    
312     void init_dynamic (void) {
313     archetype *at = first_archetype;
314     while (at) {
315 pippijn 1.5 if (at->clone.type == MAP) {
316     if (at->clone.race) {
317     strcpy (first_map_ext_path, at->clone.race);
318     }
319     if (EXIT_PATH (&at->clone)) {
320     strcpy (first_map_path, EXIT_PATH (&at->clone));
321     return;
322     }
323 root 1.1 }
324     at = at->next;
325     }
326     LOG(llevDebug,"You Need a archetype called 'map' and it have to contain start map\n");
327     exit (-1);
328     }
329    
330     unsigned long todtick;
331    
332     /*
333     * Write out the current time to the file so time does not
334     * reset every time the server reboots.
335     */
336    
337     void write_todclock(void)
338     {
339     char filename[MAX_BUF];
340     FILE *fp;
341    
342     sprintf(filename, "%s/clockdata", settings.localdir);
343     if ((fp = fopen(filename, "w")) == NULL) {
344     LOG(llevError, "Cannot open %s for writing\n", filename);
345     return;
346     }
347     fprintf(fp, "%lu", todtick);
348     fclose(fp);
349     }
350    
351     /*
352     * Initializes the gametime and TOD counters
353     * Called by init_library().
354     */
355    
356     void init_clocks(void)
357     {
358     char filename[MAX_BUF];
359     FILE *fp;
360     static int has_been_done=0;
361    
362     if (has_been_done)
363     return;
364     else
365     has_been_done = 1;
366    
367     sprintf(filename, "%s/clockdata", settings.localdir);
368     LOG(llevDebug, "Reading clockdata from %s...", filename);
369     if ((fp = fopen(filename, "r")) == NULL) {
370     LOG(llevError, "Can't open %s.\n", filename);
371     todtick = 0;
372     write_todclock();
373     return;
374     }
375     fscanf(fp, "%lu", &todtick);
376     LOG(llevDebug, "todtick=%lu\n", todtick);
377     fclose(fp);
378     }
379    
380     /*
381     * Initializes the attack messages.
382     * Called by init_library().
383     */
384    
385     attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS];
386    
387     void init_attackmess(void){
388     char buf[MAX_BUF];
389     char filename[MAX_BUF];
390     char *cp, *p;
391     FILE *fp;
392     static int has_been_done=0;
393     int mess, level, comp;
394     int mode=0, total=0;
395    
396     if (has_been_done)
397     return;
398     else
399     has_been_done = 1;
400    
401     sprintf(filename, "%s/attackmess", settings.datadir);
402     LOG(llevDebug, "Reading attack messages from %s...", filename);
403     if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
404     LOG(llevError, "Can't open %s.\n", filename);
405     return;
406     }
407    
408     level = 0;
409     while (fgets(buf, MAX_BUF, fp)!=NULL) {
410     if (*buf=='#') continue;
411     if((cp=strchr(buf,'\n'))!=NULL)
412     *cp='\0';
413     cp=buf;
414     while(*cp==' ') /* Skip blanks */
415     cp++;
416    
417     if (strncmp(cp, "TYPE:", 5)==0) {
418     p = strtok(buf, ":");
419     p = strtok(NULL, ":");
420     if (mode == 1) {
421     attack_mess[mess][level].level = -1;
422     attack_mess[mess][level].buf1 = NULL;
423     attack_mess[mess][level].buf2 = NULL;
424     attack_mess[mess][level].buf3 = NULL;
425     }
426     level = 0;
427     mess = atoi(p);
428     mode = 1;
429     continue;
430     }
431     if (mode==1) {
432     p = strtok(buf, "=");
433     attack_mess[mess][level].level = atoi(buf);
434     p = strtok(NULL, "=");
435     if (p != NULL)
436     attack_mess[mess][level].buf1 = strdup_local(p);
437     else
438     attack_mess[mess][level].buf1 = strdup_local("");
439     mode = 2;
440     continue;
441     } else if (mode==2) {
442     p = strtok(buf, "=");
443     attack_mess[mess][level].level = atoi(buf);
444     p = strtok(NULL, "=");
445     if (p != NULL)
446     attack_mess[mess][level].buf2 = strdup_local(p);
447     else
448     attack_mess[mess][level].buf2 = strdup_local("");
449     mode = 3;
450     continue;
451     } else if (mode==3) {
452     p = strtok(buf, "=");
453     attack_mess[mess][level].level = atoi(buf);
454     p = strtok(NULL, "=");
455     if (p != NULL)
456     attack_mess[mess][level].buf3 = strdup_local(p);
457     else
458     attack_mess[mess][level].buf3 = strdup_local("");
459     mode = 1;
460     level++;
461     total++;
462     continue;
463     }
464     }
465     LOG(llevDebug, "got %d messages in %d categories.\n", total, mess+1);
466     close_and_delete(fp, comp);
467     }