|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 /* TREASURE_DEBUG does some checking on the treasurelists after loading. 00031 * It is useful for finding bugs in the treasures file. Since it only 00032 * slows the startup some (and not actual game play), it is by default 00033 * left on */ 00034 #define TREASURE_DEBUG 00035 00036 /* TREASURE_VERBOSE enables copious output concerning artifact generation */ 00037 /*#define TREASURE_VERBOSE*/ 00038 00039 #include <global.h> 00040 #include <spellist.h> 00041 #include <loader.h> 00042 00044 char *coins[NUM_COINS + 1] = 00045 { 00046 "mitcoin", 00047 "goldcoin", 00048 "silvercoin", 00049 "coppercoin", 00050 NULL 00051 }; 00052 00054 archetype *coins_arch[NUM_COINS]; 00055 00057 #define ARTIFACT_TRIES 2 00058 00060 #define CHANCE_FIX (-1) 00061 00063 static archetype *ring_arch = NULL; 00065 static archetype *ring_arch_normal = NULL; 00067 static archetype *amulet_arch = NULL; 00069 static archetype *amulet_arch_normal = NULL; 00070 00071 static treasure *load_treasure(FILE *fp, int *t_style, int *a_chance); 00072 static void change_treasure(struct _change_arch *ca, object *op); 00073 static treasurelist *get_empty_treasurelist(); 00074 static treasure *get_empty_treasure(); 00075 static void put_treasure(object *op, object *creator, int flags); 00076 static artifactlist *get_empty_artifactlist(); 00077 static artifact *get_empty_artifact(); 00078 static void check_treasurelist(treasure *t, treasurelist *tl); 00079 static void set_material_real(object *op, struct _change_arch *change_arch); 00080 static void create_money_table(); 00081 static void create_all_treasures(treasure *t, object *op, int flag, int difficulty, int t_style, int a_chance, int tries, struct _change_arch *change_arch); 00082 static void create_one_treasure(treasurelist *tl, object *op, int flag, int difficulty, int t_style, int a_chance, int tries, struct _change_arch *change_arch); 00083 static int set_ring_bonus(object *op, int bonus, int level); 00084 static int get_magic(int diff); 00085 static void dump_monster_treasure_rec(const char *name, treasure *t, int depth); 00086 static void free_treasurestruct(treasure *t); 00087 static void free_charlinks(linked_char *lc); 00088 static void free_artifactlist(); 00089 static void free_artifact(artifact *at); 00090 00095 void load_treasures() 00096 { 00097 FILE *fp; 00098 char filename[MAX_BUF], buf[MAX_BUF], name[MAX_BUF]; 00099 treasurelist *previous = NULL; 00100 treasure *t; 00101 int comp, t_style, a_chance; 00102 00103 snprintf(filename, sizeof(filename), "%s/%s", settings.datadir, settings.treasures); 00104 00105 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) 00106 { 00107 LOG(llevError, "Can't open treasures file: %s\n", filename); 00108 return; 00109 } 00110 00111 while (fgets(buf, MAX_BUF, fp) != NULL) 00112 { 00113 /* Ignore comments and blank lines */ 00114 if (*buf == '#' || *buf == '\n') 00115 { 00116 continue; 00117 } 00118 00119 if (sscanf(buf, "treasureone %s\n", name) || sscanf(buf, "treasure %s\n", name)) 00120 { 00121 treasurelist *tl = get_empty_treasurelist(); 00122 FREE_AND_COPY_HASH(tl->name, name); 00123 00124 if (previous == NULL) 00125 { 00126 first_treasurelist = tl; 00127 } 00128 else 00129 { 00130 previous->next = tl; 00131 } 00132 00133 previous = tl; 00134 t_style= T_STYLE_UNSET; 00135 a_chance = ART_CHANCE_UNSET; 00136 tl->items = load_treasure(fp, &t_style, &a_chance); 00137 00138 if (tl->t_style == T_STYLE_UNSET) 00139 { 00140 tl->t_style = t_style; 00141 } 00142 00143 if (tl->artifact_chance == ART_CHANCE_UNSET) 00144 { 00145 tl->artifact_chance = a_chance; 00146 } 00147 00148 /* This is a one of the many items on the list should be generated. 00149 * Add up the chance total, and check to make sure the yes and no 00150 * fields of the treasures are not being used. */ 00151 if (!strncmp(buf, "treasureone", 11)) 00152 { 00153 for (t = tl->items; t != NULL; t = t->next) 00154 { 00155 #ifdef TREASURE_DEBUG 00156 if (t->next_yes || t->next_no) 00157 { 00158 LOG(llevBug, "Treasure %s is one item, but on treasure %s\n", tl->name, t->item ? t->item->name : t->name); 00159 LOG(llevBug, " the next_yes or next_no field is set"); 00160 } 00161 #endif 00162 tl->total_chance += t->chance; 00163 } 00164 } 00165 } 00166 else 00167 { 00168 LOG(llevError, "Treasure list didn't understand: %s\n", buf); 00169 } 00170 } 00171 00172 close_and_delete(fp, comp); 00173 00174 #ifdef TREASURE_DEBUG 00175 /* Perform some checks on how valid the treasure data actually is. 00176 * Verify that list transitions work (ie, the list that it is 00177 * supposed to transition to exists). Also, verify that at least the 00178 * name or archetype is set for each treasure element. */ 00179 for (previous = first_treasurelist; previous != NULL; previous = previous->next) 00180 { 00181 check_treasurelist(previous->items, previous); 00182 } 00183 #endif 00184 00185 create_money_table(); 00186 } 00187 00192 static void create_money_table() 00193 { 00194 int i; 00195 00196 for (i = 0; coins[i]; i++) 00197 { 00198 coins_arch[i] = find_archetype(coins[i]); 00199 00200 if (!coins_arch[i]) 00201 { 00202 LOG(llevError, "create_money_table(): Can't find %s.\n", coins[i] ? coins[i] : "NULL"); 00203 return; 00204 } 00205 } 00206 } 00207 00215 static treasure *load_treasure(FILE *fp, int *t_style, int *a_chance) 00216 { 00217 char buf[MAX_BUF], *cp = NULL, variable[MAX_BUF]; 00218 treasure *t = get_empty_treasure(); 00219 int value, start_marker = 0, t_style2, a_chance2; 00220 00221 nroftreasures++; 00222 00223 while (fgets(buf, MAX_BUF, fp) != NULL) 00224 { 00225 if (*buf == '#') 00226 { 00227 continue; 00228 } 00229 00230 if ((cp = strchr(buf, '\n')) != NULL) 00231 { 00232 *cp = '\0'; 00233 } 00234 00235 cp = buf; 00236 00237 /* Skip blanks */ 00238 while (!isalpha(*cp)) 00239 { 00240 cp++; 00241 } 00242 00243 if (sscanf(cp, "t_style %d", &value)) 00244 { 00245 if (start_marker) 00246 { 00247 t->t_style = value; 00248 } 00249 else 00250 { 00251 /* No, it's global for the while treasure list entry */ 00252 *t_style = value; 00253 } 00254 } 00255 else if (sscanf(cp, "artifact_chance %d", &value)) 00256 { 00257 if (start_marker) 00258 { 00259 t->artifact_chance = value; 00260 } 00261 else 00262 { 00263 /* No, it's global for the while treasure list entry */ 00264 *a_chance = value; 00265 } 00266 } 00267 else if (sscanf(cp, "arch %s", variable)) 00268 { 00269 if ((t->item = find_archetype(variable)) == NULL) 00270 { 00271 LOG(llevBug, "Treasure lacks archetype: %s\n", variable); 00272 } 00273 00274 start_marker = 1; 00275 } 00276 else if (sscanf(cp, "list %s", variable)) 00277 { 00278 start_marker = 1; 00279 FREE_AND_COPY_HASH(t->name, variable); 00280 } 00281 else if (sscanf(cp, "name %s", variable)) 00282 { 00283 FREE_AND_COPY_HASH(t->change_arch.name, cp + 5); 00284 } 00285 else if (sscanf(cp, "title %s", variable)) 00286 { 00287 FREE_AND_COPY_HASH(t->change_arch.title, cp + 6); 00288 } 00289 else if (sscanf(cp, "slaying %s", variable)) 00290 { 00291 FREE_AND_COPY_HASH(t->change_arch.slaying, cp + 8); 00292 } 00293 else if (sscanf(cp, "item_race %d", &value)) 00294 { 00295 t->change_arch.item_race = value; 00296 } 00297 else if (sscanf(cp, "quality %d", &value)) 00298 { 00299 t->change_arch.quality = value; 00300 } 00301 else if (sscanf(cp, "quality_range %d", &value)) 00302 { 00303 t->change_arch.quality_range = value; 00304 } 00305 else if (sscanf(cp, "material %d", &value)) 00306 { 00307 t->change_arch.material = value; 00308 } 00309 else if (sscanf(cp, "material_quality %d", &value)) 00310 { 00311 t->change_arch.material_quality = value; 00312 } 00313 else if (sscanf(cp, "material_range %d", &value)) 00314 { 00315 t->change_arch.material_range = value; 00316 } 00317 else if (sscanf(cp, "chance_fix %d", &value)) 00318 { 00319 t->chance_fix = (sint16) value; 00320 /* Important or the chance will stay 100% when not set to 0 00321 * in treasure list! */ 00322 t->chance = 0; 00323 } 00324 else if (sscanf(cp, "chance %d", &value)) 00325 { 00326 t->chance = (uint8) value; 00327 } 00328 else if (sscanf(cp, "nrof %d", &value)) 00329 { 00330 t->nrof = (uint16) value; 00331 } 00332 else if (sscanf(cp, "magic %d", &value)) 00333 { 00334 t->magic = value; 00335 } 00336 else if (sscanf(cp, "magic_fix %d", &value)) 00337 { 00338 t->magic_fix = value; 00339 } 00340 else if (sscanf(cp, "magic_chance %d", &value)) 00341 { 00342 t->magic_chance = value; 00343 } 00344 else if (sscanf(cp, "difficulty %d", &value)) 00345 { 00346 t->difficulty = value; 00347 } 00348 else if (!strncmp(cp, "yes", 3)) 00349 { 00350 t_style2 = T_STYLE_UNSET; 00351 a_chance2 = ART_CHANCE_UNSET; 00352 t->next_yes = load_treasure(fp, &t_style2, &a_chance2); 00353 00354 if (t->next_yes->artifact_chance == ART_CHANCE_UNSET) 00355 { 00356 t->next_yes->artifact_chance = a_chance2; 00357 } 00358 00359 if (t->next_yes->t_style == T_STYLE_UNSET) 00360 { 00361 t->next_yes->t_style = t_style2; 00362 } 00363 } 00364 else if (!strncmp(cp, "no", 2)) 00365 { 00366 t_style2 = T_STYLE_UNSET; 00367 a_chance2 = ART_CHANCE_UNSET; 00368 t->next_no = load_treasure(fp, &t_style2, &a_chance2); 00369 00370 if (t->next_no->artifact_chance == ART_CHANCE_UNSET) 00371 { 00372 t->next_no->artifact_chance = a_chance2; 00373 } 00374 00375 if (t->next_no->t_style == T_STYLE_UNSET) 00376 { 00377 t->next_no->t_style = t_style2; 00378 } 00379 } 00380 else if (!strncmp(cp, "end", 3)) 00381 { 00382 return t; 00383 } 00384 else if (!strncmp(cp, "more", 4)) 00385 { 00386 t_style2 = T_STYLE_UNSET; 00387 a_chance2 = ART_CHANCE_UNSET; 00388 t->next = load_treasure(fp, &t_style2, &a_chance2); 00389 00390 if (t->next->artifact_chance == ART_CHANCE_UNSET) 00391 { 00392 t->next->artifact_chance = a_chance2; 00393 } 00394 00395 if (t->next->t_style == T_STYLE_UNSET) 00396 { 00397 t->next->t_style = t_style2; 00398 } 00399 00400 return t; 00401 } 00402 else 00403 { 00404 LOG(llevBug, "Unknown treasure command: '%s', last entry %s\n", cp, t->name ? t->name : "null"); 00405 } 00406 } 00407 00408 LOG(llevBug, "Treasure %s lacks 'end'.>%s<\n", t->name ? t->name : "NULL", cp ? cp : "NULL"); 00409 00410 return t; 00411 } 00412 00417 void init_artifacts() 00418 { 00419 static int has_been_inited = 0; 00420 archetype *atemp; 00421 long old_pos, file_pos; 00422 FILE *fp; 00423 char filename[MAX_BUF], buf[HUGE_BUF], *cp, *next; 00424 artifact *art = NULL; 00425 linked_char *tmp; 00426 int value, comp, none_flag = 0; 00427 size_t lcount; 00428 artifactlist *al; 00429 char buf_text[10 * 1024]; 00430 00431 if (has_been_inited) 00432 { 00433 return; 00434 } 00435 00436 has_been_inited = 1; 00437 00438 snprintf(filename, sizeof(filename), "%s/artifacts", settings.datadir); 00439 LOG(llevDebug, " reading artifacts from %s...", filename); 00440 00441 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) 00442 { 00443 LOG(llevError, "Can't open %s.\n", filename); 00444 return; 00445 } 00446 00447 /* Start read in the artifact list */ 00448 while (fgets(buf, sizeof(buf), fp) != NULL) 00449 { 00450 if (*buf == '#') 00451 { 00452 continue; 00453 } 00454 00455 if ((cp = strchr(buf, '\n')) != NULL) 00456 { 00457 *cp = '\0'; 00458 } 00459 00460 /* Skip blank lines. */ 00461 if (*buf == '\0') 00462 { 00463 continue; 00464 } 00465 00466 cp = buf; 00467 00468 /* Skip blanks */ 00469 while (*cp == ' ') 00470 { 00471 cp++; 00472 } 00473 00474 /* We have a single artifact */ 00475 if (!strncmp(cp, "Allowed", 7)) 00476 { 00477 art = get_empty_artifact(); 00478 nrofartifacts++; 00479 none_flag = 0; 00480 cp = strchr(cp, ' ') + 1; 00481 00482 if (!strcmp(cp, "all")) 00483 { 00484 continue; 00485 } 00486 00487 if (!strcmp(cp, "none")) 00488 { 00489 none_flag = 1; 00490 continue; 00491 } 00492 00493 do 00494 { 00495 nrofallowedstr++; 00496 00497 /* Trim left whitespace. */ 00498 while (isspace(*cp)) 00499 { 00500 cp++; 00501 } 00502 00503 if ((next = strchr(cp, ',')) != NULL) 00504 { 00505 *(next++) = '\0'; 00506 } 00507 00508 tmp = (linked_char *) malloc(sizeof(linked_char)); 00509 tmp->name = NULL; 00510 FREE_AND_COPY_HASH(tmp->name, cp); 00511 tmp->next = art->allowed; 00512 art->allowed = tmp; 00513 } 00514 while ((cp = next) != NULL); 00515 } 00516 else if (sscanf(cp, "t_style %d", &value)) 00517 { 00518 art->t_style = value; 00519 } 00520 else if (sscanf(cp, "chance %d", &value)) 00521 { 00522 art->chance = (uint16) value; 00523 } 00524 else if (sscanf(cp, "difficulty %d", &value)) 00525 { 00526 art->difficulty = (uint8) value; 00527 } 00528 else if (!strncmp(cp, "artifact", 8)) 00529 { 00530 FREE_AND_COPY_HASH(art->name, cp + 9); 00531 } 00532 /* Chain a default arch to this treasure */ 00533 else if (!strncmp(cp, "def_arch", 8)) 00534 { 00535 if ((atemp = find_archetype(cp + 9)) == NULL) 00536 { 00537 LOG(llevError, "init_artifacts(): Can't find def_arch %s.\n", cp + 9); 00538 } 00539 00540 /* Ok, we have a name and an archetype */ 00541 00542 /* Store the non fake archetype name */ 00543 FREE_AND_COPY_HASH(art->def_at_name, cp + 9); 00544 /* Copy the default arch */ 00545 memcpy(&art->def_at, atemp, sizeof(archetype)); 00546 ADD_REF_NOT_NULL_HASH(art->def_at.clone.name); 00547 ADD_REF_NOT_NULL_HASH(art->def_at.clone.title); 00548 ADD_REF_NOT_NULL_HASH(art->def_at.clone.race); 00549 ADD_REF_NOT_NULL_HASH(art->def_at.clone.slaying); 00550 ADD_REF_NOT_NULL_HASH(art->def_at.clone.msg); 00551 art->def_at.clone.arch = &art->def_at; 00552 00553 /* we patch this .clone object after Object read with the artifact data. 00554 * in find_artifact, this archetype object will be returned. For the server, 00555 * it will be the same as it comes from the archlist, defined in the arches. 00556 * This will allow us the generate for every artifact a "default one" and we 00557 * will have always a non-magical base for every artifact */ 00558 } 00559 /* All text after Object is now like an arch file until an end comes */ 00560 else if (!strncmp(cp, "Object", 6)) 00561 { 00562 old_pos = ftell(fp); 00563 00564 if (!load_object(fp, &(art->def_at.clone), NULL, LO_LINEMODE, MAP_STYLE)) 00565 { 00566 LOG(llevError, "init_artifacts(): Could not load object.\n"); 00567 } 00568 00569 if (!art->name) 00570 { 00571 LOG(llevError, "init_artifacts(): Object %s has no arch id name\n", art->def_at.clone.name); 00572 } 00573 00574 if (!art->def_at_name) 00575 { 00576 LOG(llevError, "init_artifacts(): Artifact %s has no def arch\n", art->name); 00577 } 00578 00579 /* Ok, now let's catch and copy the commands to our artifacts 00580 * buffer. Let's do some file magic here - that's the easiest way. */ 00581 file_pos = ftell(fp); 00582 00583 if (fseek(fp, old_pos, SEEK_SET)) 00584 { 00585 LOG(llevError, "init_artifacts(): Could not fseek(fp, %ld, SEEK_SET).\n", old_pos); 00586 } 00587 00588 /* The lex reader will bug when it don't get feed with a 00589 * <text>+0x0a+0 string. So, we do it here and in the lex 00590 * part we simply do a strlen and point to every part without 00591 * copying it. */ 00592 lcount = 0; 00593 00594 while (fgets(buf, sizeof(buf) - 3, fp)) 00595 { 00596 strcpy(buf_text + lcount, buf); 00597 lcount += strlen(buf) + 1; 00598 00599 if (ftell(fp) == file_pos) 00600 { 00601 break; 00602 } 00603 00604 /* Should not possible. */ 00605 if (ftell(fp) > file_pos) 00606 { 00607 LOG(llevError, "init_artifacts(): fgets() read too much data! (%ld - %ld)\n", file_pos, ftell(fp)); 00608 } 00609 } 00610 00611 /* Now store the parse text in the artifacts list entry */ 00612 if ((art->parse_text = malloc(lcount)) == NULL) 00613 { 00614 LOG(llevError, "init_artifacts(): out of memory in ->parse_text (size %"FMT64U")\n", (uint64) lcount); 00615 } 00616 00617 memcpy(art->parse_text, buf_text, lcount); 00618 00619 /* Finally, change the archetype name of our fake arch to the 00620 * fake arch name. Without it, treasures will get the 00621 * original arch, not this. */ 00622 FREE_AND_COPY_HASH(art->def_at.name, art->name); 00623 /* Now handle the <Allowed none> in the artifact to create 00624 * unique items or add them to the given type list. */ 00625 al = find_artifactlist(none_flag == 0 ? art->def_at.clone.type : -1); 00626 00627 if (al == NULL) 00628 { 00629 al = get_empty_artifactlist(); 00630 al->type = none_flag == 0 ? art->def_at.clone.type : -1; 00631 al->next = first_artifactlist; 00632 first_artifactlist = al; 00633 } 00634 00635 art->next = al->items; 00636 al->items = art; 00637 } 00638 else 00639 { 00640 LOG(llevBug, "Unknown input in artifact file: %s\n", buf); 00641 } 00642 } 00643 00644 close_and_delete(fp, comp); 00645 00646 for (al = first_artifactlist; al != NULL; al = al->next) 00647 { 00648 for (art = al->items; art != NULL; art = art->next) 00649 { 00650 /* We don't use our unique artifacts as pick table */ 00651 if (al->type == -1) 00652 { 00653 continue; 00654 } 00655 00656 if (!art->chance) 00657 { 00658 LOG(llevBug, "Artifact with no chance: %s\n", art->name); 00659 } 00660 else 00661 { 00662 al->total_chance += art->chance; 00663 } 00664 } 00665 } 00666 00667 LOG(llevDebug, "done.\n"); 00668 } 00669 00672 void init_archetype_pointers() 00673 { 00674 if (ring_arch_normal == NULL) 00675 { 00676 ring_arch_normal = find_archetype("ring_normal"); 00677 } 00678 00679 if (!ring_arch_normal) 00680 { 00681 LOG(llevBug, "Can't find 'ring_normal' arch (from artifacts)\n"); 00682 } 00683 00684 if (ring_arch == NULL) 00685 { 00686 ring_arch = find_archetype("ring_generic"); 00687 } 00688 00689 if (!ring_arch) 00690 { 00691 LOG(llevBug, "Can't find 'ring_generic' arch\n"); 00692 } 00693 00694 if (amulet_arch_normal == NULL) 00695 { 00696 amulet_arch_normal = find_archetype("amulet_normal"); 00697 } 00698 00699 if (!amulet_arch_normal) 00700 { 00701 LOG(llevBug, "Can't find 'amulet_normal' arch (from artifacts)\n"); 00702 } 00703 00704 if (amulet_arch == NULL) 00705 { 00706 amulet_arch = find_archetype("amulet_generic"); 00707 } 00708 00709 if (!amulet_arch) 00710 { 00711 LOG(llevBug, "Can't find 'amulet_generic' arch\n"); 00712 } 00713 } 00714 00718 static treasurelist *get_empty_treasurelist() 00719 { 00720 treasurelist *tl = (treasurelist *) malloc(sizeof(treasurelist)); 00721 00722 if (tl == NULL) 00723 { 00724 LOG(llevError, "get_empty_treasurelist(): Out of memory.\n"); 00725 } 00726 00727 tl->name = NULL; 00728 tl->next = NULL; 00729 tl->items = NULL; 00730 /* -2 is the "unset" marker and will be virtually handled as 0 which 00731 * can be overruled. */ 00732 tl->t_style = T_STYLE_UNSET; 00733 tl->artifact_chance = ART_CHANCE_UNSET; 00734 tl->chance_fix = CHANCE_FIX; 00735 tl->total_chance = 0; 00736 00737 return tl; 00738 } 00739 00743 static treasure *get_empty_treasure() 00744 { 00745 treasure *t = (treasure *) malloc(sizeof(treasure)); 00746 00747 if (t == NULL) 00748 { 00749 LOG(llevError, "get_empty_treasure(): Out of memory.\n"); 00750 } 00751 00752 t->change_arch.item_race = -1; 00753 t->change_arch.name = NULL; 00754 t->change_arch.slaying = NULL; 00755 t->change_arch.title = NULL; 00756 /* -2 is the "unset" marker and will be virtually handled as 0 which 00757 * can be overruled. */ 00758 t->t_style = T_STYLE_UNSET; 00759 t->change_arch.material = -1; 00760 t->change_arch.material_quality = -1; 00761 t->change_arch.material_range = -1; 00762 t->change_arch.quality = -1; 00763 t->change_arch.quality_range = -1; 00764 t->chance_fix = CHANCE_FIX; 00765 t->item = NULL; 00766 t->name = NULL; 00767 t->next = NULL; 00768 t->next_yes = NULL; 00769 t->next_no = NULL; 00770 t->artifact_chance = ART_CHANCE_UNSET; 00771 t->chance = 100; 00772 t->magic_fix = 0; 00773 t->difficulty = 0; 00774 t->magic_chance = 3; 00775 t->magic = 0; 00776 t->nrof = 0; 00777 00778 return t; 00779 } 00780 00785 treasurelist *find_treasurelist(const char *name) 00786 { 00787 const char *tmp = find_string(name); 00788 treasurelist *tl; 00789 00790 /* Special cases - randomitems of none is to override default. If 00791 * first_treasurelist is null, it means we are on the first pass of 00792 * of loading archetyps, so for now, just return - second pass will 00793 * init these values. */ 00794 if (!strcmp(name, "none") || !first_treasurelist) 00795 { 00796 return NULL; 00797 } 00798 00799 if (tmp != NULL) 00800 { 00801 for (tl = first_treasurelist; tl != NULL; tl = tl->next) 00802 { 00803 if (tmp == tl->name) 00804 { 00805 return tl; 00806 } 00807 } 00808 } 00809 00810 LOG(llevBug, "Bug: Couldn't find treasurelist %s\n", name); 00811 return NULL; 00812 } 00813 00823 object *generate_treasure(treasurelist *t, int difficulty, int a_chance) 00824 { 00825 object *ob = get_object(), *tmp; 00826 00827 create_treasure(t, ob, 0, difficulty, t->t_style, a_chance, 0, NULL); 00828 00829 /* Don't want to free the object we are about to return */ 00830 tmp = ob->inv; 00831 00832 /* Remove from inv - no move off */ 00833 if (tmp != NULL) 00834 { 00835 remove_ob(tmp); 00836 } 00837 00838 if (ob->inv) 00839 { 00840 LOG(llevError, "generate_treasure(): Created multiple objects.\n"); 00841 } 00842 00843 return tmp; 00844 } 00845 00856 void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int t_style, int a_chance, int tries, struct _change_arch *arch_change) 00857 { 00858 if (tries++ > 100) 00859 { 00860 LOG(llevDebug, "create_treasure(): tries >100 for t-list %s.", t->name ? t->name : "<noname>"); 00861 return; 00862 } 00863 00864 if (t->t_style != T_STYLE_UNSET) 00865 { 00866 t_style = t->t_style; 00867 } 00868 00869 if (t->artifact_chance != ART_CHANCE_UNSET) 00870 { 00871 a_chance = t->artifact_chance; 00872 } 00873 00874 if (t->total_chance) 00875 { 00876 create_one_treasure(t, op, flag, difficulty, t_style, a_chance, tries, arch_change); 00877 } 00878 else 00879 { 00880 create_all_treasures(t->items, op, flag, difficulty, t_style, a_chance, tries, arch_change); 00881 } 00882 } 00883 00894 static void create_all_treasures(treasure *t, object *op, int flag, int difficulty, int t_style, int a_chance, int tries, struct _change_arch *change_arch) 00895 { 00896 object *tmp; 00897 00898 if (t->t_style != T_STYLE_UNSET) 00899 { 00900 t_style = t->t_style; 00901 } 00902 00903 if (t->artifact_chance != ART_CHANCE_UNSET) 00904 { 00905 a_chance = t->artifact_chance; 00906 } 00907 00908 if ((t->chance_fix != CHANCE_FIX && rndm_chance(t->chance_fix)) || (int) t->chance >= 100 || (rndm(1, 100) < (int) t->chance)) 00909 { 00910 if (t->name) 00911 { 00912 if (t->name != shstr_cons.NONE && difficulty >= t->difficulty) 00913 { 00914 create_treasure(find_treasurelist(t->name), op, flag, difficulty, t_style, a_chance, tries, change_arch ? change_arch : &t->change_arch); 00915 } 00916 } 00917 else if (difficulty >= t->difficulty) 00918 { 00919 if (IS_SYS_INVISIBLE(&t->item->clone) || !(flag & GT_INVISIBLE)) 00920 { 00921 if (t->item->clone.type != WEALTH) 00922 { 00923 tmp = arch_to_object(t->item); 00924 00925 if (t->nrof && tmp->nrof <= 1) 00926 { 00927 tmp->nrof = rndm(1, t->nrof); 00928 } 00929 00930 /* Ret 1 = artifact is generated - don't overwrite anything here */ 00931 set_material_real(tmp, change_arch ? change_arch : &t->change_arch); 00932 00933 if (!fix_generated_item(&tmp, op, difficulty, a_chance, t_style, t->magic, t->magic_fix, t->magic_chance, flag)) 00934 { 00935 change_treasure(change_arch ? change_arch : &t->change_arch, tmp); 00936 } 00937 00938 put_treasure(tmp, op, flag); 00939 00940 /* If treasure is "identified", created items are too */ 00941 if (op->type == TREASURE && QUERY_FLAG(op, FLAG_IDENTIFIED)) 00942 { 00943 SET_FLAG(tmp, FLAG_IDENTIFIED); 00944 } 00945 } 00946 /* We have a wealth object - expand it to real money */ 00947 else 00948 { 00949 /* If t->magic is != 0, that's our value - if not use default setting */ 00950 int i, value = t->magic ? t->magic : t->item->clone.value; 00951 00952 value *= (difficulty / 2) + 1; 00953 00954 /* So we have 80% to 120% of the fixed value */ 00955 value = (int) ((float) value * 0.8f + (float) value * (rndm(1, 40) / 100.0f)); 00956 00957 for (i = 0; i < NUM_COINS; i++) 00958 { 00959 if (value / coins_arch[i]->clone.value > 0) 00960 { 00961 tmp = get_object(); 00962 copy_object(&coins_arch[i]->clone, tmp, 0); 00963 tmp->nrof = value / tmp->value; 00964 value -= tmp->nrof * tmp->value; 00965 put_treasure(tmp, op, flag); 00966 } 00967 } 00968 } 00969 } 00970 } 00971 00972 if (t->next_yes != NULL) 00973 { 00974 create_all_treasures(t->next_yes, op, flag, difficulty, (t->next_yes->t_style == T_STYLE_UNSET) ? t_style : t->next_yes->t_style, a_chance, tries, change_arch); 00975 } 00976 } 00977 else if (t->next_no != NULL) 00978 { 00979 create_all_treasures(t->next_no, op, flag, difficulty, (t->next_no->t_style == T_STYLE_UNSET) ? t_style : t->next_no->t_style, a_chance, tries, change_arch); 00980 } 00981 00982 if (t->next != NULL) 00983 { 00984 create_all_treasures(t->next, op, flag, difficulty, (t->next->t_style == T_STYLE_UNSET) ? t_style : t->next->t_style, a_chance, tries, change_arch); 00985 } 00986 } 00987 00999 static void create_one_treasure(treasurelist *tl, object *op, int flag, int difficulty, int t_style, int a_chance, int tries, struct _change_arch *change_arch) 01000 { 01001 int value, diff_tries = 0; 01002 treasure *t; 01003 object *tmp; 01004 01005 if (tries++ > 100) 01006 { 01007 return; 01008 } 01009 01010 /* Well, at some point we should rework this whole system... */ 01011 create_one_treasure_again_jmp: 01012 if (diff_tries > 10) 01013 { 01014 return; 01015 } 01016 01017 value = rndm(1, tl->total_chance) - 1; 01018 01019 for (t = tl->items; t != NULL; t = t->next) 01020 { 01021 /* chance_fix will overrule the normal chance stuff!. */ 01022 if (t->chance_fix != CHANCE_FIX) 01023 { 01024 if (rndm_chance(t->chance_fix)) 01025 { 01026 /* Only when allowed, we go on! */ 01027 if (difficulty >= t->difficulty) 01028 { 01029 value = 0; 01030 break; 01031 } 01032 01033 /* Ok, difficulty is bad let's try again or break! */ 01034 if (tries++ > 100) 01035 { 01036 return; 01037 } 01038 01039 diff_tries++; 01040 goto create_one_treasure_again_jmp; 01041 } 01042 01043 if (!t->chance) 01044 { 01045 continue; 01046 } 01047 } 01048 01049 value -= t->chance; 01050 01051 /* We got one! */ 01052 if (value <= 0) 01053 { 01054 /* Only when allowed, we go on! */ 01055 if (difficulty >= t->difficulty) 01056 { 01057 break; 01058 } 01059 01060 /* Ok, difficulty is bad let's try again or break! */ 01061 if (tries++ > 100) 01062 { 01063 return; 01064 } 01065 01066 diff_tries++; 01067 goto create_one_treasure_again_jmp; 01068 } 01069 } 01070 01071 if (t->t_style != T_STYLE_UNSET) 01072 { 01073 t_style = t->t_style; 01074 } 01075 01076 if (t->artifact_chance != ART_CHANCE_UNSET) 01077 { 01078 a_chance = t->artifact_chance; 01079 } 01080 01081 if (!t || value > 0) 01082 { 01083 LOG(llevBug, "create_one_treasure: got null object or not able to find treasure - tl:%s op:%s\n", tl ? tl->name : "(null)", op ? op->name : "(null)"); 01084 return; 01085 } 01086 01087 if (t->name) 01088 { 01089 if (t->name == shstr_cons.NONE) 01090 { 01091 return; 01092 } 01093 01094 if (difficulty >= t->difficulty) 01095 { 01096 create_treasure(find_treasurelist(t->name), op, flag, difficulty, t_style, a_chance, tries, change_arch); 01097 } 01098 else if (t->nrof) 01099 { 01100 create_one_treasure(tl, op, flag, difficulty, t_style, a_chance, tries, change_arch); 01101 } 01102 01103 return; 01104 } 01105 01106 if (IS_SYS_INVISIBLE(&t->item->clone) || flag != GT_INVISIBLE) 01107 { 01108 if (t->item->clone.type != WEALTH) 01109 { 01110 tmp = arch_to_object(t->item); 01111 01112 if (t->nrof && tmp->nrof <= 1) 01113 { 01114 tmp->nrof = rndm(1, t->nrof); 01115 } 01116 01117 set_material_real(tmp, change_arch ? change_arch : &t->change_arch); 01118 01119 if (!fix_generated_item(&tmp, op, difficulty, a_chance, (t->t_style == T_STYLE_UNSET) ? t_style : t->t_style, t->magic, t->magic_fix, t->magic_chance, flag)) 01120 { 01121 change_treasure(change_arch ? change_arch : &t->change_arch, tmp); 01122 } 01123 01124 put_treasure(tmp, op, flag); 01125 01126 /* If treasure is "identified", created items are too */ 01127 if (op->type == TREASURE && QUERY_FLAG(op, FLAG_IDENTIFIED)) 01128 { 01129 SET_FLAG(tmp, FLAG_IDENTIFIED); 01130 } 01131 } 01132 /* We have a wealth object - expand it to real money */ 01133 else 01134 { 01135 /* If t->magic is != 0, that's our value - if not use default setting */ 01136 int i; 01137 01138 value = t->magic ? t->magic : t->item->clone.value; 01139 value *= difficulty; 01140 01141 /* So we have 80% to 120% of the fixed value */ 01142 value = (int) ((float) value * 0.8f + (float) value * (rndm(1, 40) / 100.0f)); 01143 01144 for (i = 0; i < NUM_COINS; i++) 01145 { 01146 if (value / coins_arch[i]->clone.value > 0) 01147 { 01148 tmp = get_object(); 01149 copy_object(&coins_arch[i]->clone, tmp, 0); 01150 tmp->nrof = value / tmp->value; 01151 value -= tmp->nrof * tmp->value; 01152 put_treasure(tmp, op, flag); 01153 } 01154 } 01155 } 01156 } 01157 } 01158 01164 static void put_treasure(object *op, object *creator, int flags) 01165 { 01166 if (flags & GT_ENVIRONMENT) 01167 { 01168 op->x = creator->x; 01169 op->y = creator->y; 01170 insert_ob_in_map(op, creator->map, op, INS_NO_MERGE | INS_NO_WALK_ON); 01171 } 01172 else 01173 { 01174 object *tmp; 01175 01176 op = insert_ob_in_ob(op, creator); 01177 01178 if ((flags & GT_UPDATE_INV) && (tmp = is_player_inv(creator)) != NULL) 01179 { 01180 esrv_send_item(tmp, op); 01181 } 01182 } 01183 } 01184 01190 static void change_treasure(struct _change_arch *ca, object *op) 01191 { 01192 if (ca->name) 01193 { 01194 FREE_AND_COPY_HASH(op->name, ca->name); 01195 } 01196 01197 if (ca->title) 01198 { 01199 FREE_AND_COPY_HASH(op->title, ca->title); 01200 } 01201 01202 if (ca->slaying) 01203 { 01204 FREE_AND_COPY_HASH(op->slaying, ca->slaying); 01205 } 01206 } 01207 01219 static void set_magic(int difficulty, object *op, int max_magic, int fix_magic, int chance_magic, int flags) 01220 { 01221 int i; 01222 01223 /* If we have a fixed value, force it */ 01224 if (fix_magic) 01225 { 01226 i = fix_magic; 01227 } 01228 else 01229 { 01230 i = 0; 01231 01232 /* chance_magic 0 means always no magic bonus */ 01233 if (rndm(1, 100) <= chance_magic || rndm(1, 200) <= difficulty) 01234 { 01235 i = rndm(1, abs(max_magic)); 01236 01237 if (max_magic < 0) 01238 { 01239 i = -i; 01240 } 01241 } 01242 } 01243 01244 if ((flags & GT_ONLY_GOOD) && i < 0) 01245 { 01246 i = 0; 01247 } 01248 01249 set_abs_magic(op, i); 01250 01251 if (i < 0) 01252 { 01253 SET_FLAG(op, FLAG_CURSED); 01254 } 01255 01256 if (i != 0) 01257 { 01258 SET_FLAG(op, FLAG_IS_MAGICAL); 01259 } 01260 } 01261 01270 void set_abs_magic(object *op, int magic) 01271 { 01272 if (!magic) 01273 { 01274 return; 01275 } 01276 01277 SET_FLAG(op, FLAG_IS_MAGICAL); 01278 01279 op->magic = magic; 01280 01281 if (op->arch) 01282 { 01283 if (magic == 1) 01284 { 01285 op->value += 5300; 01286 } 01287 else if (magic == 2) 01288 { 01289 op->value += 12300; 01290 } 01291 else if (magic == 3) 01292 { 01293 op->value += 24300; 01294 } 01295 else if (magic == 4) 01296 { 01297 op->value += 52300; 01298 } 01299 else 01300 { 01301 op->value += 88300; 01302 } 01303 01304 if (op->type == ARMOUR) 01305 { 01306 ARMOUR_SPEED(op) = (ARMOUR_SPEED(&op->arch->clone) * (100 + magic * 10)) / 100; 01307 } 01308 01309 /* You can't just check the weight always */ 01310 if (magic < 0 && !rndm(0, 2)) 01311 { 01312 magic = (-magic); 01313 } 01314 01315 op->weight = (op->arch->clone.weight * (100 - magic * 10)) / 100; 01316 } 01317 else 01318 { 01319 if (op->type == ARMOUR) 01320 { 01321 ARMOUR_SPEED(op) = (ARMOUR_SPEED(op) * (100 + magic * 10)) / 100; 01322 } 01323 01324 /* You can't just check the weight always */ 01325 if (magic < 0 && !rndm(0, 2)) 01326 { 01327 magic = (-magic); 01328 } 01329 01330 op->weight = (op->weight * (100 - magic * 10)) / 100; 01331 } 01332 } 01333 01350 static int set_ring_bonus(object *op, int bonus, int level) 01351 { 01352 int tmp, r, off; 01353 off = (level >= 50 ? 1 : 0) + (level >= 60 ? 1 : 0) + (level >= 70 ? 1 : 0) + (level >= 80 ? 1 : 0); 01354 01355 /* Let's repeat, too lazy for a loop */ 01356 set_ring_bonus_jump1: 01357 r = RANDOM() % (bonus > 0 ? 25 : 13); 01358 01359 SET_FLAG(op, FLAG_IS_MAGICAL); 01360 01361 if (op->type == AMULET) 01362 { 01363 if (!(RANDOM() % 21)) 01364 { 01365 r = 20 + RANDOM() % 2; 01366 } 01367 else if (!(RANDOM() % 20)) 01368 { 01369 tmp = RANDOM() % 3; 01370 01371 if (tmp == 2) 01372 { 01373 r = 0; 01374 } 01375 else if (!tmp) 01376 { 01377 r = 11; 01378 } 01379 else 01380 { 01381 r = 12; 01382 } 01383 } 01384 else if (RANDOM() & 2) 01385 { 01386 if (RANDOM() & 2) 01387 { 01388 r = 10; 01389 } 01390 else 01391 { 01392 r = 8; 01393 } 01394 } 01395 else 01396 { 01397 r = 13 + RANDOM() % 7; 01398 } 01399 } 01400 01401 switch (r % 25) 01402 { 01403 /* We are creating hp stuff! */ 01404 case 0: 01405 tmp = 5; 01406 01407 if (level < 5) 01408 { 01409 tmp += RANDOM() % 10; 01410 01411 if (bonus > 0) 01412 { 01413 op->value = (int) ((float) op->value * 1.3f); 01414 } 01415 } 01416 else if (level < 10) 01417 { 01418 tmp += 10 + RANDOM() % 10; 01419 01420 if (bonus > 0) 01421 { 01422 op->value = (int) ((float) op->value * 1.32f); 01423 } 01424 } 01425 else if (level < 15) 01426 { 01427 tmp += 15 + RANDOM() % 20; 01428 01429 if (bonus > 0) 01430 { 01431 op->value = (int) ((float) op->value * 1.34f); 01432 } 01433 } 01434 else if (level < 20) 01435 { 01436 tmp += 20 + RANDOM() % 21; 01437 01438 if (bonus > 0) 01439 { 01440 op->value = (int) ((float) op->value * 1.36f); 01441 } 01442 } 01443 else if (level < 25) 01444 { 01445 tmp += 25 + RANDOM() % 23; 01446 01447 if (bonus > 0) 01448 { 01449 op->value = (int) ((float) op->value * 1.38f); 01450 } 01451 } 01452 else if (level < 30) 01453 { 01454 tmp += 30 + RANDOM() % 25; 01455 01456 if (bonus > 0) 01457 { 01458 op->value = (int) ((float) op->value * 1.4f); 01459 } 01460 } 01461 else if (level < 40) 01462 { 01463 tmp += 40 + RANDOM() % 30; 01464 01465 if (bonus > 0) 01466 { 01467 op->value = (int) ((float) op->value * 1.42f); 01468 } 01469 } 01470 else 01471 { 01472 tmp += (int) ((double) level * 0.65) + 50 + RANDOM() % 40; 01473 01474 if (bonus > 0) 01475 { 01476 op->value = (int) ((float) op->value * 1.44f); 01477 } 01478 } 01479 01480 if (bonus < 0) 01481 { 01482 tmp = -tmp; 01483 } 01484 else 01485 { 01486 op->item_level = (int) ((double) level * (0.5 + ((double) (RANDOM() % 40) / 100.0))); 01487 } 01488 01489 op->stats.maxhp = tmp; 01490 break; 01491 01492 /* Stats */ 01493 case 1: 01494 case 2: 01495 case 3: 01496 case 4: 01497 case 5: 01498 case 6: 01499 set_attr_value(&op->stats, r, (sint8) (bonus + get_attr_value(&op->stats, r))); 01500 break; 01501 01502 case 7: 01503 op->stats.dam += bonus; 01504 01505 if (bonus > 0 && (RANDOM() % 20 > 16 ? 1 : 0)) 01506 { 01507 op->value = (int) ((float) op->value * 1.3f); 01508 op->stats.dam++; 01509 } 01510 01511 break; 01512 01513 case 8: 01514 op->stats.wc += bonus; 01515 01516 if (bonus > 0 && (RANDOM() % 20 > 16 ? 1 : 0)) 01517 { 01518 op->value = (int) ((float) op->value * 1.3f); 01519 op->stats.wc++; 01520 } 01521 01522 break; 01523 01524 /* Hunger/sustenance */ 01525 case 9: 01526 op->stats.food += bonus; 01527 01528 if (bonus > 0 && (RANDOM() % 20 > 16 ? 1 : 0)) 01529 { 01530 op->value = (int) ((float) op->value * 1.2f); 01531 op->stats.food++; 01532 } 01533 01534 break; 01535 01536 case 10: 01537 op->stats.ac += bonus; 01538 01539 if (bonus > 0 && (RANDOM() % 20 > 16 ? 1 : 0)) 01540 { 01541 op->value = (int) ((float) op->value * 1.3f); 01542 op->stats.ac++; 01543 } 01544 01545 break; 01546 01547 case 11: 01548 case 12: 01549 if (!RANDOM() % 3) 01550 { 01551 goto make_prot_items; 01552 } 01553 01554 tmp = 3; 01555 01556 if (level < 5) 01557 { 01558 tmp += RANDOM() % 3; 01559 01560 if (bonus > 0) 01561 { 01562 op->value = (int) ((float) op->value * 1.3f); 01563 } 01564 } 01565 else if (level < 10) 01566 { 01567 tmp += 3 + RANDOM() % 4; 01568 01569 if (bonus > 0) 01570 { 01571 op->value = (int) ((float) op->value * 1.32f); 01572 } 01573 } 01574 else if (level < 15) 01575 { 01576 tmp += 4 + RANDOM() % 6; 01577 01578 if (bonus > 0) 01579 { 01580 op->value = (int) ((float) op->value * 1.34f); 01581 } 01582 } 01583 else if (level < 20) 01584 { 01585 tmp += 6 + RANDOM() % 8; 01586 01587 if (bonus > 0) 01588 { 01589 op->value = (int) ((float) op->value * 1.36f); 01590 } 01591 } 01592 else if (level < 25) 01593 { 01594 tmp += 8 + RANDOM() % 10; 01595 01596 if (bonus > 0) 01597 { 01598 op->value = (int) ((float) op->value * 1.38f); 01599 } 01600 } 01601 else if (level < 33) 01602 { 01603 tmp += 10 + RANDOM() % 12; 01604 01605 if (bonus > 0) 01606 { 01607 op->value = (int) ((float) op->value * 1.4f); 01608 } 01609 } 01610 else if (level < 44) 01611 { 01612 tmp += 15 + RANDOM() % 15; 01613 01614 if (bonus > 0) 01615 { 01616 op->value = (int) ((float) op->value * 1.42f); 01617 } 01618 } 01619 else 01620 { 01621 tmp += (int) ((double) level * 0.53) + 20 + RANDOM() % 20; 01622 01623 if (bonus > 0) 01624 { 01625 op->value = (int) ((float) op->value * 1.44f); 01626 } 01627 } 01628 01629 if (bonus < 0) 01630 { 01631 tmp = -tmp; 01632 } 01633 else 01634 { 01635 op->item_level = (int) ((double) level * (0.5 + ((double) (RANDOM() % 40) / 100.0))); 01636 } 01637 01638 op->stats.maxsp = tmp; 01639 break; 01640 01641 case 13: 01642 make_prot_items: 01643 case 14: 01644 case 15: 01645 case 16: 01646 case 17: 01647 case 18: 01648 case 19: 01649 { 01650 int b = 5 + FABS(bonus), val, protect = RANDOM() % (LAST_PROTECTION - 4 + off); 01651 01652 /* Roughly generate a bonus between 100 and 35 (depending on the bonus) */ 01653 val = 10 + RANDOM() % b + RANDOM() % b + RANDOM() % b + RANDOM() % b; 01654 01655 /* Cursed items need to have higher negative values to equal 01656 * out with positive values for how protections work out. Put 01657 * another little random element in since that they don't 01658 * always end up with even values. */ 01659 if (bonus < 0) 01660 { 01661 val = 2 * -val - RANDOM() % b; 01662 } 01663 01664 /* Upper limit */ 01665 if (val > 35) 01666 { 01667 val = 35; 01668 } 01669 01670 b = 0; 01671 01672 while (op->protection[protect] != 0) 01673 { 01674 /* Not able to find a free protection */ 01675 if (b++ >= 4) 01676 { 01677 goto set_ring_bonus_jump1; 01678 } 01679 01680 protect = RANDOM() % (LAST_PROTECTION - 4 + off); 01681 } 01682 01683 op->protection[protect] = val; 01684 break; 01685 } 01686 01687 case 20: 01688 if (op->type == AMULET) 01689 { 01690 SET_FLAG(op, FLAG_REFL_SPELL); 01691 op->value *= 11; 01692 } 01693 else 01694 { 01695 /* Regenerate hit points */ 01696 op->stats.hp += bonus; 01697 op->value = (int) ((float) op->value * 1.3f); 01698 01699 if (bonus > 0 && (RANDOM() % 20 > 16 ? 1 : 0)) 01700 { 01701 op->value = (int) ((float) op->value * 1.3f); 01702 op->stats.hp++; 01703 } 01704 } 01705 01706 break; 01707 01708 case 21: 01709 if (op->type == AMULET) 01710 { 01711 SET_FLAG(op, FLAG_REFL_MISSILE); 01712 op->value *= 9; 01713 } 01714 else 01715 { 01716 /* Regenerate spell points */ 01717 op->stats.sp += bonus; 01718 op->value = (int) ((float) op->value * 1.35f); 01719 01720 if (bonus > 0 && (RANDOM() % 20 > 16 ? 1 : 0)) 01721 { 01722 op->value = (int) ((float) op->value * 1.35f); 01723 op->stats.sp++; 01724 } 01725 } 01726 01727 break; 01728 01729 case 22: 01730 /* Regenerate grace */ 01731 op->stats.grace += bonus; 01732 op->value = (int) ((float) op->value * 1.35f); 01733 01734 if (bonus > 0 && (RANDOM() % 20 > 16 ? 1 : 0)) 01735 { 01736 op->value = (int) ((float) op->value * 1.35f); 01737 op->stats.grace++; 01738 } 01739 01740 break; 01741 01742 default: 01743 if (!bonus) 01744 { 01745 bonus = 1; 01746 } 01747 01748 /* Speed! */ 01749 op->stats.exp += bonus; 01750 op->value = (int) ((float) op->value * 1.4f); 01751 break; 01752 } 01753 01754 if (bonus > 0) 01755 { 01756 op->value = (int) ((float) op->value * 2.0f * (float) bonus); 01757 } 01758 else 01759 { 01760 op->value = -(op->value * 2 * bonus) / 2; 01761 } 01762 01763 /* Check possible overflow */ 01764 if (op->value < 0) 01765 { 01766 op->value = 0; 01767 } 01768 01769 return 1; 01770 } 01771 01775 static void set_ring_item_power(object *ob) 01776 { 01777 int tmp, i; 01778 01779 if (ob->stats.maxhp > 0) 01780 { 01781 ob->item_power += ob->stats.maxhp / 50; 01782 } 01783 01784 if (ob->stats.maxsp > 0) 01785 { 01786 ob->item_power += ob->stats.maxsp / 50; 01787 } 01788 01789 if (ob->stats.exp >= 2) 01790 { 01791 ob->item_power += ob->stats.exp - 1; 01792 } 01793 01794 if (ob->stats.ac > 0) 01795 { 01796 ob->item_power += ob->stats.ac; 01797 } 01798 01799 if (ob->stats.dam > 0) 01800 { 01801 ob->item_power += ob->stats.dam; 01802 } 01803 01804 if (ob->stats.wc > 0) 01805 { 01806 ob->item_power += ob->stats.wc; 01807 } 01808 01809 if (QUERY_FLAG(ob, FLAG_REFL_MISSILE)) 01810 { 01811 ob->item_power++; 01812 } 01813 01814 if (QUERY_FLAG(ob, FLAG_REFL_SPELL)) 01815 { 01816 ob->item_power += 2; 01817 } 01818 01819 if (ob->stats.hp > 0) 01820 { 01821 ob->item_power += ob->stats.hp; 01822 } 01823 01824 if (ob->stats.sp > 0) 01825 { 01826 ob->item_power += ob->stats.sp + 1; 01827 } 01828 01829 if (ob->stats.grace > 0) 01830 { 01831 ob->item_power += ob->stats.grace + 2; 01832 } 01833 01834 tmp = 0; 01835 01836 for (i = 0; i < NROFATTACKS; i++) 01837 { 01838 tmp += ob->protection[i]; 01839 } 01840 01841 if (tmp > 0) 01842 { 01843 ob->item_power += (tmp + 10) / 20; 01844 } 01845 01846 for (i = 0; i < NUM_STATS; i++) 01847 { 01848 tmp = get_attr_value(&ob->stats, i); 01849 01850 if (tmp >= 2) 01851 { 01852 ob->item_power += tmp - 1; 01853 } 01854 } 01855 } 01856 01866 static int get_magic(int diff) 01867 { 01868 int i; 01869 01870 if (diff < 3) 01871 { 01872 diff = 3; 01873 } 01874 01875 for (i = 0; i < 4; i++) 01876 { 01877 if (rndm(0, diff - 1)) 01878 { 01879 return i; 01880 } 01881 } 01882 01883 return 4; 01884 } 01885 01894 static int get_random_spell(int level, int flags) 01895 { 01896 int i, num_spells = 0, possible_spells[NROFREALSPELLS]; 01897 01898 /* Collect the list of spells we can choose from. */ 01899 for (i = 0; i < NROFREALSPELLS; i++) 01900 { 01901 if (level >= spells[i].level && spells[i].spell_use & flags) 01902 { 01903 possible_spells[num_spells] = i; 01904 num_spells++; 01905 } 01906 } 01907 01908 /* If we found any spells we can use, select randomly. */ 01909 if (num_spells) 01910 { 01911 return possible_spells[rndm(1, num_spells) - 1]; 01912 } 01913 01914 /* If we are here, there is no fitting spell. */ 01915 return SP_NO_SPELL; 01916 } 01917 01922 static void add_random_race(object *op) 01923 { 01924 ob_race *race = race_get_random(); 01925 01926 if (race) 01927 { 01928 FREE_AND_COPY_HASH(op->slaying, race->name); 01929 } 01930 } 01931 01932 #define DICE2 (get_magic(2) == 2 ? 2 : 1) 01933 01947 int fix_generated_item(object **op_ptr, object *creator, int difficulty, int a_chance, int t_style, int max_magic, int fix_magic, int chance_magic, int flags) 01948 { 01949 /* Just to make things easy */ 01950 object *op = *op_ptr; 01951 int temp, retval = 0, was_magic = op->magic; 01952 int too_many_tries = 0, is_special = 0; 01953 01954 /* Safety and to prevent polymorphed objects giving attributes */ 01955 if (!creator || creator->type == op->type) 01956 { 01957 creator = op; 01958 } 01959 01960 if (difficulty < 1) 01961 { 01962 difficulty = 1; 01963 } 01964 01965 if (op->type != POTION && op->type != SCROLL && op->type != FOOD) 01966 { 01967 if ((!op->magic && max_magic) || fix_magic) 01968 { 01969 set_magic(difficulty, op, max_magic, fix_magic, chance_magic, flags); 01970 } 01971 01972 if (a_chance != 0) 01973 { 01974 if ((!was_magic && rndm_chance(CHANCE_FOR_ARTIFACT)) || op->type == HORN || difficulty >= 999 || rndm(1, 100) <= a_chance) 01975 { 01976 retval = generate_artifact(op, difficulty, t_style, a_chance); 01977 } 01978 } 01979 } 01980 01981 /* Only modify object if not special */ 01982 if (!op->title || op->type == RUNE) 01983 { 01984 switch (op->type) 01985 { 01986 /* We create scrolls now in artifacts file too */ 01987 case SCROLL: 01988 while (op->stats.sp == SP_NO_SPELL) 01989 { 01990 generate_artifact(op, difficulty, t_style, 100); 01991 01992 if (too_many_tries++ > 3) 01993 { 01994 break; 01995 } 01996 } 01997 01998 /* Ok, forget it... */ 01999 if (op->stats.sp == SP_NO_SPELL) 02000 { 02001 break; 02002 } 02003 02004 /* Marks as magical */ 02005 SET_FLAG(op, FLAG_IS_MAGICAL); 02006 /* Charges */ 02007 op->stats.food = rndm(1, spells[op->stats.sp].charges); 02008 temp = (((difficulty * 100) - (difficulty * 20)) + (difficulty * rndm(0, 34))) / 100; 02009 02010 if (temp < 1) 02011 { 02012 temp = 1; 02013 } 02014 else if (temp > MAXLEVEL) 02015 { 02016 temp = MAXLEVEL; 02017 } 02018 02019 op->level = temp; 02020 02021 if (temp < spells[op->stats.sp].level) 02022 { 02023 temp = spells[op->stats.sp].level; 02024 } 02025 02026 break; 02027 02028 case POTION: 02029 { 02030 /* Balm */ 02031 if (!op->sub_type) 02032 { 02033 if ((op->stats.sp = get_random_spell(difficulty, SPELL_USE_BALM)) == SP_NO_SPELL) 02034 { 02035 break; 02036 } 02037 02038 SET_FLAG(op, FLAG_IS_MAGICAL); 02039 op->value = (int) (150.0f * spells[op->stats.sp].value_mul); 02040 } 02041 /* Dust */ 02042 else if (op->sub_type > 128) 02043 { 02044 if ((op->stats.sp = get_random_spell(difficulty, SPELL_USE_DUST)) == SP_NO_SPELL) 02045 { 02046 break; 02047 } 02048 02049 SET_FLAG(op, FLAG_IS_MAGICAL); 02050 op->value = (int) (125.0f * spells[op->stats.sp].value_mul); 02051 } 02052 else 02053 { 02054 while (!(is_special = special_potion(op)) && op->stats.sp == SP_NO_SPELL) 02055 { 02056 generate_artifact(op, difficulty, t_style, 100); 02057 02058 if (too_many_tries++ > 3) 02059 { 02060 goto jump_break1; 02061 } 02062 } 02063 } 02064 02065 temp = (((difficulty * 100) - (difficulty * 20)) + (difficulty * rndm(0, 34))) / 100; 02066 02067 if (temp < 1) 02068 { 02069 temp = 1; 02070 } 02071 else if (temp > MAXLEVEL) 02072 { 02073 temp = MAXLEVEL; 02074 } 02075 02076 if (!is_special && temp < spells[op->stats.sp].level) 02077 { 02078 temp = spells[op->stats.sp].level; 02079 } 02080 02081 op->level = temp; 02082 02083 /* Chance to make special potions damned or cursed. The 02084 * chance is somewhat high to make the game more 02085 * difficult. Applying this potions without identify is a 02086 * great risk! */ 02087 if (is_special && !(flags & GT_ONLY_GOOD)) 02088 { 02089 if (rndm_chance(2)) 02090 { 02091 SET_FLAG(op, (rndm_chance(2) ? FLAG_CURSED : FLAG_DAMNED)); 02092 } 02093 } 02094 02095 jump_break1: 02096 break; 02097 } 02098 02099 case AMULET: 02100 /* Since it's not just decoration */ 02101 if (op->arch == amulet_arch) 02102 { 02103 op->value *= 5; 02104 } 02105 02106 case RING: 02107 if (op->arch == NULL) 02108 { 02109 remove_ob(op); 02110 *op_ptr = op = NULL; 02111 break; 02112 } 02113 02114 /* It's a special artifact! For these items, there is no point 02115 * carrying on, as the next bit is for regular rings only. */ 02116 if (op->arch != ring_arch && op->arch != amulet_arch) 02117 { 02118 break; 02119 } 02120 02121 /* We have no special ring or amulet - now we create one. We first 02122 * get us a value, material and face changed prototype. 02123 * Then we cast the powers over it. */ 02124 02125 /* This is called before we inserted it in the map or elsewhere */ 02126 if (!QUERY_FLAG(op, FLAG_REMOVED)) 02127 { 02128 remove_ob(op); 02129 } 02130 02131 /* Here we give the ring or amulet a random material. 02132 * First we use a special arch for this. Only this archtype is 02133 * allowed to be masked with a special material artifact. */ 02134 if (op->arch == ring_arch) 02135 { 02136 *op_ptr = op = arch_to_object(ring_arch_normal); 02137 } 02138 else 02139 { 02140 *op_ptr = op = arch_to_object(amulet_arch_normal); 02141 } 02142 02143 generate_artifact(op, difficulty, t_style, 99); 02144 02145 /* Now we add the random boni/mali to the item */ 02146 if (!(flags & GT_ONLY_GOOD) && rndm_chance(4)) 02147 { 02148 SET_FLAG(op, FLAG_CURSED); 02149 } 02150 02151 set_ring_bonus(op, QUERY_FLAG(op, FLAG_CURSED) ? -DICE2 : DICE2, difficulty); 02152 02153 if (op->type == RING) 02154 { 02155 if (rndm_chance(4)) 02156 { 02157 int d = (!rndm_chance(2) || QUERY_FLAG(op, FLAG_CURSED)) ? -DICE2 : DICE2; 02158 02159 if (set_ring_bonus(op, d, difficulty)) 02160 { 02161 op->value = (int) ((float) op->value * 1.95f); 02162 } 02163 02164 if (rndm_chance(4)) 02165 { 02166 d = (!rndm_chance(3) || QUERY_FLAG(op, FLAG_CURSED)) ? -DICE2 : DICE2; 02167 02168 if (set_ring_bonus(op, d, difficulty)) 02169 { 02170 op->value = (int) ((float) op->value * 1.95f); 02171 } 02172 } 02173 } 02174 } 02175 02176 set_ring_item_power(op); 02177 02178 break; 02179 02180 case BOOK: 02181 /* Is it an empty book? If yes let's make a special msg 02182 * for it, and tailor its properties based on the creator 02183 * and/or map level we found it on. */ 02184 if (!op->msg && !rndm_chance(10)) 02185 { 02186 int level = 5; 02187 02188 /* Set the book level properly. */ 02189 if (creator->level == 0 || IS_LIVE(creator)) 02190 { 02191 object *ob; 02192 02193 for (ob = creator; ob && ob->env; ob = ob->env) 02194 { 02195 } 02196 02197 if (ob->map && ob->map->difficulty) 02198 { 02199 level = ob->map->difficulty; 02200 } 02201 } 02202 else 02203 { 02204 level = creator->level; 02205 } 02206 02207 level = (((level * 100) - (level * 20)) + (level * rndm(0, 50))) / 100; 02208 02209 if (level < 1) 02210 { 02211 level = 1; 02212 } 02213 else if (level > MAXLEVEL) 02214 { 02215 level = MAXLEVEL; 02216 } 02217 02218 op->level = level; 02219 02220 tailor_readable_ob(op, (creator && creator->stats.sp) ? creator->stats.sp : -1); 02221 generate_artifact(op, 1, T_STYLE_UNSET, 100); 02222 02223 /* Books with info are worth more! */ 02224 if (op->msg && strlen(op->msg) > 0) 02225 { 02226 op->value *= ((op->level > 10 ? op->level : (op->level + 1) / 2) * ((strlen(op->msg) / 250) + 1)); 02227 } 02228 02229 /* For library, chained books! */ 02230 if (creator->type != MONSTER && QUERY_FLAG(creator, FLAG_NO_PICK)) 02231 { 02232 SET_FLAG(op, FLAG_NO_PICK); 02233 } 02234 02235 /* For check_inv floors */ 02236 if (creator->slaying && !op->slaying) 02237 { 02238 FREE_AND_COPY_HASH(op->slaying, creator->slaying); 02239 } 02240 02241 /* Add exp so reading it gives xp (once) */ 02242 op->stats.exp = op->value > 10000 ? op->value / 5 : op->value / 10; 02243 } 02244 02245 break; 02246 02247 case SPELLBOOK: 02248 LOG(llevDebug, "fix_generated_item(): called for disabled object SPELLBOOK (%s)\n", query_name(op, NULL)); 02249 break; 02250 02251 case WAND: 02252 if ((op->stats.sp = get_random_spell(difficulty, SPELL_USE_WAND)) == SP_NO_SPELL) 02253 { 02254 break; 02255 } 02256 02257 /* Marks as magical */ 02258 SET_FLAG(op, FLAG_IS_MAGICAL); 02259 /* Charges */ 02260 op->stats.food = rndm(1, spells[op->stats.sp].charges) + 12; 02261 02262 temp = (((difficulty * 100) - (difficulty * 20)) + (difficulty * rndm(0, 34))) / 100; 02263 02264 if (temp < 1) 02265 { 02266 temp = 1; 02267 } 02268 else if (temp > MAXLEVEL) 02269 { 02270 temp = MAXLEVEL; 02271 } 02272 02273 if (temp < spells[op->stats.sp].level) 02274 { 02275 temp = spells[op->stats.sp].level; 02276 } 02277 02278 op->level = temp; 02279 op->value = (int) (16.3f * spells[op->stats.sp].value_mul); 02280 02281 break; 02282 02283 case HORN: 02284 case ROD: 02285 if ((op->stats.sp = get_random_spell(difficulty, op->type == HORN ? SPELL_USE_HORN : SPELL_USE_ROD)) == SP_NO_SPELL) 02286 { 02287 break; 02288 } 02289 02290 /* Marks as magical */ 02291 SET_FLAG(op, FLAG_IS_MAGICAL); 02292 02293 if (op->stats.maxhp) 02294 { 02295 op->stats.maxhp += rndm(1, op->stats.maxhp); 02296 } 02297 02298 op->stats.hp = op->stats.maxhp; 02299 temp = (((difficulty * 100) - (difficulty * 20)) + (difficulty * rndm(0, 34))) / 100; 02300 02301 if (temp < 1) 02302 { 02303 temp = 1; 02304 } 02305 else if (temp > MAXLEVEL) 02306 { 02307 temp = MAXLEVEL; 02308 } 02309 02310 op->level = temp; 02311 02312 if (temp < spells[op->stats.sp].level) 02313 { 02314 temp = spells[op->stats.sp].level; 02315 } 02316 02317 op->value = (int) (1850.0f * spells[op->stats.sp].value_mul); 02318 02319 break; 02320 02321 case RUNE: 02322 /* Artifact AND normal treasure runes! */ 02323 trap_adjust(op, difficulty); 02324 break; 02325 02326 /* Generate some special food */ 02327 case FOOD: 02328 if (rndm_chance(4)) 02329 { 02330 generate_artifact(op, difficulty, T_STYLE_UNSET, 100); 02331 } 02332 02333 /* Small chance to become cursed food */ 02334 if (!(flags & GT_ONLY_GOOD) && rndm_chance(20)) 02335 { 02336 int strong_curse = rndm(0, 1), i; 02337 02338 SET_FLAG(op, FLAG_CURSED); 02339 SET_FLAG(op, FLAG_PERM_CURSED); 02340 02341 /* Pick a random stat to put negative value on */ 02342 change_attr_value(&op->stats, rndm(1, NUM_STATS) - 1, strong_curse ? -2 : -1); 02343 02344 /* If this is strong curse food, give it half a chance to curse another stat */ 02345 if (strong_curse && rndm(0, 1)) 02346 { 02347 change_attr_value(&op->stats, rndm(1, NUM_STATS) - 1, strong_curse ? -2 : -1); 02348 } 02349 02350 /* Put a negative value on random protection. */ 02351 op->protection[rndm(1, LAST_PROTECTION) - 1] = strong_curse ? -25 : -10; 02352 02353 /* And again, if this is strong curse food, half a chance to curse another protection. */ 02354 if (strong_curse && rndm(0, 1)) 02355 { 02356 op->protection[rndm(1, LAST_PROTECTION) - 1] = strong_curse ? -25 : -10; 02357 } 02358 02359 /* Change food, hp, mana and grace bonuses to negative values */ 02360 if (op->stats.food) 02361 { 02362 op->stats.food = -op->stats.food; 02363 } 02364 02365 if (op->stats.hp) 02366 { 02367 op->stats.hp = -op->stats.hp; 02368 } 02369 02370 if (op->stats.sp) 02371 { 02372 op->stats.sp = -op->stats.sp; 02373 } 02374 02375 if (op->stats.grace) 02376 { 02377 op->stats.grace = -op->stats.grace; 02378 } 02379 02380 /* Change any positive stat bonuses to negative bonuses. */ 02381 for (i = 0; i < NUM_STATS; i++) 02382 { 02383 sint8 val = get_attr_value(&op->stats, i); 02384 02385 if (val > 0) 02386 { 02387 set_attr_value(&op->stats, i, -val); 02388 } 02389 } 02390 02391 /* And the same for protections. */ 02392 for (i = 0; i < NROFATTACKS; i++) 02393 { 02394 if (op->protection[i] > 0) 02395 { 02396 op->protection[i] = -op->protection[i]; 02397 } 02398 } 02399 02400 if (!op->title) 02401 { 02402 FREE_AND_ADD_REF_HASH(op->title, (strong_curse ? shstr_cons.of_hideous_poison : shstr_cons.of_poison)); 02403 } 02404 } 02405 02406 break; 02407 } 02408 } 02409 /* Title is not NULL. */ 02410 else 02411 { 02412 switch (op->type) 02413 { 02414 case ARROW: 02415 if (op->slaying == shstr_cons.none) 02416 { 02417 add_random_race(op); 02418 } 02419 02420 break; 02421 02422 case WEAPON: 02423 if (op->slaying == shstr_cons.none) 02424 { 02425 add_random_race(op); 02426 } 02427 02428 break; 02429 } 02430 } 02431 02432 if ((flags & GT_NO_VALUE) && op->type != MONEY) 02433 { 02434 op->value = 0; 02435 } 02436 02437 if (flags & GT_STARTEQUIP) 02438 { 02439 if (op->nrof < 2 && op->type != CONTAINER && op->type != MONEY && !QUERY_FLAG(op, FLAG_IS_THROWN)) 02440 { 02441 SET_FLAG(op, FLAG_STARTEQUIP); 02442 } 02443 else if (op->type != MONEY) 02444 { 02445 op->value = 0; 02446 } 02447 } 02448 02449 return retval; 02450 } 02451 02455 static artifactlist *get_empty_artifactlist() 02456 { 02457 artifactlist *tl = (artifactlist *) malloc(sizeof(artifactlist)); 02458 02459 if (tl == NULL) 02460 { 02461 LOG(llevError, "get_empty_artifactlist(): Out of memory.\n"); 02462 } 02463 02464 tl->next = NULL; 02465 tl->items = NULL; 02466 tl->total_chance = 0; 02467 02468 return tl; 02469 } 02470 02474 static artifact *get_empty_artifact(void) 02475 { 02476 artifact *t = (artifact *) malloc(sizeof(artifact)); 02477 02478 if (t == NULL) 02479 { 02480 LOG(llevError, "get_empty_artifact(): Out of memory.\n"); 02481 } 02482 02483 t->next = NULL; 02484 t->name = NULL; 02485 t->def_at_name = NULL; 02486 t->t_style = 0; 02487 t->chance = 0; 02488 t->difficulty = 0; 02489 t->allowed = NULL; 02490 02491 return t; 02492 } 02493 02499 artifactlist *find_artifactlist(int type) 02500 { 02501 artifactlist *al; 02502 02503 for (al = first_artifactlist; al != NULL; al = al->next) 02504 { 02505 if (al->type == type) 02506 { 02507 return al; 02508 } 02509 } 02510 02511 return NULL; 02512 } 02513 02519 archetype *find_artifact_archtype(const char *name) 02520 { 02521 artifactlist *al; 02522 artifact *art = NULL; 02523 02524 for (al = first_artifactlist; al != NULL; al = al->next) 02525 { 02526 art = al->items; 02527 02528 do 02529 { 02530 if (art->name && !strcmp(art->name, name)) 02531 { 02532 return &art->def_at; 02533 } 02534 02535 art = art->next; 02536 } 02537 while (art != NULL); 02538 } 02539 02540 return NULL; 02541 } 02542 02549 artifact *find_artifact_type(const char *name, int type) 02550 { 02551 artifactlist *al; 02552 artifact *art; 02553 02554 al = find_artifactlist(type); 02555 02556 if (!al) 02557 { 02558 return NULL; 02559 } 02560 02561 for (art = al->items; art; art = art->next) 02562 { 02563 if (!strcmp(art->name, name)) 02564 { 02565 return art; 02566 } 02567 } 02568 02569 return NULL; 02570 } 02571 02574 void dump_artifacts() 02575 { 02576 artifactlist *al; 02577 artifact *art; 02578 linked_char *next; 02579 02580 for (al = first_artifactlist; al != NULL; al = al->next) 02581 { 02582 LOG(llevInfo, "Artifact has type %d, total_chance=%d\n", al->type, al->total_chance); 02583 02584 for (art = al->items; art != NULL; art = art->next) 02585 { 02586 LOG(llevInfo, "Artifact %-30s Difficulty %3d T-Style %d Chance %5d\n", art->name, art->difficulty, art->t_style, art->chance); 02587 02588 if (art->allowed != NULL) 02589 { 02590 LOG(llevInfo, "\tAllowed combinations:"); 02591 02592 for (next = art->allowed; next != NULL; next = next->next) 02593 { 02594 LOG(llevInfo, "%s,", next->name); 02595 } 02596 02597 LOG(llevInfo, "\n"); 02598 } 02599 } 02600 } 02601 02602 LOG(llevInfo, "\n"); 02603 } 02604 02608 static void dump_monster_treasure_rec(const char *name, treasure *t, int depth) 02609 { 02610 treasurelist *tl; 02611 int i; 02612 02613 if (depth > 100) 02614 { 02615 return; 02616 } 02617 02618 while (t != NULL) 02619 { 02620 if (t->name != NULL) 02621 { 02622 for (i = 0; i < depth; i++) 02623 { 02624 LOG(llevInfo, " "); 02625 } 02626 02627 LOG(llevInfo, "{ (list: %s)\n", t->name); 02628 tl = find_treasurelist(t->name); 02629 dump_monster_treasure_rec(name, tl->items, depth + 2); 02630 02631 for (i = 0; i < depth; i++) 02632 { 02633 LOG(llevInfo, " "); 02634 } 02635 02636 LOG(llevInfo, "} (end of list: %s)\n", t->name); 02637 } 02638 else 02639 { 02640 for (i = 0; i < depth; i++) 02641 { 02642 LOG(llevInfo, " "); 02643 } 02644 02645 if (t->item->clone.type == FLESH) 02646 { 02647 LOG(llevInfo, "%s's %s\n", name, t->item->clone.name); 02648 } 02649 else 02650 { 02651 LOG(llevInfo, "%s\n", t->item->clone.name); 02652 } 02653 } 02654 02655 if (t->next_yes != NULL) 02656 { 02657 for (i = 0; i < depth; i++) 02658 { 02659 LOG(llevInfo, " "); 02660 } 02661 02662 LOG(llevInfo, " (if yes)\n"); 02663 dump_monster_treasure_rec(name, t->next_yes, depth + 1); 02664 } 02665 02666 if (t->next_no != NULL) 02667 { 02668 for (i = 0; i < depth; i++) 02669 { 02670 LOG(llevInfo, " "); 02671 } 02672 02673 LOG(llevInfo, " (if no)\n"); 02674 dump_monster_treasure_rec(name, t->next_no, depth + 1); 02675 } 02676 02677 t = t->next; 02678 } 02679 } 02680 02683 static int legal_artifact_combination(object *op, artifact *art) 02684 { 02685 int neg, success = 0; 02686 linked_char *tmp; 02687 const char *name; 02688 02689 /* Ie, "all" */ 02690 if (art->allowed == NULL) 02691 { 02692 return 1; 02693 } 02694 02695 for (tmp = art->allowed; tmp; tmp = tmp->next) 02696 { 02697 #ifdef TREASURE_VERBOSE 02698 LOG(llevDebug, "legal_art: %s\n", tmp->name); 02699 #endif 02700 02701 if (*tmp->name == '!') 02702 { 02703 name = tmp->name + 1, neg = 1; 02704 } 02705 else 02706 { 02707 name = tmp->name, neg = 0; 02708 } 02709 02710 /* If we match name, then return the opposite of 'neg' */ 02711 if (!strcmp(name, op->name) || (op->arch && !strcmp(name, op->arch->name))) 02712 { 02713 return !neg; 02714 } 02715 /* Set success as true, since if the match was an inverse, it 02716 * means everything is allowed except what we match. */ 02717 else if (neg) 02718 { 02719 success = 1; 02720 } 02721 } 02722 02723 return success; 02724 } 02725 02729 void give_artifact_abilities(object *op, artifact *art) 02730 { 02731 int tmp_value = op->value; 02732 02733 op->value = 0; 02734 02735 if (!load_object(art->parse_text, op, NULL, LO_MEMORYMODE, MAP_ARTIFACT)) 02736 { 02737 LOG(llevError, "give_artifact_abilities(): load_object() error (ob: %s art: %s).\n", op->name, art->name); 02738 } 02739 02740 FREE_AND_ADD_REF_HASH(op->artifact, art->name); 02741 02742 /* This will solve the problem to adjust the value for different 02743 * items of same artification. Also we can safely use negative 02744 * values. */ 02745 op->value += tmp_value; 02746 02747 if (op->value < 0) 02748 { 02749 op->value = 0; 02750 } 02751 02752 return; 02753 } 02754 02765 int generate_artifact(object *op, int difficulty, int t_style, int a_chance) 02766 { 02767 artifactlist *al; 02768 artifact *art, *art_tmp = NULL; 02769 int i = 0; 02770 02771 al = find_artifactlist(op->type); 02772 02773 /* Now we overrule unset to 0 */ 02774 if (t_style == T_STYLE_UNSET) 02775 { 02776 t_style = 0; 02777 } 02778 02779 if (al == NULL) 02780 { 02781 #ifdef TREASURE_VERBOSE 02782 LOG(llevDebug, "Couldn't change %s into artifact - no table.\n", op->name); 02783 #endif 02784 return 0; 02785 } 02786 02787 for (i = 0; i < ARTIFACT_TRIES; i++) 02788 { 02789 int roll = rndm(1, al->total_chance) - 1; 02790 02791 for (art = al->items; art != NULL; art = art->next) 02792 { 02793 roll -= art->chance; 02794 02795 if (roll < 0) 02796 { 02797 break; 02798 } 02799 } 02800 02801 if (art == NULL || roll >= 0) 02802 { 02803 LOG(llevBug, "Got null entry and non zero roll in generate_artifact, type %d\n", op->type); 02804 return 0; 02805 } 02806 02807 /* Map difficulty not high enough OR the t_style is set and don't match */ 02808 if (difficulty < art->difficulty || (t_style == -1 && art->t_style && art->t_style != T_STYLE_UNSET) || (t_style && art->t_style && art->t_style != t_style && art->t_style != T_STYLE_UNSET)) 02809 { 02810 continue; 02811 } 02812 02813 if (!legal_artifact_combination(op, art)) 02814 { 02815 #ifdef TREASURE_VERBOSE 02816 LOG(llevDebug, "%s of %s was not a legal combination.\n", op->name, art->item->name); 02817 #endif 02818 continue; 02819 } 02820 02821 give_artifact_abilities(op, art); 02822 return 1; 02823 } 02824 02825 /* If we are here then we failed to generate an artifact by chance. */ 02826 if (a_chance > 0) 02827 { 02828 for (art = al->items; art != NULL; art = art->next) 02829 { 02830 if (art->chance <= 0) 02831 { 02832 continue; 02833 } 02834 02835 if (difficulty < art->difficulty || (t_style == -1 && art->t_style && art->t_style != T_STYLE_UNSET) || (t_style && art->t_style && art->t_style != t_style && art->t_style != T_STYLE_UNSET)) 02836 { 02837 continue; 02838 } 02839 02840 if (!legal_artifact_combination(op, art)) 02841 { 02842 continue; 02843 } 02844 02845 /* There we go! */ 02846 art_tmp = art; 02847 } 02848 } 02849 02850 /* Now we MUST have one - if there was at least one legal possible 02851 * artifact. */ 02852 if (art_tmp) 02853 { 02854 give_artifact_abilities(op, art_tmp); 02855 } 02856 02857 return 1; 02858 } 02859 02864 static void free_treasurestruct(treasure *t) 02865 { 02866 if (t->next) 02867 { 02868 free_treasurestruct(t->next); 02869 } 02870 02871 if (t->next_yes) 02872 { 02873 free_treasurestruct(t->next_yes); 02874 } 02875 02876 if (t->next_no) 02877 { 02878 free_treasurestruct(t->next_no); 02879 } 02880 02881 FREE_AND_CLEAR_HASH2(t->name); 02882 FREE_AND_CLEAR_HASH2(t->change_arch.name); 02883 FREE_AND_CLEAR_HASH2(t->change_arch.slaying); 02884 FREE_AND_CLEAR_HASH2(t->change_arch.title); 02885 free(t); 02886 } 02887 02891 static void free_charlinks(linked_char *lc) 02892 { 02893 linked_char *tmp, *next; 02894 02895 for (tmp = lc; tmp; tmp = next) 02896 { 02897 next = tmp->next; 02898 FREE_AND_CLEAR_HASH(tmp->name); 02899 free(tmp); 02900 } 02901 } 02902 02907 static void free_artifact(artifact *at) 02908 { 02909 FREE_AND_CLEAR_HASH2(at->name); 02910 FREE_AND_CLEAR_HASH2(at->def_at.name); 02911 02912 if (at->next) 02913 { 02914 free_artifact(at->next); 02915 } 02916 02917 if (at->allowed) 02918 { 02919 free_charlinks(at->allowed); 02920 } 02921 02922 if (at->parse_text) 02923 { 02924 free(at->parse_text); 02925 } 02926 02927 FREE_AND_CLEAR_HASH2(at->def_at.clone.name); 02928 FREE_AND_CLEAR_HASH2(at->def_at.clone.race); 02929 FREE_AND_CLEAR_HASH2(at->def_at.clone.slaying); 02930 FREE_AND_CLEAR_HASH2(at->def_at.clone.msg); 02931 FREE_AND_CLEAR_HASH2(at->def_at.clone.title); 02932 free_key_values(&at->def_at.clone); 02933 free(at); 02934 } 02935 02938 static void free_artifactlist() 02939 { 02940 artifactlist *al, *nextal; 02941 02942 LOG(llevDebug, "Freeing artifact list.\n"); 02943 02944 for (al = first_artifactlist; al; al = nextal) 02945 { 02946 nextal = al->next; 02947 02948 if (al->items) 02949 { 02950 free_artifact(al->items); 02951 } 02952 02953 free(al); 02954 } 02955 } 02956 02959 void free_all_treasures() 02960 { 02961 treasurelist *tl, *next; 02962 02963 LOG(llevDebug, "Freeing treasure lists.\n"); 02964 02965 for (tl = first_treasurelist; tl; tl = next) 02966 { 02967 next = tl->next; 02968 FREE_AND_CLEAR_HASH2(tl->name); 02969 02970 if (tl->items) 02971 { 02972 free_treasurestruct(tl->items); 02973 } 02974 02975 free(tl); 02976 } 02977 02978 free_artifactlist(); 02979 } 02980 02985 static void set_material_real(object *op, struct _change_arch *change_arch) 02986 { 02987 if (change_arch->item_race != -1) 02988 { 02989 op->item_race = (uint8) change_arch->item_race; 02990 } 02991 02992 /* This must be tested - perhaps we want that change_arch->material 02993 * also overrule the material_real -1 marker? */ 02994 if (op->material_real == -1) 02995 { 02996 /* WARNING: material_real == -1 skips also the quality modifier. 02997 * this is really for objects which don't fit in the material/quality 02998 * system (like system objects, forces, effects and stuff). */ 02999 op->material_real = 0; 03000 return; 03001 } 03002 03003 /* We overrule the material settings in any case when this is set */ 03004 if (change_arch->material != -1) 03005 { 03006 op->material_real = change_arch->material; 03007 03008 /* Skip if material is 0 (aka neutralized material setting) */ 03009 if (change_arch->material_range > 0 && change_arch->material) 03010 { 03011 op->material_real += rndm(0, change_arch->material_range); 03012 } 03013 } 03014 03015 /* If 0, grab a valid material class. We should assign to all objects 03016 * a valid material_real value to avoid problems here. */ 03017 else if (!op->material_real && op->material != M_ADAMANT) 03018 { 03019 if (op->material & M_IRON) 03020 { 03021 op->material_real = M_START_IRON; 03022 } 03023 else if (op->material & M_LEATHER) 03024 { 03025 op->material_real = M_START_LEATHER; 03026 } 03027 else if (op->material & M_PAPER) 03028 { 03029 op->material_real = M_START_PAPER; 03030 } 03031 else if (op->material & M_GLASS) 03032 { 03033 op->material_real = M_START_GLASS; 03034 } 03035 else if (op->material & M_WOOD) 03036 { 03037 op->material_real = M_START_WOOD; 03038 } 03039 else if (op->material & M_ORGANIC) 03040 { 03041 op->material_real = M_START_ORGANIC; 03042 } 03043 else if (op->material & M_STONE) 03044 { 03045 op->material_real = M_START_STONE; 03046 } 03047 else if (op->material & M_CLOTH) 03048 { 03049 op->material_real = M_START_CLOTH; 03050 } 03051 else if (op->material & M_ADAMANT) 03052 { 03053 op->material_real = M_START_ADAMANT; 03054 } 03055 else if (op->material & M_LIQUID) 03056 { 03057 op->material_real = M_START_LIQUID; 03058 } 03059 else if (op->material & M_SOFT_METAL) 03060 { 03061 op->material_real = M_START_SOFT_METAL; 03062 } 03063 else if (op->material & M_BONE) 03064 { 03065 op->material_real = M_START_BONE; 03066 } 03067 else if (op->material & M_ICE) 03068 { 03069 op->material_real = M_START_ICE; 03070 } 03071 } 03072 03073 /* Now we do some work: we define a (material) quality and try to 03074 * find a best matching pre-set material_real for that item. This is 03075 * a bit more complex but we are with that free to define different 03076 * materials without having a strong fixed material table. */ 03077 if (change_arch->material_quality != -1) 03078 { 03079 int i, q_tmp = -1; 03080 int m_range = change_arch->material_quality; 03081 03082 if (change_arch->material_range > 0) 03083 { 03084 m_range += rndm(0, change_arch->material_range); 03085 } 03086 03087 if (op->material_real) 03088 { 03089 int m_tmp = op->material_real / NROFMATERIALS_REAL; 03090 03091 /* The first entry of the material_real of material table */ 03092 m_tmp = m_tmp * 64 + 1; 03093 03094 /* We should add paper & cloth here too later */ 03095 if (m_tmp == M_START_IRON || m_tmp == M_START_WOOD || m_tmp == M_START_LEATHER) 03096 { 03097 for (i = 0; i < NROFMATERIALS_REAL; i++) 03098 { 03099 /* We have a full hit */ 03100 if (material_real[m_tmp + i].quality == m_range) 03101 { 03102 op->material_real = m_tmp + i; 03103 goto set_material_real; 03104 } 03105 03106 /* Find nearest quality we want */ 03107 if (material_real[m_tmp + i].quality >= change_arch->material_quality && material_real[m_tmp + i].quality <= m_range && material_real[m_tmp + i].quality > q_tmp) 03108 { 03109 q_tmp = m_tmp + i; 03110 } 03111 } 03112 03113 /* If we have no match, we simply use the (always valid) 03114 * first material_real entry and forcing the 03115 * material_quality to quality! */ 03116 if (q_tmp == -1) 03117 { 03118 op->material_real = m_tmp; 03119 op->item_quality = change_arch->material_quality; 03120 op->item_condition = op->item_quality; 03121 return; 03122 } 03123 03124 /* That's now our best match! */ 03125 op->material_real = q_tmp; 03126 } 03127 /* Excluded material table! */ 03128 else 03129 { 03130 op->item_quality = m_range; 03131 op->item_condition = op->item_quality; 03132 return; 03133 } 03134 } 03135 /* We have material_real 0 but we modify at least the quality! */ 03136 else 03137 { 03138 op->item_quality = m_range; 03139 op->item_condition = op->item_quality; 03140 return; 03141 } 03142 } 03143 03144 set_material_real: 03145 /* Adjust quality - use material default value or quality adjustment */ 03146 if (change_arch->quality != -1) 03147 { 03148 op->item_quality = change_arch->quality; 03149 } 03150 else 03151 { 03152 op->item_quality = material_real[op->material_real].quality; 03153 } 03154 03155 if (change_arch->quality_range > 0) 03156 { 03157 op->item_quality += rndm(0, change_arch->quality_range); 03158 03159 if (op->item_quality > 100) 03160 { 03161 op->item_quality = 100; 03162 } 03163 } 03164 03165 op->item_condition = op->item_quality; 03166 } 03167 03171 void dump_monster_treasure(const char *name) 03172 { 03173 archetype *at; 03174 int found; 03175 03176 found = 0; 03177 LOG(llevInfo, "\n"); 03178 03179 for (at = first_archetype; at != NULL; at = at->next) 03180 { 03181 if (!strcasecmp(at->name, name)) 03182 { 03183 LOG(llevInfo, "treasures for %s (arch: %s)\n", at->clone.name, at->name); 03184 03185 if (at->clone.randomitems != NULL) 03186 { 03187 dump_monster_treasure_rec(at->clone.name, at->clone.randomitems->items, 1); 03188 } 03189 else 03190 { 03191 LOG(llevInfo, "(nothing)\n"); 03192 } 03193 03194 LOG(llevInfo, "\n"); 03195 found++; 03196 } 03197 } 03198 03199 if (found == 0) 03200 { 03201 LOG(llevInfo, "No objects have the name %s!\n\n", name); 03202 } 03203 } 03204 03210 int get_environment_level(object *op) 03211 { 03212 object *env; 03213 03214 if (!op) 03215 { 03216 LOG(llevBug, "get_environment_level() called for NULL object!\n"); 03217 return 1; 03218 } 03219 03220 /* Return object level or map level... */ 03221 if (op->level) 03222 { 03223 return op->level; 03224 } 03225 03226 if (op->map) 03227 { 03228 return op->map->difficulty ? op->map->difficulty : 1; 03229 } 03230 03231 /* Let's check for env */ 03232 env = op->env; 03233 03234 while (env) 03235 { 03236 if (env->level) 03237 { 03238 return env->level; 03239 } 03240 03241 if (env->map) 03242 { 03243 return env->map->difficulty ? env->map->difficulty : 1; 03244 } 03245 03246 env = env->env; 03247 } 03248 03249 return 1; 03250 } 03251 03257 object *create_artifact(object *op, char *artifactname) 03258 { 03259 artifactlist *al = find_artifactlist(op->type); 03260 artifact *art; 03261 03262 if (al == NULL) 03263 { 03264 return NULL; 03265 } 03266 03267 for (art = al->items; art != NULL; art = art->next) 03268 { 03269 if (!strcmp(art->name, artifactname)) 03270 { 03271 give_artifact_abilities(op, art); 03272 } 03273 } 03274 03275 return NULL; 03276 } 03277 03278 #ifdef TREASURE_DEBUG 03279 03283 static void check_treasurelist(treasure *t, treasurelist *tl) 03284 { 03285 if (t->item == NULL && t->name == NULL) 03286 { 03287 LOG(llevError, "Treasurelist %s has element with no name or archetype\n", tl->name); 03288 } 03289 03290 if (t->chance >= 100 && t->next_yes && (t->next || t->next_no)) 03291 { 03292 LOG(llevBug, "Treasurelist %s has element that has 100%% generation, next_yes field as well as next or next_no\n", tl->name); 03293 } 03294 03295 /* find_treasurelist will print out its own error message */ 03296 if (t->name && t->name != shstr_cons.NONE) 03297 { 03298 (void) find_treasurelist(t->name); 03299 } 03300 03301 if (t->next) 03302 { 03303 check_treasurelist(t->next, tl); 03304 } 03305 03306 if (t->next_yes) 03307 { 03308 check_treasurelist(t->next_yes, tl); 03309 } 03310 03311 if (t->next_no) 03312 { 03313 check_treasurelist(t->next_no, tl); 03314 } 03315 } 03316 #endif
1.7.4