Crossfire Server, Branch 1.12  R12190
gods.c
Go to the documentation of this file.
00001 /*
00002  * static char *rcsid_gods_c =
00003  *   "$Id: gods.c 14477 2011-05-21 17:59:50Z ryo_saeba $";
00004  */
00005 
00006 /*
00007     CrossFire, A Multiplayer game for X-windows
00008 
00009     Copyright (C) 2006 Mark Wedel & Crossfire Development Team
00010     Copyright (C) 1992 Frank Tore Johansen
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00025 
00026     The authors can be reached via e-mail at crossfire-devel@real-time.com
00027 */
00028 
00039 #include <global.h>
00040 #include <living.h>
00041 #include <object.h>
00042 #include <spells.h>
00043 #include <sounds.h>
00044 #ifndef __CEXTRACT__
00045 #include <sproto.h>
00046 #endif
00047 
00048 static int worship_forbids_use(object *op, object *exp_obj, uint32 flag, const char *string);
00049 static void stop_using_item(object *op, int type, int number);
00050 static void update_priest_flag(const object *god, object *exp_ob, uint32 flag);
00051 static void god_intervention(object *op, const object *god, object *skill);
00052 static int god_examines_priest(object *op, const object *god);
00053 static int god_examines_item(const object *god, object *item);
00054 static const char *get_god_for_race(const char *race);
00055 
00066 static int lookup_god_by_name(const char *name) {
00067     int godnr = -1;
00068     size_t nmlen = strlen(name);
00069 
00070     if (name && strcmp(name, "none")) {
00071         godlink *gl;
00072         for (gl = first_god; gl; gl = gl->next)
00073             if (!strncmp(name, gl->name, MIN(strlen(gl->name), nmlen)))
00074                 break;
00075         if (gl)
00076             godnr = gl->id;
00077     }
00078     return godnr;
00079 }
00080 
00092 const object *find_god(const char *name) {
00093     godlink *gl;
00094 
00095     if (!name)
00096         return NULL;
00097 
00098     for (gl = first_god; gl; gl = gl->next) {
00099         if (!strcmp(name, gl->name))
00100             return pntr_to_god_obj(gl);
00101     }
00102 
00103     return NULL;
00104 }
00105 
00118 const char *determine_god(object *op) {
00119     int godnr = -1;
00120     const char *godname;
00121 
00122     /* spells */
00123     if ((op->type == SPELL || op->type == SPELL_EFFECT)
00124     && op->title) {
00125         if (lookup_god_by_name(op->title) >= 0)
00126             return op->title;
00127     }
00128 
00129     if (op->type != PLAYER && QUERY_FLAG(op, FLAG_ALIVE)) {
00130         /* find a god based on race */
00131         if (!op->title) {
00132             if (op->race != NULL) {
00133                 godname = get_god_for_race(op->race);
00134                 if (godname != NULL) {
00135                     op->title = add_string(godname);
00136                 }
00137             }
00138         }
00139 
00140         /* find a random god */
00141         if (!op->title) {
00142             godlink *gl = first_god;
00143 
00144             godnr = rndm(1, gl->id);
00145             while (gl) {
00146                 if (gl->id == godnr)
00147                     break;
00148                 gl = gl->next;
00149             }
00150             op->title = add_string(gl->name);
00151         }
00152 
00153         return op->title;
00154     }
00155 
00156     /* The god the player worships is in the praying skill (native skill
00157      * not skill tool).  Since a player can only have one instance of
00158      * that skill, once we find it, we can return, either with the
00159      * title or "none".
00160      */
00161     if (op->type == PLAYER) {
00162         object *tmp;
00163 
00164         for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
00165             if (tmp->type == SKILL && tmp->subtype == SK_PRAYING) {
00166                 if (tmp->title)
00167                     return (tmp->title);
00168                 else
00169                     return("none");
00170             }
00171     }
00172     return ("none");
00173 }
00174 
00183 static int same_string(const char *s1, const char *s2) {
00184     if (s1 == NULL)
00185         if (s2 == NULL)
00186             return 1;
00187         else
00188             return 0;
00189     else
00190         if (s2 == NULL)
00191             return 0;
00192         else
00193             return strcmp(s1, s2) == 0;
00194 }
00195 
00211 static void follower_remove_given_items(object *pl, object *op, const object *god) {
00212     object *tmp, *next;
00213     const char *given_by;
00214 
00215     /* search the inventory */
00216     for (tmp = op->inv; tmp != NULL; tmp = next) {
00217         next = tmp->below;   /* backup in case we remove tmp */
00218 
00219         given_by = get_ob_key_value(tmp, "divine_giver_name");
00220         if (given_by == god->name) {
00221             char name[HUGE_BUF];
00222 
00223             query_short_name(tmp, name, HUGE_BUF);
00224             /* Send the client a message. */
00225             if (tmp->nrof > 1)
00226                 draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_ITEM, MSG_TYPE_ITEM_REMOVE,
00227                                      "The %s crumble to dust!",
00228                                      "The %s crumble to dust!",
00229                                      name);
00230             else
00231                 draw_ext_info_format(NDI_UNIQUE, 0, pl, MSG_TYPE_ITEM, MSG_TYPE_ITEM_REMOVE,
00232                                      "The %s crumbles to dust!",
00233                                      "The %s crumbles to dust!",
00234                                      name);
00235 
00236             remove_ob(tmp);    /* remove obj from players inv. */
00237             free_object(tmp);
00238         } else if (tmp->inv)
00239             follower_remove_given_items(pl, tmp, god);
00240     }
00241 }
00242 
00252 static int follower_has_similar_item(object *op, object *item) {
00253     object *tmp;
00254 
00255     for (tmp = op->inv; tmp != NULL; tmp = tmp->below) {
00256         if (tmp->type == item->type
00257         && same_string(tmp->name, item->name)
00258         && same_string(tmp->title, item->title)
00259         && same_string(tmp->msg, item->msg)
00260         && same_string(tmp->slaying, item->slaying))
00261             return 1;
00262         if (tmp->inv && follower_has_similar_item(tmp, item))
00263             return 1;
00264     }
00265     return 0;
00266 }
00267 
00280 static int god_gives_present(object *op, const object *god, treasure *tr) {
00281     object *tmp;
00282     char name[HUGE_BUF];
00283 
00284     if (follower_has_similar_item(op, &tr->item->clone))
00285         return 0;
00286 
00287     tmp = arch_to_object(tr->item);
00288 
00289     /*
00290      * Give inventory if needed, for instance Lythander's pipe.
00291      * Use high level and magic so something IS put in inventory.
00292      */
00293     fix_generated_item(tmp, NULL, 120, 120, GT_ONLY_GOOD);
00294 
00295     /* And just in case nothing was put and something is needed, bail out. */
00296     if ((tmp->type == ROD || tmp->type == WAND) && (tmp->inv == NULL)) {
00297         free_object2(tmp, 0);
00298         return 0;
00299     }
00300 
00301     query_short_name(tmp, name, HUGE_BUF);
00302     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_ADD,
00303                          "%s lets %s appear in your hands.",
00304                          NULL,
00305                          god->name, name);
00309     set_ob_key_value(tmp, "divine_giver_name", god->name, TRUE);
00310     insert_ob_in_ob(tmp, op);
00311     return 1;
00312 }
00313 
00325 void pray_at_altar(object *pl, object *altar, object *skill) {
00326     const object *pl_god = find_god(determine_god(pl));
00327 
00328     /* Lauwenmark: Handle for plugin altar-praying (apply) event */
00329     if (execute_event(altar, EVENT_APPLY, pl, NULL, NULL, SCRIPT_FIX_ALL) != 0)
00330         return;
00331 
00332     /* If non consecrate altar, don't do anything */
00333     if (!altar->other_arch)
00334         return;
00335 
00336     /* hmm. what happend depends on pl's current god, level, etc */
00337     if (!pl_god) { /*new convert */
00338         become_follower(pl, &altar->other_arch->clone);
00339         return;
00340 
00341     } else if (!strcmp(pl_god->name, altar->other_arch->clone.name)) {
00342         /* pray at your gods altar */
00343         int bonus = (pl->stats.Wis+skill->level)/10;
00344 
00345         /* we can get neg grace up faster */
00346         if (pl->stats.grace < 0)
00347             pl->stats.grace += (bonus > -1*(pl->stats.grace/10) ? bonus : -1*(pl->stats.grace/10));
00348         /* we can super-charge grace to 2x max */
00349         if (pl->stats.grace < (2*pl->stats.maxgrace)) {
00350             pl->stats.grace += bonus/2;
00351         }
00352         if (pl->stats.grace > (2*pl->stats.maxgrace)) {
00353             pl->stats.grace = (2*pl->stats.maxgrace);
00354         }
00355 
00356         /* Every once in a while, the god decides to checkup on their
00357          * follower, and may intervene to help them out.
00358          */
00359         bonus = MAX(1, bonus+MAX(pl->stats.luck, -3)); /* -- DAMN -- */
00360 
00361         if (((random_roll(0, 399, pl, PREFER_LOW))-bonus) < 0)
00362             god_intervention(pl, pl_god, skill);
00363 
00364     } else { /* praying to another god! */
00365         uint64 loss = 0;
00366         int angry = 1;
00367 
00368         /* I believe the logic for detecting opposing gods was completely
00369          * broken - I think it should work now.  altar->other_arch
00370          * points to the god of this altar (which we have
00371          * already verified is non null).  pl_god->other_arch
00372          * is the opposing god - we need to verify that exists before
00373          * using its values.
00374          */
00375         if (pl_god->other_arch
00376         && (altar->other_arch->name == pl_god->other_arch->name)) {
00377             angry = 2;
00378             if (random_roll(0, skill->level+2, pl, PREFER_LOW)-5 > 0) {
00379                 object *tmp;
00380 
00381                 /* you really screwed up */
00382                 angry = 3;
00383                 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00384                                      "Foul Priest! %s punishes you!",
00385                                      "Foul Priest! %s punishes you!",
00386                                      pl_god->name);
00387                 tmp = create_archetype(LOOSE_MANA);
00388                 cast_magic_storm(pl, tmp, pl_god->level+20);
00389             } else
00390                 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00391                                      "Foolish heretic! %s is livid!",
00392                                      "Foolish heretic! %s is livid!",
00393                                      pl_god->name);
00394         } else
00395             draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00396                                  "Heretic! %s is angered!",
00397                                  "Heretic! %s is angered!",
00398                                  pl_god->name);
00399 
00400         /* whether we will be successfull in defecting or not -
00401          * we lose experience from the clerical experience obj
00402          */
00403 
00404         loss = angry*(skill->stats.exp/10);
00405         if (loss)
00406             change_exp(pl, -random_roll64(0, loss, pl, PREFER_LOW), skill ? skill->skill : "none", SK_SUBTRACT_SKILL_EXP);
00407 
00408         /* May switch Gods, but its random chance based on our current level
00409          * note it gets harder to swap gods the higher we get
00410          */
00411         if ((angry == 1) && !(random_roll(0, skill->level, pl, PREFER_LOW))) {
00412             become_follower(pl, &altar->other_arch->clone);
00413         } else {
00414             /* toss this player off the altar.  He can try again. */
00415             draw_ext_info(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00416                           "A divine force pushes you off the altar.", NULL);
00417 
00418             move_player(pl, absdir(pl->facing+4)); /* back him off the way he came. */
00419         }
00420     }
00421 }
00422 
00431 static void check_special_prayers(object *op, const object *god) {
00432     /* Ensure that 'op' doesn't know any special prayers that are not granted
00433      * by 'god'.
00434      */
00435     treasure *tr;
00436     object *tmp, *next_tmp;
00437     int remove = 0;
00438 
00439     /* Outer loop iterates over all special prayer marks */
00440     for (tmp = op->inv; tmp; tmp = next_tmp) {
00441         next_tmp = tmp->below;
00442 
00443         /* we mark special prayers with the STARTEQUIP flag, so if it isn't
00444          * in that category, not something we need to worry about.
00445          */
00446         if (tmp->type != SPELL || !QUERY_FLAG(tmp, FLAG_STARTEQUIP))
00447             continue;
00448 
00449         if (god->randomitems == NULL) {
00450             LOG(llevError, "BUG: check_special_prayers(): god %s without randomitems\n", god->name);
00451             do_forget_spell(op, tmp->name);
00452             continue;
00453         }
00454 
00455         /* Inner loop tries to find the special prayer in the god's treasure
00456          * list. We default that the spell should be removed.
00457         */
00458         remove = 1;
00459         for (tr = god->randomitems->items; tr; tr = tr->next) {
00460             object *item;
00461 
00462             if (tr->item == NULL)
00463                 continue;
00464             item = &tr->item->clone;
00465 
00466             /* Basically, see if the matching spell is granted by this god. */
00467 
00468             if (tr->item->clone.type == SPELL && tr->item->clone.name == tmp->name) {
00469                 remove = 0;
00470                 break;
00471             }
00472         }
00473         if (remove) {
00474             /* just do the work of removing the spell ourselves - we already
00475              * know that the player knows the spell
00476              */
00477             draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op,
00478                                  MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00479                                  "You lose knowledge of %s.",
00480                                  "You lose knowledge of %s.",
00481                                  tmp->name);
00482             player_unready_range_ob(op->contr, tmp);
00483             remove_ob(tmp);
00484             free_object(tmp);
00485         }
00486 
00487     }
00488 }
00489 
00502 void become_follower(object *op, const object *new_god) {
00503     const object *old_god = NULL;                      /* old god */
00504     treasure *tr;
00505     object *item, *skop, *next;
00506     int i, sk_applied;
00507     int undeadified = 0; /* Turns to true if changing god can changes the undead
00508                           * status of the player.*/
00509     old_god = find_god(determine_god(op));
00510 
00511     /* take away any special god-characteristic items. */
00512     for (item = op->inv; item != NULL; item = next) {
00513         next = item->below;
00514         /* remove all invisible startequip items which are
00515          *  not skill, exp or force
00516           */
00517         if (QUERY_FLAG(item, FLAG_STARTEQUIP)
00518         && item->invisible
00519         && (item->type != SKILL)
00520         && (item->type != EXPERIENCE)
00521         && (item->type != FORCE)) {
00522             if (item->type == SPELL)
00523                 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00524                                      "You lose knowledge of %s.",
00525                                      "You lose knowledge of %s.",
00526                                      item->name);
00527             player_unready_range_ob(op->contr, item);
00528             remove_ob(item);
00529             free_object(item);
00530         }
00531     }
00532 
00533     /* remove any items given by the old god */
00534     if (old_god) {
00535         /* Changed to use the new "divine_giver_name" key_value
00536          *   so it can reliably delete enchanted items.  Now it loops
00537          *   through the player's inventory, instead of the god's
00538          *   treasure list.
00539          */
00540         follower_remove_given_items(op, op, old_god);
00541     }
00542 
00543     if (!op || !new_god)
00544         return;
00545 
00546     if (op->race && new_god->slaying && strstr(op->race, new_god->slaying)) {
00547         draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00548                              "Fool! %s detests your kind!",
00549                              "Fool! %s detests your kind!",
00550                              new_god->name);
00551         if (random_roll(0, op->level-1, op, PREFER_LOW)-5 > 0) {
00552             object *tmp = create_archetype(LOOSE_MANA);
00553             cast_magic_storm(op, tmp, new_god->level+10);
00554         }
00555         return;
00556     }
00557 
00558     /* give the player any special god-characteristic-items. */
00559     for (tr = new_god->randomitems->items; tr != NULL; tr = tr->next) {
00560         if (tr->item
00561         && tr->item->clone.invisible
00562         && tr->item->clone.type != SPELLBOOK
00563         && tr->item->clone.type != BOOK
00564         && tr->item->clone.type != SPELL)
00565             god_gives_present(op, new_god, tr);
00566     }
00567 
00568     draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00569                          "You become a follower of %s!",
00570                          "You become a follower of %s!",
00571                          new_god->name);
00572 
00573     for (skop = op->inv; skop != NULL; skop = skop->below)
00574         if (skop->type == SKILL && skop->subtype == SK_PRAYING)
00575             break;
00576 
00577     /* Player has no skill - give them the skill */
00578     if (!skop) {
00579         /* The archetype should always be defined - if we crash here because it doesn't,
00580          * things are really messed up anyways.
00581          */
00582         skop = give_skill_by_name(op, get_archetype_by_type_subtype(SKILL, SK_PRAYING)->clone.skill);
00583         link_player_skills(op);
00584     }
00585 
00586     sk_applied = QUERY_FLAG(skop, FLAG_APPLIED); /* save skill status */
00587 
00588     /* Clear the "undead" status. We also need to force a call to change_abil,
00589      * so I set undeadified for that.
00590      * - gros, 21th July 2006.
00591      */
00592     if ((old_god) && (QUERY_FLAG(old_god, FLAG_UNDEAD))) {
00593         CLEAR_FLAG(skop, FLAG_UNDEAD);
00594         undeadified = 1;
00595     }
00596 
00597     if (skop->title) { /* get rid of old god */
00598         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00599                              "%s's blessing is withdrawn from you.",
00600                              "%s's blessing is withdrawn from you.",
00601                              skop->title);
00602 
00603         /* The point of this is to really show what abilities the player just lost */
00604         if (sk_applied || undeadified) {
00605             CLEAR_FLAG(skop, FLAG_APPLIED);
00606             (void)change_abil(op, skop);
00607         }
00608         free_string(skop->title);
00609     }
00610 
00611     /* now change to the new gods attributes to exp_obj */
00612     skop->title = add_string(new_god->name);
00613     skop->path_attuned = new_god->path_attuned;
00614     skop->path_repelled = new_god->path_repelled;
00615     skop->path_denied = new_god->path_denied;
00616     /* copy god's resistances */
00617     memcpy(skop->resist, new_god->resist, sizeof(new_god->resist));
00618 
00619     /* make sure that certain immunities do NOT get passed
00620      * to the follower!
00621      */
00622     for (i = 0; i < NROFATTACKS; i++)
00623         if (skop->resist[i] > 30
00624         && (i == ATNR_FIRE || i == ATNR_COLD || i == ATNR_ELECTRICITY || i == ATNR_POISON))
00625             skop->resist[i] = 30;
00626 
00627     skop->stats.hp = (sint16)new_god->last_heal;
00628     skop->stats.sp = (sint16)new_god->last_sp;
00629     skop->stats.grace = (sint16)new_god->last_grace;
00630     skop->stats.food = (sint16)new_god->last_eat;
00631     skop->stats.luck = (sint8)new_god->stats.luck;
00632     /* gods may pass on certain flag properties */
00633     update_priest_flag(new_god, skop, FLAG_SEE_IN_DARK);
00634     update_priest_flag(new_god, skop, FLAG_REFL_SPELL);
00635     update_priest_flag(new_god, skop, FLAG_REFL_MISSILE);
00636     update_priest_flag(new_god, skop, FLAG_STEALTH);
00637     update_priest_flag(new_god, skop, FLAG_MAKE_INVIS);
00638     update_priest_flag(new_god, skop, FLAG_UNDEAD);
00639     update_priest_flag(new_god, skop, FLAG_BLIND);
00640     update_priest_flag(new_god, skop, FLAG_XRAYS); /* better have this if blind! */
00641     update_priest_flag(new_god, skop, FLAG_USE_WEAPON);
00642     update_priest_flag(new_god, skop, FLAG_USE_ARMOUR);
00643     update_priest_flag(new_god, skop, FLAG_USE_SHIELD);
00644 
00645     draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00646                          "You are bathed in %s's aura.",
00647                          "You are bathed in %s's aura.",
00648                          new_god->name);
00649 
00650     /* Weapon/armour use are special...handle flag toggles here as this can
00651      * only happen when gods are worshipped and if the new priest could
00652      * have used armour/weapons in the first place.
00653      *
00654      * This also can happen for monks which cannot use weapons. In this case
00655      * do not allow to use weapons even if the god otherwise would allow it.
00656      */
00657     if (!present_in_ob_by_name(FORCE, "no weapon force", op)) {
00658         if (worship_forbids_use(op, skop, FLAG_USE_WEAPON, "weapons"))
00659             stop_using_item(op, WEAPON, 2);
00660     }
00661     update_priest_flag(new_god, skop, FLAG_USE_ARMOUR);
00662 
00663     if (worship_forbids_use(op, skop, FLAG_USE_ARMOUR, "armour")) {
00664         stop_using_item(op, ARMOUR, 1);
00665         stop_using_item(op, HELMET, 1);
00666         stop_using_item(op, BOOTS, 1);
00667         stop_using_item(op, GLOVES, 1);
00668     }
00669 
00670     if (worship_forbids_use(op, skop, FLAG_USE_SHIELD, "shield"))
00671         stop_using_item(op, SHIELD, 1);
00672 
00673     SET_FLAG(skop, FLAG_APPLIED);
00674     (void)change_abil(op, skop);
00675 
00676     /* return to previous skill status */
00677     if (!sk_applied)
00678         CLEAR_FLAG(skop, FLAG_APPLIED);
00679 
00680     check_special_prayers(op, new_god);
00681 }
00682 
00696 static int worship_forbids_use(object *op, object *exp_obj, uint32 flag, const char *string) {
00697     if (QUERY_FLAG(&op->arch->clone, flag)) {
00698         if (QUERY_FLAG(op, flag) != QUERY_FLAG(exp_obj, flag)) {
00699             update_priest_flag(exp_obj, op, flag);
00700             if (QUERY_FLAG(op, flag))
00701                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00702                                      "You may use %s again.",
00703                                      "You may use %s again.",
00704                                      string);
00705             else {
00706                 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00707                                      "You are forbidden to use %s.",
00708                                      "You are forbidden to use %s.",
00709                                      string);
00710                 return 1;
00711             }
00712         }
00713     }
00714     return 0;
00715 }
00716 
00728 static void stop_using_item(object *op, int type, int number) {
00729     object *tmp;
00730 
00731     for (tmp = op->inv; tmp && number; tmp = tmp->below)
00732         if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED)) {
00733             apply_special(op, tmp, AP_UNAPPLY|AP_IGNORE_CURSE);
00734             number--;
00735         }
00736 }
00737 
00750 static void update_priest_flag(const object *god, object *exp_ob, uint32 flag) {
00751     if (QUERY_FLAG(god, flag) && !QUERY_FLAG(exp_ob, flag))
00752         SET_FLAG(exp_ob, flag);
00753     else if (QUERY_FLAG(exp_ob, flag) && !QUERY_FLAG(god, flag)) {
00754         /*  When this is called with the exp_ob set to the player,
00755          * this check is broken, because most all players arch
00756          * allow use of weapons.  I'm not actually sure why this
00757          * check is here - I guess if you had a case where the
00758          * value in the archetype (wisdom) should over ride the restrictions
00759          * the god places on it, this may make sense.  But I don't think
00760          * there is any case like that.
00761          */
00762 
00763 /*      if (!(QUERY_FLAG(&(exp_ob->arch->clone), flag)))*/
00764         CLEAR_FLAG(exp_ob, flag);
00765     }
00766 }
00767 
00768 
00782 archetype *determine_holy_arch(const object *god, const char *type) {
00783     treasure *tr;
00784     int count;
00785     archetype *last;
00786     object *item;
00787 
00788     if (!god || !god->randomitems) {
00789         LOG(llevError, "BUG: determine_holy_arch(): no god or god without randomitems\n");
00790         return NULL;
00791     }
00792 
00793     count = 0;
00794     last = NULL;
00795     for (tr = god->randomitems->items; tr != NULL; tr = tr->next) {
00796         if (!tr->item)
00797             continue;
00798         item = &tr->item->clone;
00799         if (item->type == BOOK && item->invisible && item->name == type)
00800             count++;
00801     }
00802     if (count == 0) {
00803         return NULL;
00804     }
00805 
00806     count = rndm(1, count);
00807 
00808     for (tr = god->randomitems->items; tr != NULL; tr = tr->next) {
00809         if (!tr->item)
00810             continue;
00811         item = &tr->item->clone;
00812         if (item->type == BOOK && item->invisible && item->name == type) {
00813             count--;
00814             if (count == 0)
00815                 return item->other_arch;
00816         }
00817     }
00818 
00819     return NULL;
00820 }
00821 
00832 static int god_removes_curse(object *op, int remove_damnation) {
00833     object *tmp;
00834     int success = 0;
00835 
00836     for (tmp = op->inv; tmp; tmp = tmp->below) {
00837         if (tmp->invisible)
00838             continue;
00839         if (QUERY_FLAG(tmp, FLAG_DAMNED) && !remove_damnation)
00840             continue;
00841         if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
00842             success = 1;
00843             CLEAR_FLAG(tmp, FLAG_DAMNED);
00844             CLEAR_FLAG(tmp, FLAG_CURSED);
00845             CLEAR_FLAG(tmp, FLAG_KNOWN_CURSED);
00846             if (op->type == PLAYER)
00847                 esrv_update_item(UPD_FLAGS, op, tmp);
00848         }
00849     }
00850 
00851     if (success)
00852         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
00853                       "You feel like someone is helping you.", NULL);
00854     return success;
00855 }
00856 
00866 static int follower_level_to_enchantments(int level, int difficulty) {
00867     if (difficulty < 1) {
00868         LOG(llevError, "follower_level_to_enchantments(): difficulty %d is invalid\n", difficulty);
00869         return 0;
00870     }
00871 
00872     if (level <= 20)
00873         return level/difficulty;
00874     if (level <= 40)
00875         return (20+(level-20)/2)/difficulty;
00876     return (30+(level-40)/4)/difficulty;
00877 }
00878 
00897 static int improve_weapon_magic(object *op, object *tr, object *weapon, object *skill) {
00898     int tmp = follower_level_to_enchantments(skill->level, tr->level);
00899 
00900     if (weapon->magic < tmp) {
00901         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
00902                       "A phosphorescent glow envelops your weapon!", NULL);
00903         weapon->magic++;
00904         if (op->type == PLAYER)
00905             esrv_update_item(UPD_NAME, op, weapon);
00906         weapon->item_power++;
00907         return 1;
00908     }
00909 
00910     return 0;
00911 }
00912 
00930 static int god_enchants_weapon(object *op, const object *god, object *tr, object *skill) {
00931     char buf[MAX_BUF];
00932     object *weapon;
00933     uint32 attacktype;
00934 
00935     for (weapon = op->inv; weapon; weapon = weapon->below)
00936         if ((weapon->type == WEAPON || weapon->type == BOW)
00937         && QUERY_FLAG(weapon, FLAG_APPLIED))
00938             break;
00939     if (weapon == NULL || god_examines_item(god, weapon) <= 0)
00940         return 0;
00941 
00942     if (weapon->item_power >= MAX_WEAPON_ITEM_POWER) {
00943         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_INFO,
00944                              "%s considers your %s is not worthy to be enchanted any more.",
00945                              "%s considers your %s is not worthy to be enchanted any more.",
00946                              god->name,
00947                              weapon->name);
00948         return 0;
00949     }
00950 
00951     /* If personalized_blessings is activated, then the god's name is
00952      * associated with the weapon, as well as the owner (the one who blesses it),
00953      * and a "weapon willpower", which is equivalent to the owner's experience
00954      * in praying when the weapon is blessed.
00955      * Those values are used later, when another player attempts to wield the
00956      * weapon - nasty things may happen to those who do not deserve to use it ! :)
00957      */
00958     if (settings.personalized_blessings) {
00959         const char *divine_owner = get_ob_key_value(weapon, "divine_blessing_name");
00960         const char *owner = get_ob_key_value(weapon, "item_owner");
00961         object *skillop = NULL;
00962 
00963         if (divine_owner != NULL) {
00964             if (!strcmp(divine_owner, god->name)) {
00965                 /* It already belongs to this god - do not go further. */
00966                 /*
00967                 [DT] (2009-06-10): It is ok if the weapon has already been enchanted
00968                 one time, but in that particular case we only give out additional plusses.
00969                 No new slays or new attacktypes
00970                 */
00971                 return improve_weapon_magic(op, tr, weapon, skill);
00972             }
00973 
00974             /* Huho... Another god already blessed this one ! */
00975             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_INFO,
00976                                  "Your %s already belongs to %s !",
00977                                  "Your %s already belongs to %s !",
00978                                  weapon->name, divine_owner);
00979             return 0;
00980         } else if ((owner != NULL) && (!strcmp(owner, op->name))) {
00981             /* Maybe the weapon itself will not agree ? */
00982             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_INFO,
00983                                  "The %s is not yours, and is magically protected against such changes !",
00984                                  "The %s is not yours, and is magically protected against such changes !",
00985                                  weapon->name);
00986             return 0;
00987         }
00988         skillop = find_skill_by_number(op, SK_PRAYING);
00989         if (skillop == NULL) {
00990             LOG(llevError, "god_enchants_weapon: no praying skill object found ?!\n");
00991             snprintf(buf, sizeof(buf), "%d", 1);
00992         } else
00993             snprintf(buf, sizeof(buf), "%"FMT64, skillop->stats.exp);
00994         set_ob_key_value(weapon, "divine_blessing_name", god->name, TRUE);
00995         set_ob_key_value(weapon, "item_owner", op->name, TRUE);
00996         set_ob_key_value(weapon, "item_willpower", buf, TRUE);
00997     }
00998 
00999     /* First give it a title, so other gods won't touch it */
01000     if (!weapon->title) {
01001         snprintf(buf, sizeof(buf), "of %s", god->name);
01002         weapon->title = add_string(buf);
01003         if (op->type == PLAYER)
01004             esrv_update_item(UPD_NAME, op, weapon);
01005         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
01006                       "Your weapon quivers as if struck!", NULL);
01007     }
01008 
01009     /* Allow the weapon to slay enemies */
01010     if (!weapon->slaying && god->slaying) {
01011         weapon->slaying = add_string(god->slaying);
01012         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
01013                              "Your %s now hungers to slay enemies of your god!",
01014                              "Your %s now hungers to slay enemies of your god!",
01015                              weapon->name);
01016         weapon->item_power++;
01017         return 1;
01018     }
01019 
01020     /* Add the gods attacktype */
01021     attacktype = (weapon->attacktype == 0) ? AT_PHYSICAL : weapon->attacktype;
01022     if ((attacktype&god->attacktype) != god->attacktype) {
01023         draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
01024                       "Your weapon suddenly glows!", NULL);
01025         weapon->attacktype = attacktype|god->attacktype;
01026         weapon->item_power++;
01027         return 1;
01028     }
01029 
01030     /* Higher magic value */
01031     return improve_weapon_magic(op, tr, weapon, skill);
01032 }
01033 
01047 static void god_intervention(object *op, const object *god, object *skill) {
01048     treasure *tr;
01049 
01050     if (!god || !god->randomitems) {
01051         LOG(llevError, "BUG: god_intervention(): no god or god without randomitems\n");
01052         return;
01053     }
01054 
01055     check_special_prayers(op, god);
01056 
01057     /* lets do some checks of whether we are kosher with our god */
01058     if (god_examines_priest(op, god) < 0)
01059         return;
01060 
01061     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01062                   "You feel a holy presence!", NULL);
01063 
01064     for (tr = god->randomitems->items; tr != NULL; tr = tr->next) {
01065         object *item;
01066 
01067         if (tr->chance <= random_roll(0, 99, op, PREFER_HIGH))
01068             continue;
01069 
01070         /* Treasurelist - generate some treasure for the follower */
01071         if (tr->name) {
01072             treasurelist *tl = find_treasurelist(tr->name);
01073             if (tl == NULL)
01074                 continue;
01075 
01076             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_ADD,
01077                           "Something appears before your eyes.  You catch it before it falls to the ground.",
01078                           NULL);
01079 
01080             create_treasure(tl, op, GT_STARTEQUIP|GT_ONLY_GOOD|GT_UPDATE_INV, skill->level, 0);
01081             return;
01082         }
01083 
01084         if (!tr->item) {
01085             LOG(llevError, "BUG: empty entry in %s's treasure list\n", god->name);
01086             continue;
01087         }
01088         item = &tr->item->clone;
01089 
01090         /* Grace limit */
01091         if (item->type == BOOK && item->invisible
01092         && strcmp(item->name, "grace limit") == 0) {
01093             if (op->stats.grace < item->stats.grace
01094             || op->stats.grace < op->stats.maxgrace) {
01095                 object *tmp;
01096 
01097                 /* Follower lacks the required grace for the following
01098                  * treasure list items. */
01099 
01100                 tmp = create_archetype(HOLY_POSSESSION);
01101                 cast_change_ability(op, op, tmp, 0, 1);
01102                 free_object(tmp);
01103                 return;
01104             }
01105             continue;
01106         }
01107 
01108         /* Restore grace */
01109         if (item->type == BOOK && item->invisible
01110         && strcmp(item->name, "restore grace") == 0) {
01111             if (op->stats.grace >= 0)
01112                 continue;
01113             op->stats.grace = random_roll(0, 9, op, PREFER_HIGH);
01114             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01115                           "You are returned to a state of grace.", NULL);
01116             return;
01117         }
01118 
01119         /* Heal damage */
01120         if (item->type == BOOK && item->invisible
01121             && strcmp(item->name, "restore hitpoints") == 0) {
01122             if (op->stats.hp >= op->stats.maxhp)
01123                 continue;
01124             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01125                           "A white light surrounds and heals you!", NULL);
01126             op->stats.hp = op->stats.maxhp;
01127             return;
01128         }
01129 
01130         /* Restore spellpoints */
01131         if (item->type == BOOK
01132         && item->invisible
01133         && strcmp(item->name, "restore spellpoints") == 0) {
01134             int max = op->stats.maxsp*(item->stats.maxsp/100.0);
01135             /* Restore to 50 .. 100%, if sp < 50% */
01136             int new_sp = random_roll(1000, 1999, op, PREFER_HIGH)/2000.0*max;
01137             if (op->stats.sp >= max/2)
01138                 continue;
01139             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01140                           "A blue lightning strikes your head but doesn't hurt you!", NULL);
01141             op->stats.sp = new_sp;
01142         }
01143 
01144         /* Various heal spells */
01145         if (item->type == BOOK && item->invisible
01146             && strcmp(item->name, "heal spell") == 0) {
01147             object *tmp;
01148             int success;
01149 
01150             tmp = create_archetype_by_object_name(item->slaying);
01151 
01152             success = cast_heal(op, op, tmp, 0);
01153             free_object(tmp);
01154             if (success)
01155                 return;
01156             else
01157                 continue;
01158         }
01159 
01160         /* Remove curse */
01161         if (item->type == BOOK && item->invisible
01162             && strcmp(item->name, "remove curse") == 0) {
01163             if (god_removes_curse(op, 0))
01164                 return;
01165             else
01166                 continue;
01167         }
01168 
01169         /* Remove damnation */
01170         if (item->type == BOOK && item->invisible
01171             && strcmp(item->name, "remove damnation") == 0) {
01172             if (god_removes_curse(op, 1))
01173                 return;
01174             else
01175                 continue;
01176         }
01177 
01178         /* Heal depletion */
01179         if (item->type == BOOK && item->invisible
01180             && strcmp(item->name, "heal depletion") == 0) {
01181             object *depl;
01182             archetype *at;
01183             int i;
01184 
01185             if ((at = find_archetype(ARCH_DEPLETION)) == NULL) {
01186                 LOG(llevError, "Could not find archetype depletion.\n");
01187                 continue;
01188             }
01189             depl = present_arch_in_ob(at, op);
01190             if (depl == NULL)
01191                 continue;
01192             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01193                           "Shimmering light surrounds and restores you!", NULL);
01194             for (i = 0; i < NUM_STATS; i++)
01195                 if (get_attr_value(&depl->stats, i))
01196                     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE,
01197                                   MSG_TYPE_ATTRIBUTE_BAD_EFFECT_END,
01198                                   restore_msg[i], restore_msg[i]);
01199             remove_ob(depl);
01200             free_object(depl);
01201             fix_object(op);
01202             return;
01203         }
01204 
01205         /* Voices */
01206         if (item->type == BOOK && item->invisible
01207             && strcmp(item->name, "voice_behind") == 0) {
01208             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01209                           "You hear a voice from behind you, but you don't dare to "
01210                           "turn around:", NULL);
01211             draw_ext_info(NDI_WHITE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01212                           item->msg, item->msg);
01213             return;
01214         }
01215 
01216         /* Messages */
01217         if (item->type == BOOK && item->invisible
01218             && strcmp(item->name, "message") == 0) {
01219             draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01220                           item->msg, item->msg);
01221             return;
01222         }
01223 
01224         /* Enchant weapon */
01225         if (item->type == BOOK && item->invisible
01226             && strcmp(item->name, "enchant weapon") == 0) {
01227             if (god_enchants_weapon(op, god, item, skill))
01228                 return;
01229             else
01230                 continue;
01231         }
01232 
01233         /* Spellbooks - works correctly only for prayers */
01234         if (item->type == SPELL) {
01235             if (check_spell_known(op, item->name))
01236                 continue;
01237             if (item->level > skill->level)
01238                 continue;
01239 
01240             draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01241                                  "%s grants you use of a special prayer!",
01242                                  "%s grants you use of a special prayer!",
01243                                  god->name);
01244             do_learn_spell(op, item, 1);
01245             return;
01246 
01247         }
01248 
01249         /* Other gifts */
01250         if (!item->invisible) {
01251             if (god_gives_present(op, god, tr))
01252                 return;
01253             else
01254                 continue;
01255         }
01256         /* else ignore it */
01257     }
01258 
01259     draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01260                   "You feel rapture.", NULL);
01261 }
01262 
01275 static int god_examines_priest(object *op, const object *god) {
01276     int reaction = 1;
01277     object *item = NULL, *skop;
01278 
01279     for (item = op->inv; item; item = item->below) {
01280         if (QUERY_FLAG(item, FLAG_APPLIED)) {
01281             reaction += god_examines_item(god, item)*(item->magic ? abs(item->magic) : 1);
01282         }
01283     }
01284 
01285     /* well, well. Looks like we screwed up. Time for god's revenge */
01286     if (reaction < 0) {
01287         int loss = 10000000;
01288         int angry = abs(reaction);
01289 
01290         for (skop = op->inv; skop != NULL; skop = skop->below)
01291             if (skop->type == SKILL && skop->subtype == SK_PRAYING)
01292                 break;
01293 
01294         if (skop)
01295             loss = 0.05*(float)skop->stats.exp;
01296         change_exp(op, -random_roll(0, loss*angry-1, op, PREFER_LOW), skop ? skop->skill : "none", SK_SUBTRACT_SKILL_EXP);
01297         if (random_roll(0, angry, op, PREFER_LOW)) {
01298             object *tmp = create_archetype(LOOSE_MANA);
01299 
01300             cast_magic_storm(op, tmp, op->level+(angry*3));
01301         }
01302         draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
01303                              "%s becomes angry and punishes you!",
01304                              "%s becomes angry and punishes you!",
01305                              god->name);
01306     }
01307     return reaction;
01308 }
01309 
01326 static int god_examines_item(const object *god, object *item) {
01327     char buf[MAX_BUF];
01328 
01329     if (!god || !item)
01330         return 0;
01331 
01332     if (!item->title)
01333         return 1; /* unclaimed item are ok */
01334 
01335     snprintf(buf, sizeof(buf), "of %s", god->name);
01336     if (!strcmp(item->title, buf))
01337         return 1; /* belongs to that God */
01338 
01339     if (god->title) { /* check if we have any enemy blessed item*/
01340         snprintf(buf, sizeof(buf), "of %s", god->title);
01341         if (!strcmp(item->title, buf)) {
01342             if (item->env) {
01343                 char name[MAX_BUF];
01344 
01345                 query_name(item, name, MAX_BUF);
01346                 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, item->env, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
01347                                      "Heretic! You are using %s!",
01348                                      "Heretic! You are using %s!",
01349                                      name);
01350             }
01351             return -1;
01352         }
01353     }
01354     return 0; /* item is sacred to a non-enemy god/or is otherwise magical */
01355 }
01356 
01367 static const char *get_god_for_race(const char *race) {
01368     godlink *gl = first_god;
01369     const char *godname = NULL;
01370 
01371     if (race == NULL)
01372         return NULL;
01373     while (gl) {
01374         if (gl->arch->clone.race && !strcasecmp(gl->arch->clone.race, race)) {
01375             godname = gl->name;
01376             break;
01377         }
01378         gl = gl->next;
01379     }
01380     return godname;
01381 }
01382 
01394 int tailor_god_spell(object *spellop, object *caster) {
01395     const object *god = find_god(determine_god(caster));
01396     int caster_is_spell = 0;
01397 
01398     if (caster->type == SPELL_EFFECT || caster->type == SPELL)
01399         caster_is_spell = 1;
01400 
01401     /* if caster is a rune or the like, it doesn't worship anything.  However,
01402      * if this object is owned by someone, then the god that they worship
01403      * is relevant, so use that.
01404      */
01405     if (!god && get_owner(caster))
01406         god = find_god(determine_god(get_owner(caster)));
01407 
01408     if (!god || (spellop->attacktype&AT_HOLYWORD && !god->race)) {
01409         if (!caster_is_spell)
01410             draw_ext_info(NDI_UNIQUE, 0, caster, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
01411                           "This prayer is useless unless you worship an appropriate god", NULL);
01412         else
01413             LOG(llevError, "BUG: tailor_god_spell(): no god\n");
01414         free_object(spellop);
01415         return 0;
01416     }
01417 
01418     /* either holy word or godpower attacks will set the slaying field */
01419     if (spellop->attacktype&AT_HOLYWORD || spellop->attacktype&AT_GODPOWER) {
01420         if (spellop->slaying) {
01421             free_string(spellop->slaying);
01422             spellop->slaying = NULL;
01423         }
01424         if (!caster_is_spell)
01425             spellop->slaying = god->slaying ? add_string(god->slaying) : NULL;
01426         else if (caster->slaying)
01427             spellop->slaying = add_string(caster->slaying);
01428     }
01429 
01430     /* only the godpower attacktype adds the god's attack onto the spell */
01431     if (spellop->attacktype&AT_GODPOWER)
01432         spellop->attacktype = spellop->attacktype|god->attacktype;
01433 
01434     /* tack on the god's name to the spell */
01435     if (spellop->attacktype&AT_HOLYWORD || spellop->attacktype&AT_GODPOWER) {
01436         if (spellop->title)
01437             free_string(spellop->title);
01438         spellop->title = add_string(god->name);
01439         if (spellop->title) {
01440             char buf[MAX_BUF];
01441 
01442             snprintf(buf, sizeof(buf), "%s of %s", spellop->name, spellop->title);
01443             FREE_AND_COPY(spellop->name, buf);
01444             FREE_AND_COPY(spellop->name_pl, buf);
01445         }
01446     }
01447 
01448     return 1;
01449 }