|
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 #include <global.h> 00031 00032 /* define this if you want to allow gods to assign more gifts 00033 * and limitations to priests */ 00034 #define MORE_PRIEST_GIFTS 00035 00036 static int lookup_god_by_name(const char *name); 00037 static int worship_forbids_use(object *op, object *exp_obj, uint32 flag, char *string); 00038 static void stop_using_item(object *op, int type, int number); 00039 static void update_priest_flag(object *god, object *exp_ob, uint32 flag); 00040 static int god_gives_present(object *op, object *god, treasure *tr); 00041 static int god_examines_priest(object *op, object *god); 00042 static int god_examines_item(object *god, object *item); 00043 static void lose_priest_exp(object *pl, int loss); 00044 static void god_intervention(object *op, object *god); 00045 00050 static int lookup_god_by_name(const char *name) 00051 { 00052 int godnr = -1; 00053 size_t nmlen = strlen(name); 00054 00055 if (name && strcmp(name, "none")) 00056 { 00057 godlink *gl; 00058 00059 for (gl = first_god; gl; gl = gl->next) 00060 { 00061 if (!strncmp(name, gl->name, MIN(strlen(gl->name), nmlen))) 00062 { 00063 break; 00064 } 00065 } 00066 00067 if (gl) 00068 { 00069 godnr = gl->id; 00070 } 00071 } 00072 00073 return godnr; 00074 } 00075 00080 object *find_god(const char *name) 00081 { 00082 object *god = NULL; 00083 00084 if (name) 00085 { 00086 godlink *gl; 00087 00088 for (gl = first_god; gl; gl = gl->next) 00089 { 00090 if (!strcmp(name, gl->name)) 00091 { 00092 break; 00093 } 00094 } 00095 00096 if (gl) 00097 { 00098 god = pntr_to_god_obj(gl); 00099 } 00100 } 00101 00102 return god; 00103 } 00104 00112 void pray_at_altar(object *pl, object *altar) 00113 { 00114 object *pl_god = find_god(determine_god(pl)); 00115 00116 /* If non consecrate altar, don't do anything */ 00117 if (!altar->other_arch) 00118 { 00119 return; 00120 } 00121 00122 /* new convert */ 00123 if (!pl_god) 00124 { 00125 become_follower(pl, &altar->other_arch->clone); 00126 return; 00127 } 00128 /* Pray at your gods altar */ 00129 else if (!strcmp(pl_god->name, altar->other_arch->clone.name)) 00130 { 00131 int bonus = ((pl->stats.Wis / 10) + (SK_level(pl) / 10)); 00132 00133 new_draw_info_format(0, COLOR_WHITE, pl, "You feel the powers of your deity %s.", pl_god->name); 00134 00135 /* We can get negative grace up faster */ 00136 if (pl->stats.grace < 0) 00137 { 00138 pl->stats.grace += (bonus > -1 * (pl->stats.grace / 10) ? bonus : -1 * (pl->stats.grace / 10)); 00139 } 00140 00141 /* We can super-charge grace to 2x max */ 00142 if (pl->stats.grace < (2 * pl->stats.maxgrace)) 00143 { 00144 pl->stats.grace += bonus / 2; 00145 } 00146 00147 /* I think there was a bug here in that this was nested 00148 * in the if immediately above */ 00149 if (pl->stats.grace > pl->stats.maxgrace) 00150 { 00151 pl->stats.grace = pl->stats.maxgrace; 00152 } 00153 00154 /* Every once in a while, the god decides to checkup on their 00155 * follower, and may intervene to help them out. */ 00156 bonus = MAX(1, bonus); 00157 00158 if (((rndm(0, 399)) - bonus) < 0) 00159 { 00160 god_intervention(pl, pl_god); 00161 } 00162 } 00163 /* Praying to another god! */ 00164 else 00165 { 00166 int loss = 0, angry = 1; 00167 00168 /* I believe the logic for detecting opposing gods was completely 00169 * broken - I think it should work now. altar->other_arch 00170 * points to the god of this altar (which we have 00171 * already verified is non null). pl_god->other_arch 00172 * is the opposing god - we need to verify that exists before 00173 * using its values. */ 00174 if (pl_god->other_arch && (altar->other_arch->name == pl_god->other_arch->name)) 00175 { 00176 angry = 2; 00177 00178 if (rndm(0, SK_level(pl) + 2) - 5 > 0) 00179 { 00180 /* you really screwed up */ 00181 angry = 3; 00182 new_draw_info_format(0, COLOR_NAVY, pl, "Foul priest! %s punishes you!", pl_god->name); 00183 cast_magic_storm(pl, get_archetype("loose_magic"), pl_god->level + 20); 00184 } 00185 00186 new_draw_info_format(0, COLOR_NAVY, pl, "Foolish heretic! %s is livid!", pl_god->name); 00187 } 00188 else 00189 { 00190 new_draw_info_format(0, COLOR_NAVY, pl, "Heretic! %s is angered!", pl_god->name); 00191 } 00192 00193 /* whether we will be successfull in defecting or not - 00194 * we lose experience from the clerical experience obj */ 00195 loss = (int) ((float) 0.1 * (float) pl->chosen_skill->exp_obj->stats.exp); 00196 00197 if (loss) 00198 { 00199 lose_priest_exp(pl, rndm(0, loss * angry - 1)); 00200 } 00201 00202 /* May switch Gods, but it's random chance based on our current 00203 * level. Note it gets harder to swap gods the higher we get */ 00204 if (QUERY_FLAG(altar, FLAG_XRAYS) || (angry == 1 && rndm_chance(pl->chosen_skill->exp_obj->level))) 00205 { 00206 become_follower(pl, &altar->other_arch->clone); 00207 } 00208 /* If angry... switching gods */ 00209 else 00210 { 00211 /* toss this player off the altar. He can try again. */ 00212 new_draw_info_format(0, COLOR_NAVY, pl, "A divine force pushes you off the altar."); 00213 /* back him off the way he came. */ 00214 move_player(pl, absdir(pl->facing + 4)); 00215 } 00216 } 00217 } 00218 00223 static int get_spell_number(object *op) 00224 { 00225 int spell; 00226 00227 if (op->slaying && (spell = look_up_spell_name(op->slaying)) >= 0) 00228 { 00229 return spell; 00230 } 00231 else 00232 { 00233 return op->stats.sp; 00234 } 00235 } 00236 00242 static void check_special_prayers(object *op, object *god) 00243 { 00244 treasure *tr; 00245 object *tmp, *next_tmp; 00246 int spell; 00247 00248 /* Outer loop iterates over all special prayer marks */ 00249 for (tmp = op->inv; tmp; tmp = next_tmp) 00250 { 00251 next_tmp = tmp->below; 00252 00253 if (tmp->type != FORCE || tmp->slaying == NULL || strcmp(tmp->slaying, "special prayer")) 00254 { 00255 continue; 00256 } 00257 00258 spell = tmp->stats.sp; 00259 00260 if (god->randomitems == NULL) 00261 { 00262 LOG(llevBug, "check_special_prayers(): %s without randomitems\n", query_name(god, NULL)); 00263 do_forget_spell(op, spell); 00264 continue; 00265 } 00266 00267 /* Inner loop tries to find the special prayer in the god's treasure 00268 * list. */ 00269 for (tr = god->randomitems->items; tr; tr = tr->next) 00270 { 00271 object *item; 00272 00273 if (tr->item == NULL) 00274 { 00275 continue; 00276 } 00277 00278 item = &tr->item->clone; 00279 00280 if (item->type == SPELLBOOK && get_spell_number(item) == spell) 00281 { 00282 /* Current god allows this special prayer. */ 00283 spell = -1; 00284 break; 00285 } 00286 } 00287 00288 if (spell >= 0) 00289 { 00290 do_forget_spell(op, spell); 00291 } 00292 } 00293 } 00294 00301 void become_follower(object *op, object *new_god) 00302 { 00303 /* obj. containing god data */ 00304 object *exp_obj = op->chosen_skill->exp_obj; 00305 treasure *tr; 00306 int i; 00307 00308 CONTR(op)->socket.ext_title_flag = 1; 00309 00310 /* give the player any special god-characteristic-items. */ 00311 for (tr = new_god->randomitems->items; tr != NULL; tr = tr->next) 00312 { 00313 if (tr->item && IS_SYS_INVISIBLE(&tr->item->clone) && tr->item->clone.type != SPELLBOOK && tr->item->clone.type != BOOK) 00314 { 00315 god_gives_present(op, new_god, tr); 00316 } 00317 } 00318 00319 if (!op || !new_god) 00320 { 00321 return; 00322 } 00323 00324 if (op->race && new_god->slaying && strstr(op->race, new_god->slaying)) 00325 { 00326 new_draw_info_format(0, COLOR_NAVY, op, "Fool! %s detests your kind!", new_god->name); 00327 00328 if (rndm(0, op->level - 1) - 5 > 0) 00329 { 00330 cast_magic_storm(op, get_archetype("loose_magic"), new_god->level + 10); 00331 } 00332 00333 return; 00334 } 00335 00336 new_draw_info_format(0, COLOR_NAVY, op, "You become a follower of %s!", new_god->name); 00337 00338 /* get rid of old god */ 00339 if (exp_obj->title) 00340 { 00341 new_draw_info_format(0, COLOR_WHITE, op, "%s's blessing is withdrawn from you.", exp_obj->title); 00342 CLEAR_FLAG(exp_obj, FLAG_APPLIED); 00343 (void) change_abil(op, exp_obj); 00344 FREE_AND_CLEAR_HASH2(exp_obj->title); 00345 } 00346 00347 /* now change to the new gods attributes to exp_obj */ 00348 FREE_AND_COPY_HASH(exp_obj->title, new_god->name); 00349 exp_obj->path_attuned = new_god->path_attuned; 00350 exp_obj->path_repelled = new_god->path_repelled; 00351 exp_obj->path_denied = new_god->path_denied; 00352 /* copy god's protections */ 00353 memcpy(exp_obj->protection, new_god->protection, sizeof(new_god->protection)); 00354 00355 /* make sure that certain immunities do NOT get passed to the 00356 * follower! */ 00357 for (i = 0; i < NROFATTACKS; i++) 00358 { 00359 if (exp_obj->protection[i] > 30 && (i == ATNR_FIRE || i == ATNR_COLD || i == ATNR_ELECTRICITY || i == ATNR_POISON)) 00360 { 00361 exp_obj->protection[i] = 30; 00362 } 00363 } 00364 00365 #ifdef MORE_PRIEST_GIFTS 00366 exp_obj->stats.hp = (sint16) new_god->last_heal; 00367 exp_obj->stats.sp = (sint16) new_god->last_sp; 00368 exp_obj->stats.grace = (sint16) new_god->last_grace; 00369 exp_obj->stats.food = (sint16) new_god->last_eat; 00370 /* gods may pass on certain flag properties */ 00371 update_priest_flag(new_god, exp_obj, FLAG_SEE_IN_DARK); 00372 update_priest_flag(new_god, exp_obj, FLAG_REFL_SPELL); 00373 update_priest_flag(new_god, exp_obj, FLAG_REFL_MISSILE); 00374 update_priest_flag(new_god, exp_obj, FLAG_STEALTH); 00375 update_priest_flag(new_god, exp_obj, FLAG_SEE_INVISIBLE); 00376 update_priest_flag(new_god, exp_obj, FLAG_UNDEAD); 00377 update_priest_flag(new_god, exp_obj, FLAG_BLIND); 00378 /* better have this if blind! */ 00379 update_priest_flag(new_god, exp_obj, FLAG_XRAYS); 00380 #endif 00381 00382 new_draw_info_format(0, COLOR_WHITE, op, "You are bathed in %s's aura.", new_god->name); 00383 00384 #ifdef MORE_PRIEST_GIFTS 00385 /* Weapon/armour use are special...handle flag toggles here as this can 00386 * only happen when gods are worshiped and if the new priest could 00387 * have used armour/weapons in the first place */ 00388 update_priest_flag(new_god,exp_obj, FLAG_USE_WEAPON); 00389 update_priest_flag(new_god,exp_obj, FLAG_USE_ARMOUR); 00390 00391 if (worship_forbids_use(op, exp_obj, FLAG_USE_WEAPON, "weapons")) 00392 { 00393 stop_using_item(op, WEAPON, 2); 00394 } 00395 00396 if (worship_forbids_use(op, exp_obj, FLAG_USE_ARMOUR, "armour")) 00397 { 00398 stop_using_item(op, ARMOUR, 1); 00399 stop_using_item(op, HELMET, 1); 00400 stop_using_item(op, BOOTS, 1); 00401 stop_using_item(op, GLOVES, 1); 00402 stop_using_item(op, SHIELD, 1); 00403 } 00404 #endif 00405 00406 SET_FLAG(exp_obj, FLAG_APPLIED); 00407 (void) change_abil(op, exp_obj); 00408 00409 check_special_prayers(op, new_god); 00410 } 00411 00419 static int worship_forbids_use(object *op, object *exp_obj, uint32 flag, char *string) 00420 { 00421 if (QUERY_FLAG(&op->arch->clone, flag)) 00422 { 00423 if (QUERY_FLAG(op, flag) != QUERY_FLAG(exp_obj, flag)) 00424 { 00425 update_priest_flag(exp_obj, op, flag); 00426 00427 if (QUERY_FLAG(op, flag)) 00428 { 00429 new_draw_info_format(0, COLOR_WHITE, op, "You may use %s again.", string); 00430 } 00431 else 00432 { 00433 new_draw_info_format(0, COLOR_WHITE, op, "You are forbidden to use %s.", string); 00434 return 1; 00435 } 00436 } 00437 } 00438 00439 return 0; 00440 } 00441 00450 static void stop_using_item(object *op, int type, int number) 00451 { 00452 object *tmp; 00453 00454 for (tmp = op->inv; tmp && number; tmp = tmp->below) 00455 { 00456 if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED)) 00457 { 00458 apply_special(op, tmp, AP_UNAPPLY | AP_IGNORE_CURSE); 00459 number--; 00460 } 00461 } 00462 } 00463 00470 static void update_priest_flag(object *god, object *exp_ob, uint32 flag) 00471 { 00472 if (QUERY_FLAG(god, flag) && !QUERY_FLAG(exp_ob, flag)) 00473 { 00474 SET_FLAG(exp_ob, flag); 00475 } 00476 else if (QUERY_FLAG(exp_ob, flag) && !QUERY_FLAG(god, flag)) 00477 { 00478 CLEAR_FLAG(exp_ob, flag); 00479 } 00480 } 00481 00488 const char *determine_god(object *op) 00489 { 00490 int godnr = -1; 00491 00492 /* spells */ 00493 if ((op->type == CONE || op->type == SWARM_SPELL) && op->title) 00494 { 00495 if (lookup_god_by_name(op->title) >= 0) 00496 { 00497 return op->title; 00498 } 00499 } 00500 00501 if (op->type != PLAYER && QUERY_FLAG(op, FLAG_ALIVE)) 00502 { 00503 if (!op->title) 00504 { 00505 godlink *gl = first_god; 00506 00507 godnr = rndm(1, gl->id); 00508 00509 while (gl) 00510 { 00511 if (gl->id == godnr) 00512 { 00513 break; 00514 } 00515 00516 gl = gl->next; 00517 } 00518 00519 FREE_AND_COPY_HASH(op->title, gl->name); 00520 } 00521 00522 return op->title; 00523 } 00524 00525 /* If we are player, let's search a bit harder for the god. This 00526 * is a fix for perceive self (before, we just looked at the active 00527 * skill.) */ 00528 if (op->type == PLAYER) 00529 { 00530 object *tmp; 00531 00532 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 00533 { 00534 if (tmp->type == EXPERIENCE && tmp->stats.Wis) 00535 { 00536 if (tmp->title) 00537 { 00538 return tmp->title; 00539 } 00540 else 00541 { 00542 return shstr_cons.none; 00543 } 00544 } 00545 } 00546 } 00547 00548 return shstr_cons.none; 00549 } 00550 00559 archetype *determine_holy_arch(object *god, const char *type) 00560 { 00561 treasure *tr; 00562 00563 if (!god || !god->randomitems) 00564 { 00565 LOG(llevBug, "determine_holy_arch(): no god or god without randomitems\n"); 00566 return NULL; 00567 } 00568 00569 for (tr = god->randomitems->items; tr != NULL; tr = tr->next) 00570 { 00571 object *item; 00572 00573 if (!tr->item) 00574 { 00575 continue; 00576 } 00577 00578 item = &tr->item->clone; 00579 00580 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && strcmp(item->name, type) == 0) 00581 { 00582 return item->other_arch; 00583 } 00584 } 00585 00586 return NULL; 00587 } 00588 00594 static int god_removes_curse(object *op, int remove_damnation) 00595 { 00596 object *tmp; 00597 int success = 0; 00598 00599 for (tmp = op->inv; tmp; tmp = tmp->below) 00600 { 00601 if (QUERY_FLAG(tmp, FLAG_DAMNED) && !remove_damnation) 00602 { 00603 continue; 00604 } 00605 00606 if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) 00607 { 00608 success = 1; 00609 CLEAR_FLAG(tmp, FLAG_DAMNED); 00610 CLEAR_FLAG(tmp, FLAG_CURSED); 00611 00612 if (op->type == PLAYER) 00613 { 00614 esrv_send_item(op, tmp); 00615 } 00616 } 00617 } 00618 00619 if (success) 00620 { 00621 new_draw_info(0, COLOR_WHITE, op, "You feel like someone is helping you."); 00622 } 00623 00624 return success; 00625 } 00626 00633 static int follower_level_to_enchantments(int level, int difficulty) 00634 { 00635 if (difficulty < 1) 00636 { 00637 LOG(llevBug, "follower_level_to_enchantments(): difficulty %d is invalid\n", difficulty); 00638 return 0; 00639 } 00640 00641 if (level <= 20) 00642 { 00643 return level / difficulty; 00644 } 00645 00646 if (level <= 40) 00647 { 00648 return (20 + (level - 20) / 2) / difficulty; 00649 } 00650 00651 return (30 + (level - 40) / 4) / difficulty; 00652 } 00653 00665 static int god_enchants_weapon(object *op, object *god, object *tr) 00666 { 00667 char buf[MAX_BUF]; 00668 object *weapon; 00669 int tmp; 00670 00671 for (weapon = op->inv; weapon; weapon = weapon->below) 00672 { 00673 if (weapon->type == WEAPON && QUERY_FLAG(weapon, FLAG_APPLIED)) 00674 { 00675 break; 00676 } 00677 } 00678 00679 if (weapon == NULL || god_examines_item(god, weapon) <= 0) 00680 { 00681 return 0; 00682 } 00683 00684 /* First give it a title, so other gods won't touch it */ 00685 if (!weapon->title) 00686 { 00687 snprintf(buf, sizeof(buf), "of %s", god->name); 00688 FREE_AND_COPY_HASH(weapon->title, buf); 00689 00690 if (op->type == PLAYER) 00691 { 00692 esrv_update_item(UPD_NAME, op, weapon); 00693 } 00694 00695 new_draw_info(0, COLOR_WHITE, op, "Your weapon quivers as if struck!"); 00696 } 00697 00698 /* Allow the weapon to slay enemies */ 00699 if (!weapon->slaying && god->slaying) 00700 { 00701 FREE_AND_COPY_HASH(weapon->slaying, god->slaying); 00702 new_draw_info_format(0, COLOR_WHITE, op, "Your %s now hungers to slay enemies of your god!", weapon->name); 00703 return 1; 00704 } 00705 00706 /* Higher magic value */ 00707 tmp = follower_level_to_enchantments(SK_level(op), tr->level); 00708 00709 if (weapon->magic < tmp) 00710 { 00711 new_draw_info(0, COLOR_WHITE, op, "A phosphorescent glow envelops your weapon!"); 00712 weapon->magic++; 00713 00714 if (op->type == PLAYER) 00715 { 00716 esrv_update_item(UPD_NAME, op, weapon); 00717 } 00718 00719 return 1; 00720 } 00721 00722 return 0; 00723 } 00724 00731 static int same_string(const char *s1, const char *s2) 00732 { 00733 if (s1 == NULL) 00734 { 00735 if (s2 == NULL) 00736 { 00737 return 1; 00738 } 00739 else 00740 { 00741 return 0; 00742 } 00743 } 00744 else 00745 { 00746 if (s2 == NULL) 00747 { 00748 return 0; 00749 } 00750 else 00751 { 00752 return strcmp(s1, s2) == 0; 00753 } 00754 } 00755 } 00756 00763 static int follower_has_similar_item(object *op, object *item) 00764 { 00765 object *tmp; 00766 00767 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 00768 { 00769 if (tmp->type == item->type && same_string(tmp->name, item->name) && same_string(tmp->title, item->title) && same_string(tmp->msg, item->msg) && same_string(tmp->slaying, item->slaying)) 00770 { 00771 return 1; 00772 } 00773 00774 if (tmp->inv && follower_has_similar_item(tmp, item)) 00775 { 00776 return 1; 00777 } 00778 } 00779 00780 return 0; 00781 } 00782 00789 static int god_gives_present(object *op, object *god, treasure *tr) 00790 { 00791 object *tmp; 00792 00793 if (follower_has_similar_item(op, &tr->item->clone)) 00794 { 00795 return 0; 00796 } 00797 00798 tmp = arch_to_object(tr->item); 00799 new_draw_info_format(0, COLOR_WHITE, op, "%s lets %s appear in your hands.", god->name, query_short_name(tmp, NULL)); 00800 tmp = insert_ob_in_ob(tmp, op); 00801 00802 if (op->type == PLAYER) 00803 { 00804 esrv_send_item(op, tmp); 00805 } 00806 00807 return 1; 00808 } 00809 00815 static void god_intervention(object *op, object *god) 00816 { 00817 int level = SK_level(op); 00818 treasure *tr; 00819 00820 if (!god || !god->randomitems) 00821 { 00822 LOG(llevBug, "god_intervention(): (p:%s) no god %s or god without randomitems\n", query_name(op, NULL), query_name(god, NULL)); 00823 return; 00824 } 00825 00826 check_special_prayers(op, god); 00827 00828 /* Let's do some checks of whether we are kosher with our god */ 00829 if (god_examines_priest(op, god) < 0) 00830 { 00831 return; 00832 } 00833 00834 new_draw_info(0, COLOR_WHITE, op, "You feel a holy presence!"); 00835 00836 for (tr = god->randomitems->items; tr != NULL; tr = tr->next) 00837 { 00838 object *item; 00839 00840 if (tr->chance <= rndm(0, 99)) 00841 { 00842 continue; 00843 } 00844 00845 /* Treasurelist - generate some treasure for the follower */ 00846 if (tr->name) 00847 { 00848 treasurelist *tl = find_treasurelist(tr->name); 00849 00850 if (tl == NULL) 00851 { 00852 continue; 00853 } 00854 00855 new_draw_info(0, COLOR_WHITE, op, "Something appears before your eyes. You catch it before it falls to the ground."); 00856 create_treasure(tl, op, GT_STARTEQUIP | GT_ONLY_GOOD | GT_UPDATE_INV, level, T_STYLE_UNSET, ART_CHANCE_UNSET, 0, NULL); 00857 return; 00858 } 00859 00860 if (!tr->item) 00861 { 00862 LOG(llevBug, "Empty entry in %s's treasure list\n", query_name(god, NULL)); 00863 continue; 00864 } 00865 00866 item = &tr->item->clone; 00867 00868 /* Grace limit */ 00869 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.grace_limit) 00870 { 00871 if (op->stats.grace < item->stats.grace || op->stats.grace < op->stats.maxgrace) 00872 { 00873 #if 0 00874 /* Follower lacks the required grace for the following 00875 * treasure list items. */ 00876 (void) cast_change_attr(op, op, op, SP_HOLY_POSSESSION); 00877 #endif 00878 return; 00879 } 00880 00881 continue; 00882 } 00883 00884 /* Restore grace */ 00885 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.restore_grace) 00886 { 00887 if (op->stats.grace >= 0) 00888 { 00889 continue; 00890 } 00891 00892 op->stats.grace = rndm(0, 9); 00893 new_draw_info(0, COLOR_WHITE, op, "You are returned to a state of grace."); 00894 return; 00895 } 00896 00897 /* Heal damage */ 00898 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.restore_hitpoints) 00899 { 00900 if (op->stats.hp >= op->stats.maxhp) 00901 { 00902 continue; 00903 } 00904 00905 new_draw_info(0, COLOR_WHITE, op, "A white light surrounds and heals you!"); 00906 op->stats.hp = op->stats.maxhp; 00907 return; 00908 } 00909 00910 /* Restore spellpoints */ 00911 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.restore_hitpoints) 00912 { 00913 int max = (int) ((float) op->stats.maxsp * ((float) item->stats.maxsp / (float) 100.0)); 00914 /* Restore to 50 .. 100%, if sp < 50% */ 00915 int new_sp = (int) (rndm(1000, 1999) / 2000.0 * (float) max); 00916 00917 if (op->stats.sp >= max / 2) 00918 { 00919 continue; 00920 } 00921 00922 new_draw_info(0, COLOR_WHITE, op, "A blue lightning strikes your head but doesn't hurt you!"); 00923 op->stats.sp = new_sp; 00924 } 00925 00926 /* Various heal spells */ 00927 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.heal_spell) 00928 { 00929 if (cast_heal(op, 1, op, get_spell_number(item))) 00930 { 00931 return; 00932 } 00933 else 00934 { 00935 continue; 00936 } 00937 } 00938 00939 /* Remove curse */ 00940 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.remove_curse) 00941 { 00942 if (god_removes_curse(op, 0)) 00943 { 00944 return; 00945 } 00946 else 00947 { 00948 continue; 00949 } 00950 } 00951 00952 /* Remove damnation */ 00953 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.remove_damnation) 00954 { 00955 if (god_removes_curse(op, 1)) 00956 { 00957 return; 00958 } 00959 else 00960 { 00961 continue; 00962 } 00963 } 00964 00965 /* Heal depletion */ 00966 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.heal_depletion) 00967 { 00968 object *depl; 00969 archetype *at; 00970 int i; 00971 00972 if ((at = find_archetype("depletion")) == NULL) 00973 { 00974 LOG(llevBug, "Could not find archetype depletion.\n"); 00975 continue; 00976 } 00977 00978 depl = present_arch_in_ob(at, op); 00979 00980 if (depl == NULL) 00981 { 00982 continue; 00983 } 00984 00985 new_draw_info(0, COLOR_WHITE, op, "Shimmering light surrounds and restores you!"); 00986 00987 for (i = 0; i < NUM_STATS; i++) 00988 { 00989 if (get_attr_value(&depl->stats, i)) 00990 { 00991 new_draw_info(0, COLOR_WHITE, op, restore_msg[i]); 00992 } 00993 } 00994 00995 remove_ob(depl); 00996 fix_player(op); 00997 return; 00998 } 00999 01000 /* Messages */ 01001 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.message) 01002 { 01003 new_draw_info(0, COLOR_WHITE, op, item->msg); 01004 return; 01005 } 01006 01007 /* Enchant weapon */ 01008 if (item->type == BOOK && IS_SYS_INVISIBLE(item) && item->name == shstr_cons.enchant_weapon) 01009 { 01010 if (god_enchants_weapon(op, god, item)) 01011 { 01012 return; 01013 } 01014 else 01015 { 01016 continue; 01017 } 01018 } 01019 01020 /* Spellbooks - works correctly only for prayers */ 01021 if (item->type == SPELLBOOK) 01022 { 01023 int spell = get_spell_number(item); 01024 01025 if (check_spell_known(op, spell)) 01026 { 01027 continue; 01028 } 01029 01030 if (spells[spell].level > level) 01031 { 01032 continue; 01033 } 01034 01035 if (IS_SYS_INVISIBLE(item)) 01036 { 01037 new_draw_info_format(0, COLOR_WHITE, op, "%s grants you use of a special prayer!", god->name); 01038 do_learn_spell(op, spell, 1); 01039 return; 01040 } 01041 01042 if (!QUERY_FLAG(item, FLAG_STARTEQUIP)) 01043 { 01044 LOG(llevBug, "visible spellbook in %s's treasure list lacks FLAG_STARTEQUIP\n", query_name(god, NULL)); 01045 continue; 01046 } 01047 01048 if (!item->stats.Wis) 01049 { 01050 LOG(llevBug, "visible spellbook in %s's treasure list doesn't contain a special prayer\n", query_name(god, NULL)); 01051 continue; 01052 } 01053 01054 if (god_gives_present(op, god, tr)) 01055 { 01056 return; 01057 } 01058 else 01059 { 01060 continue; 01061 } 01062 } 01063 01064 /* Other gifts */ 01065 if (!IS_SYS_INVISIBLE(item)) 01066 { 01067 if (god_gives_present(op, god, tr)) 01068 { 01069 return; 01070 } 01071 else 01072 { 01073 continue; 01074 } 01075 } 01076 } 01077 01078 new_draw_info(0, COLOR_WHITE, op, "You feel rapture."); 01079 } 01080 01091 static int god_examines_priest(object *op, object *god) 01092 { 01093 int reaction = 1; 01094 object *item = NULL; 01095 01096 for (item = op->inv; item; item = item->below) 01097 { 01098 if (QUERY_FLAG(item, FLAG_APPLIED)) 01099 { 01100 reaction += god_examines_item(god, item) * (item->magic ? abs(item->magic) : 1); 01101 } 01102 } 01103 01104 /* Well, well. Looks like we screwed up. Time for god's revenge */ 01105 if (reaction < 0) 01106 { 01107 int loss = 10000000, angry = abs(reaction); 01108 01109 if (op->chosen_skill->exp_obj) 01110 { 01111 loss = (int) ((float) 0.05 * (float) op->chosen_skill->exp_obj->stats.exp); 01112 } 01113 01114 lose_priest_exp(op, rndm(0, loss * angry - 1)); 01115 01116 if (rndm(0, angry)) 01117 { 01118 cast_magic_storm(op, get_archetype("loose_magic"), SK_level(op) + (angry * 3)); 01119 } 01120 01121 new_draw_info_format(0, COLOR_NAVY, op, "%s becomes angry and punishes you!", god->name); 01122 } 01123 01124 return reaction; 01125 } 01126 01135 static int god_examines_item(object *god, object *item) 01136 { 01137 char buf[MAX_BUF]; 01138 01139 if (!god || !item) 01140 { 01141 return 0; 01142 } 01143 01144 /* unclaimed item are ok */ 01145 if (!item->title) 01146 { 01147 return 1; 01148 } 01149 01150 snprintf(buf, sizeof(buf), "of %s", god->name); 01151 01152 /* belongs to that God */ 01153 if (!strcmp(item->title, buf)) 01154 { 01155 return 1; 01156 } 01157 01158 /* check if we have any enemy blessed item */ 01159 if (god->title) 01160 { 01161 snprintf(buf, sizeof(buf), "of %s", god->title); 01162 01163 if (!strcmp(item->title, buf)) 01164 { 01165 if (item->env) 01166 { 01167 new_draw_info_format(0, COLOR_NAVY, item->env, "Heretic! You are using %s!", query_name(item, NULL)); 01168 } 01169 01170 return -1; 01171 } 01172 } 01173 01174 /* item is sacred to a non-enemy god/or is otherwise magical */ 01175 return 0; 01176 } 01177 01183 static void lose_priest_exp(object *pl, int loss) 01184 { 01185 (void) pl; 01186 (void) loss; 01187 #if 0 01188 if (!pl || pl->type != PLAYER || !pl->chosen_skill || !pl->chosen_skill->exp_obj) 01189 { 01190 LOG(llevBug, "Bad call to lose_priest_exp()\n"); 01191 return; 01192 } 01193 01194 if ((loss = check_dm_add_exp_to_obj(pl->chosen_skill->exp_obj, loss, 0))) 01195 { 01196 add_exp(pl, -loss, pl->chosen_skill->stats.sp, 0); 01197 } 01198 #endif 01199 }
1.7.4