ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.C
Revision: 1.15
Committed: Wed Dec 13 02:55:49 2006 UTC (17 years, 5 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.14: +0 -7 lines
Log Message:
- medium decruftification
- medium cleanups
- make settings accessible to perl using cf::settings->mutator
  (completely untested)

File Contents

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