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, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.9: +354 -303 lines
Log Message:
indent

File Contents

# Content
1
2 /*
3 * static char *rcsid_init_c =
4 * "$Id: init.C,v 1.9 2006-09-09 23:49:06 root Exp $";
5 */
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 #define EXTERN // horrible hack
31
32 #include <global.h>
33 #include <object.h>
34
35 extern const char *const attacktype_desc[NROFATTACKS] = {
36 #define def(uc, lc, name, plus, change) # name,
37 #include "attackinc.h"
38 #undef def
39 };
40
41 extern const keyword resist_save[NROFATTACKS] = {
42 #define def(uc, lc, name, plus, change) KW_resist_ ## lc,
43 #include "attackinc.h"
44 #undef def
45 };
46
47 extern const char *const resist_plus[NROFATTACKS] = {
48 #define def(uc, lc, name, plus, change) # plus,
49 #include "attackinc.h"
50 #undef def
51 };
52
53 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 };
58
59 int resist_table[NROFATTACKS] = {
60 #define def(uc, lc, name, plus, change) ATNR_ ## uc,
61 #include "attackinc.h"
62 #undef def
63 };
64
65 /* You unforunately need to looking in include/global.h to see what these
66 * correspond to.
67 */
68 struct Settings settings = {
69 LOGFILE, /* Logfile */
70 CSPORT, /* Client/server port */
71
72 /* Debug level */
73 #ifdef DEBUG
74 llevDebug,
75 #else
76 llevInfo,
77 #endif
78
79 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 /* Armor enchantment stuff */
125 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 };
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 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 };
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 static void
170 init_emergency_mappath (void)
171 {
172 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 }
190 else if (online == 1)
191 {
192 settings.emergency_x = atoi (tmpbuf);
193 }
194
195 else if (online == 2)
196 {
197 settings.emergency_y = atoi (tmpbuf);
198 }
199 online++;
200 if (online > 2)
201 break;
202 }
203 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 }
208 }
209
210
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 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 }
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 void
245 init_environ (void)
246 {
247 char *cp;
248
249 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 }
277
278
279 /*
280 * Initialises all global variables.
281 * Might use environment-variables as default for some of them.
282 */
283
284 void
285 init_globals (void)
286 {
287 if (settings.logfilename[0] == 0)
288 {
289 logfile = stderr;
290 }
291 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 }
296 else
297 {
298 setvbuf (logfile, NULL, _IOLBF, 0);
299 }
300 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 }
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 void
328 init_objects (void)
329 {
330 /* Initialize all objects: */
331 objects = NULL;
332 active_objects = NULL;
333 }
334
335 /*
336 * Initialises global variables which can be changed by options.
337 * Called by init_library().
338 */
339
340 void
341 init_defaults (void)
342 {
343 editor = 0;
344 nroferrors = 0;
345 }
346
347
348 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 }
361 if (EXIT_PATH (&at->clone))
362 {
363 strcpy (first_map_path, EXIT_PATH (&at->clone));
364 return;
365 }
366 }
367 at = at->next;
368 }
369 LOG (llevDebug, "You Need a archetype called 'map' and it have to contain start map\n");
370 exit (-1);
371 }
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 void
381 write_todclock (void)
382 {
383 char filename[MAX_BUF];
384 FILE *fp;
385
386 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 }
392 fprintf (fp, "%lu", todtick);
393 fclose (fp);
394 }
395
396 /*
397 * Initializes the gametime and TOD counters
398 * Called by init_library().
399 */
400
401 void
402 init_clocks (void)
403 {
404 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 }
422 fscanf (fp, "%lu", &todtick);
423 LOG (llevDebug, "todtick=%lu\n", todtick);
424 fclose (fp);
425 }
426
427 /*
428 * Initializes the attack messages.
429 * Called by init_library().
430 */
431
432 //attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS];
433
434 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 }
457
458 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 }
480 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 }
509 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 }
523 }
524 LOG (llevDebug, "got %d messages in %d categories.\n", total, mess + 1);
525 close_and_delete (fp, comp);
526 }