Atrinik Server 2.5
server/gods.c
Go to the documentation of this file.
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 }