ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/init.c
Revision: 1.4
Committed: Wed Mar 15 15:35:46 2006 UTC (18 years, 2 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.3: +3 -1 lines
Log Message:
UPSTREAM merge from 15.03.2006

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