ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.c
Revision: 1.3
Committed: Wed Feb 22 18:53:48 2006 UTC (18 years, 3 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.2: +5 -3 lines
Log Message:
UPSTREAM_2006-02-22 merge

File Contents

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