00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #define EXTERN
00035 #define INIT_C
00036 #include <global.h>
00037 #include <object.h>
00038
00039 static void init_environ(void);
00040 static void init_defaults(void);
00041 static void init_dynamic(void);
00042 static void init_clocks(void);
00043 static void init_attackmess(void);
00044
00048 struct Settings settings = {
00049 LOGFILE,
00050 CSPORT,
00051
00052
00053 #ifdef DEBUG
00054 llevDebug,
00055 #else
00056 llevInfo,
00057 #endif
00058 0, NULL, 0,
00059 0,
00060 NULL,
00061 CONFDIR,
00062 DATADIR,
00063 LOCALDIR,
00064 PLAYERDIR, MAPDIR, ARCHETYPES, REGIONS, TREASURES,
00065 UNIQUE_DIR, TEMPLATE_DIR,
00066 TMPDIR,
00067 STAT_LOSS_ON_DEATH,
00068 PK_LUCK_PENALTY,
00069 PERMANENT_EXPERIENCE_RATIO,
00070 DEATH_PENALTY_RATIO,
00071 DEATH_PENALTY_LEVEL,
00072 BALANCED_STAT_LOSS,
00073 NOT_PERMADETH,
00074 SIMPLE_EXP,
00075 RESET_LOCATION_TIME,
00076 SET_TITLE,
00077 RESURRECTION,
00078 SEARCH_ITEMS,
00079 SPELL_ENCUMBRANCE,
00080 SPELL_FAILURE_EFFECTS,
00081 CASTING_TIME,
00082 REAL_WIZ,
00083 RECYCLE_TMP_MAPS,
00084 EXPLORE_MODE,
00085 SPELLPOINT_LEVEL_DEPEND,
00086 SET_FRIENDLY_FIRE,
00087 "",
00088 "",
00089 MOTD,
00090 "rules",
00091 "news",
00092 "",
00093 0,
00094 "",
00095 "",
00096 0,
00097 "",
00098 0, 0, 0, 0, 0, 0, 0,
00099 EMERGENCY_MAPPATH, EMERGENCY_X, EMERGENCY_Y,
00100 0,
00101 1.0,
00102
00103 ARMOR_MAX_ENCHANT,
00104 ARMOR_WEIGHT_REDUCTION,
00105 ARMOR_WEIGHT_LINEAR,
00106 ARMOR_SPEED_IMPROVEMENT,
00107 ARMOR_SPEED_LINEAR,
00108 1,
00109 0,
00110 1,
00111 5000000,
00112 10,
00113 0,
00114 0,
00115 0,
00116 NULL,
00117 };
00118
00119 struct Statistics statistics;
00120
00126 const char *const spellpathnames[NRSPELLPATHS] = {
00127 "Protection",
00128 "Fire",
00129 "Frost",
00130 "Electricity",
00131 "Missiles",
00132 "Self",
00133 "Summoning",
00134 "Abjuration",
00135 "Restoration",
00136 "Detonation",
00137 "Mind",
00138 "Creation",
00139 "Teleportation",
00140 "Information",
00141 "Transmutation",
00142 "Transferrence",
00143 "Turning",
00144 "Wounding",
00145 "Death",
00146 "Light"
00147 };
00148
00149
00161 static void init_emergency_mappath(void) {
00162 char filename[MAX_BUF], tmpbuf[MAX_BUF];
00163 FILE *fp;
00164 int online = 0;
00165
00166
00167 snprintf(filename, sizeof(filename), "%s/%s/.emergency", settings.datadir, settings.mapdir);
00168 if ((fp = fopen(filename, "r")) != NULL) {
00169 while (fgets(tmpbuf, MAX_BUF-1, fp)) {
00170 if (tmpbuf[0] == '#')
00171 continue;
00172
00173 if (online == 0) {
00174 tmpbuf[strlen(tmpbuf)-1] = 0;
00175 settings.emergency_mapname = strdup_local(tmpbuf);
00176 } else if (online == 1) {
00177 settings.emergency_x = atoi(tmpbuf);
00178 } else if (online == 2) {
00179 settings.emergency_y = atoi(tmpbuf);
00180 }
00181 online++;
00182 if (online > 2)
00183 break;
00184 }
00185 fclose(fp);
00186 if (online <= 2)
00187 LOG(llevError, "Online read partial data from %s\n", filename);
00188 LOG(llevDebug, "Emergency mappath reset to %s (%d, %d)\n", settings.emergency_mapname, settings.emergency_x, settings.emergency_y);
00189 }
00190 }
00191
00192
00201 void init_library(void) {
00202 init_environ();
00203 init_globals();
00204 init_hash_table();
00205 i18n_init();
00206 init_objects();
00207 init_vars();
00208 init_block();
00209 read_bmap_names();
00210 read_smooth();
00211 init_anim();
00212 init_archetypes();
00213 init_attackmess();
00214 init_clocks();
00215 init_emergency_mappath();
00216 init_experience();
00217 init_dynamic();
00218 }
00219
00225 static void init_environ(void) {
00226 char *cp;
00227
00228 cp = getenv("CROSSFIRE_LIBDIR");
00229 if (cp)
00230 settings.datadir = cp;
00231 cp = getenv("CROSSFIRE_LOCALDIR");
00232 if (cp)
00233 settings.localdir = cp;
00234 cp = getenv("CROSSFIRE_PLAYERDIR");
00235 if (cp)
00236 settings.playerdir = cp;
00237 cp = getenv("CROSSFIRE_MAPDIR");
00238 if (cp)
00239 settings.mapdir = cp;
00240 cp = getenv("CROSSFIRE_ARCHETYPES");
00241 if (cp)
00242 settings.archetypes = cp;
00243 cp = getenv("CROSSFIRE_TREASURES");
00244 if (cp)
00245 settings.treasures = cp;
00246 cp = getenv("CROSSFIRE_UNIQUEDIR");
00247 if (cp)
00248 settings.uniquedir = cp;
00249 cp = getenv("CROSSFIRE_TEMPLATEDIR");
00250 if (cp)
00251 settings.templatedir = cp;
00252 cp = getenv("CROSSFIRE_TMPDIR");
00253 if (cp)
00254 settings.tmpdir = cp;
00255 }
00256
00263 void init_globals(void) {
00264
00265 memset(&statistics, 0, sizeof(struct Statistics));
00266 if (settings.logfilename[0] == 0) {
00267 logfile = stderr;
00268 } else if ((logfile = fopen(settings.logfilename, "a")) == NULL) {
00269 fprintf(stderr, "Unable to open %s as the logfile - will use stderr instead\n", settings.logfilename);
00270 logfile = stderr;
00271 } else {
00272 setvbuf(logfile, NULL, _IOLBF, 0);
00273 }
00274 exiting = 0;
00275 first_player = NULL;
00276 first_friendly_object = NULL;
00277 first_map = NULL;
00278 first_treasurelist = NULL;
00279 first_artifactlist = NULL;
00280 first_archetype = NULL;
00281 *first_map_ext_path = 0;
00282 warn_archetypes = 0;
00283 nroftreasures = 0;
00284 nrofartifacts = 0;
00285 nrofallowedstr = 0;
00286 ring_arch = NULL;
00287 amulet_arch = NULL;
00288 staff_arch = NULL;
00289 undead_name = add_string("undead");
00290 trying_emergency_save = 0;
00291 num_animations = 0;
00292 animations = NULL;
00293 animations_allocated = 0;
00294 init_defaults();
00295 }
00296
00307 void free_globals(void) {
00308 int msg, attack;
00309 objectlink *friend;
00310 region *reg;
00311
00312 FREE_AND_CLEAR_STR(undead_name);
00313 for (msg = 0; msg < NROFATTACKMESS; msg++)
00314 for (attack = 0; attack < MAXATTACKMESS; attack++) {
00315 free(attack_mess[msg][attack].buf1);
00316 free(attack_mess[msg][attack].buf2);
00317 free(attack_mess[msg][attack].buf3);
00318 }
00319
00320 free(settings.emergency_mapname);
00321
00322 while (first_friendly_object) {
00323 friend = first_friendly_object->next;
00324 FREE_AND_CLEAR(first_friendly_object);
00325 first_friendly_object = friend;
00326 }
00327
00328 free_experience();
00329
00330 while (first_region) {
00331 reg = first_region->next;
00332 FREE_AND_CLEAR(first_region->name);
00333 FREE_AND_CLEAR(first_region->parent_name);
00334 FREE_AND_CLEAR(first_region->jailmap);
00335 FREE_AND_CLEAR(first_region->msg);
00336 FREE_AND_CLEAR(first_region->longname);
00337 FREE_AND_CLEAR(first_region);
00338 first_region = reg;
00339 }
00340 }
00341
00347 void init_objects(void) {
00348 int i;
00349
00350 objects = NULL;
00351 active_objects = NULL;
00352
00353 #ifdef MEMORY_DEBUG
00354 free_objects = NULL;
00355 #else
00356 free_objects = objarray;
00357 objarray[0].prev = NULL,
00358 objarray[0].next = &objarray[1],
00359 SET_FLAG(&objarray[0], FLAG_REMOVED);
00360 SET_FLAG(&objarray[0], FLAG_FREED);
00361 for (i = 1; i < STARTMAX-1; i++) {
00362 objarray[i].next = &objarray[i+1];
00363 objarray[i].prev = &objarray[i-1];
00364 SET_FLAG(&objarray[i], FLAG_REMOVED);
00365 SET_FLAG(&objarray[i], FLAG_FREED);
00366 }
00367 objarray[STARTMAX-1].next = NULL;
00368 objarray[STARTMAX-1].prev = &objarray[STARTMAX-2];
00369 SET_FLAG(&objarray[STARTMAX-1], FLAG_REMOVED);
00370 SET_FLAG(&objarray[STARTMAX-1], FLAG_FREED);
00371 #endif
00372 }
00373
00378 static void init_defaults(void) {
00379 nroferrors = 0;
00380 }
00381
00390 static void init_dynamic(void) {
00391 archetype *at = first_archetype;
00392 while (at) {
00393 if (at->clone.type == MAP) {
00394 if (at->clone.race) {
00395 strcpy(first_map_ext_path, at->clone.race);
00396 }
00397 if (EXIT_PATH(&at->clone)) {
00398 mapstruct *first;
00399
00400 snprintf(first_map_path, sizeof(first_map_path), "%s", EXIT_PATH(&at->clone));
00401 first = ready_map_name(first_map_path, 0);
00402 if (!first) {
00403 LOG(llevError, "Initial map %s can't be found! Please ensure maps are correctly installed.\n", first_map_path);
00404 LOG(llevError, "Unable to continue without initial map.\n");
00405 abort();
00406 }
00407 delete_map(first);
00408 return;
00409 }
00410 }
00411 at = at->next;
00412 }
00413 LOG(llevError, "You need a archetype called 'map' and it have to contain start map\n");
00414 exit(-1);
00415 }
00416
00418 unsigned long todtick;
00419
00424 void write_todclock(void) {
00425 char filename[MAX_BUF];
00426 FILE *fp;
00427
00428 snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir);
00429 if ((fp = fopen(filename, "w")) == NULL) {
00430 LOG(llevError, "Cannot open %s for writing\n", filename);
00431 return;
00432 }
00433 fprintf(fp, "%lu", todtick);
00434 fclose(fp);
00435 }
00436
00441 static void init_clocks(void) {
00442 char filename[MAX_BUF];
00443 FILE *fp;
00444 static int has_been_done = 0;
00445
00446 if (has_been_done)
00447 return;
00448 else
00449 has_been_done = 1;
00450
00451 snprintf(filename, sizeof(filename), "%s/clockdata", settings.localdir);
00452 LOG(llevDebug, "Reading clockdata from %s...\n", filename);
00453 if ((fp = fopen(filename, "r")) == NULL) {
00454 LOG(llevError, "Can't open %s.\n", filename);
00455 todtick = 0;
00456 write_todclock();
00457 return;
00458 }
00459 fscanf(fp, "%lu", &todtick);
00460 LOG(llevDebug, "todtick=%lu\n", todtick);
00461 fclose(fp);
00462 }
00463
00465 attackmess_t attack_mess[NROFATTACKMESS][MAXATTACKMESS];
00466
00473 static void init_attackmess(void) {
00474 char buf[MAX_BUF];
00475 char filename[MAX_BUF];
00476 char *cp, *p;
00477 FILE *fp;
00478 static int has_been_done = 0;
00479 int mess, level, comp;
00480 int mode = 0, total = 0;
00481
00482 if (has_been_done)
00483 return;
00484 else
00485 has_been_done = 1;
00486
00487 snprintf(filename, sizeof(filename), "%s/attackmess", settings.datadir);
00488 LOG(llevDebug, "Reading attack messages from %s...\n", filename);
00489 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
00490 LOG(llevError, "Can't open %s.\n", filename);
00491 return;
00492 }
00493
00494 level = 0;
00495 while (fgets(buf, MAX_BUF, fp) != NULL) {
00496 if (*buf == '#')
00497 continue;
00498 if ((cp = strchr(buf, '\n')) != NULL)
00499 *cp = '\0';
00500 cp = buf;
00501 while (*cp == ' ')
00502 cp++;
00503
00504 if (strncmp(cp, "TYPE:", 5) == 0) {
00505 p = strtok(buf, ":");
00506 p = strtok(NULL, ":");
00507 if (mode == 1) {
00508 attack_mess[mess][level].level = -1;
00509 attack_mess[mess][level].buf1 = NULL;
00510 attack_mess[mess][level].buf2 = NULL;
00511 attack_mess[mess][level].buf3 = NULL;
00512 }
00513 level = 0;
00514 mess = atoi(p);
00515 mode = 1;
00516 continue;
00517 }
00518 if (mode == 1) {
00519 p = strtok(buf, "=");
00520 attack_mess[mess][level].level = atoi(buf);
00521 p = strtok(NULL, "=");
00522 if (p != NULL)
00523 attack_mess[mess][level].buf1 = strdup_local(p);
00524 else
00525 attack_mess[mess][level].buf1 = strdup_local("");
00526 mode = 2;
00527 continue;
00528 } else if (mode == 2) {
00529 p = strtok(buf, "=");
00530 attack_mess[mess][level].level = atoi(buf);
00531 p = strtok(NULL, "=");
00532 if (p != NULL)
00533 attack_mess[mess][level].buf2 = strdup_local(p);
00534 else
00535 attack_mess[mess][level].buf2 = strdup_local("");
00536 mode = 3;
00537 continue;
00538 } else if (mode == 3) {
00539 p = strtok(buf, "=");
00540 attack_mess[mess][level].level = atoi(buf);
00541 p = strtok(NULL, "=");
00542 if (p != NULL)
00543 attack_mess[mess][level].buf3 = strdup_local(p);
00544 else
00545 attack_mess[mess][level].buf3 = strdup_local("");
00546 mode = 1;
00547 level++;
00548 total++;
00549 continue;
00550 }
00551 }
00552 LOG(llevDebug, "got %d messages in %d categories.\n", total, mess+1);
00553 close_and_delete(fp, comp);
00554 }