ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.C
Revision: 1.10
Committed: Sun Sep 10 16:00:23 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.9: +354 -303 lines
Log Message:
indent

File Contents

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