00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
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
00157
00158
00159
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
00216 for (tmp = op->inv; tmp != NULL; tmp = next) {
00217 next = tmp->below;
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
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);
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 query_short_name(tmp, name, HUGE_BUF);
00289 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_ADD,
00290 "%s lets %s appear in your hands.",
00291 NULL,
00292 god->name, name);
00296 set_ob_key_value(tmp, "divine_giver_name", god->name, TRUE);
00297 insert_ob_in_ob(tmp, op);
00298 return 1;
00299 }
00300
00312 void pray_at_altar(object *pl, object *altar, object *skill) {
00313 const object *pl_god = find_god(determine_god(pl));
00314
00315
00316 if (execute_event(altar, EVENT_APPLY, pl, NULL, NULL, SCRIPT_FIX_ALL) != 0)
00317 return;
00318
00319
00320 if (!altar->other_arch)
00321 return;
00322
00323
00324 if (!pl_god) {
00325 become_follower(pl, &altar->other_arch->clone);
00326 return;
00327
00328 } else if (!strcmp(pl_god->name, altar->other_arch->clone.name)) {
00329
00330 int bonus = (pl->stats.Wis+skill->level)/10;
00331
00332
00333 if (pl->stats.grace < 0)
00334 pl->stats.grace += (bonus > -1*(pl->stats.grace/10) ? bonus : -1*(pl->stats.grace/10));
00335
00336 if (pl->stats.grace < (2*pl->stats.maxgrace)) {
00337 pl->stats.grace += bonus/2;
00338 }
00339 if (pl->stats.grace > (2*pl->stats.maxgrace)) {
00340 pl->stats.grace = (2*pl->stats.maxgrace);
00341 }
00342
00343
00344
00345
00346 bonus = MAX(1, bonus+MAX(pl->stats.luck, -3));
00347
00348 if (((random_roll(0, 399, pl, PREFER_LOW))-bonus) < 0)
00349 god_intervention(pl, pl_god, skill);
00350
00351 } else {
00352 uint64 loss = 0;
00353 int angry = 1;
00354
00355
00356
00357
00358
00359
00360
00361
00362 if (pl_god->other_arch
00363 && (altar->other_arch->name == pl_god->other_arch->name)) {
00364 angry = 2;
00365 if (random_roll(0, skill->level+2, pl, PREFER_LOW)-5 > 0) {
00366 object *tmp;
00367
00368
00369 angry = 3;
00370 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00371 "Foul Priest! %s punishes you!",
00372 "Foul Priest! %s punishes you!",
00373 pl_god->name);
00374 tmp = create_archetype(LOOSE_MANA);
00375 cast_magic_storm(pl, tmp, pl_god->level+20);
00376 } else
00377 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00378 "Foolish heretic! %s is livid!",
00379 "Foolish heretic! %s is livid!",
00380 pl_god->name);
00381 } else
00382 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00383 "Heretic! %s is angered!",
00384 "Heretic! %s is angered!",
00385 pl_god->name);
00386
00387
00388
00389
00390
00391 loss = angry*(skill->stats.exp/10);
00392 if (loss)
00393 change_exp(pl, -random_roll64(0, loss, pl, PREFER_LOW), skill ? skill->skill : "none", SK_SUBTRACT_SKILL_EXP);
00394
00395
00396
00397
00398 if ((angry == 1) && !(random_roll(0, skill->level, pl, PREFER_LOW))) {
00399 become_follower(pl, &altar->other_arch->clone);
00400 } else {
00401
00402 draw_ext_info(NDI_UNIQUE|NDI_NAVY, 0, pl, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00403 "A divine force pushes you off the altar.", NULL);
00404
00405 move_player(pl, absdir(pl->facing+4));
00406 }
00407 }
00408 }
00409
00418 static void check_special_prayers(object *op, const object *god) {
00419
00420
00421
00422 treasure *tr;
00423 object *tmp, *next_tmp;
00424 int remove = 0;
00425
00426
00427 for (tmp = op->inv; tmp; tmp = next_tmp) {
00428 next_tmp = tmp->below;
00429
00430
00431
00432
00433 if (tmp->type != SPELL || !QUERY_FLAG(tmp, FLAG_STARTEQUIP))
00434 continue;
00435
00436 if (god->randomitems == NULL) {
00437 LOG(llevError, "BUG: check_special_prayers(): god %s without randomitems\n", god->name);
00438 do_forget_spell(op, tmp->name);
00439 continue;
00440 }
00441
00442
00443
00444
00445 remove = 1;
00446 for (tr = god->randomitems->items; tr; tr = tr->next) {
00447 object *item;
00448
00449 if (tr->item == NULL)
00450 continue;
00451 item = &tr->item->clone;
00452
00453
00454
00455 if (tr->item->clone.type == SPELL && tr->item->clone.name == tmp->name) {
00456 remove = 0;
00457 break;
00458 }
00459 }
00460 if (remove) {
00461
00462
00463
00464 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op,
00465 MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00466 "You lose knowledge of %s.",
00467 "You lose knowledge of %s.",
00468 tmp->name);
00469 player_unready_range_ob(op->contr, tmp);
00470 remove_ob(tmp);
00471 free_object(tmp);
00472 }
00473
00474 }
00475 }
00476
00489 void become_follower(object *op, const object *new_god) {
00490 const object *old_god = NULL;
00491 treasure *tr;
00492 object *item, *skop, *next;
00493 int i, sk_applied;
00494 int undeadified = 0;
00495
00496 old_god = find_god(determine_god(op));
00497
00498
00499 for (item = op->inv; item != NULL; item = next) {
00500 next = item->below;
00501
00502
00503
00504 if (QUERY_FLAG(item, FLAG_STARTEQUIP)
00505 && item->invisible
00506 && (item->type != SKILL)
00507 && (item->type != EXPERIENCE)
00508 && (item->type != FORCE)) {
00509 if (item->type == SPELL)
00510 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00511 "You lose knowledge of %s.",
00512 "You lose knowledge of %s.",
00513 item->name);
00514 player_unready_range_ob(op->contr, item);
00515 remove_ob(item);
00516 free_object(item);
00517 }
00518 }
00519
00520
00521 if (old_god) {
00522
00523
00524
00525
00526
00527 follower_remove_given_items(op, op, old_god);
00528 }
00529
00530 if (!op || !new_god)
00531 return;
00532
00533 if (op->race && new_god->slaying && strstr(op->race, new_god->slaying)) {
00534 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00535 "Fool! %s detests your kind!",
00536 "Fool! %s detests your kind!",
00537 new_god->name);
00538 if (random_roll(0, op->level-1, op, PREFER_LOW)-5 > 0) {
00539 object *tmp = create_archetype(LOOSE_MANA);
00540 cast_magic_storm(op, tmp, new_god->level+10);
00541 }
00542 return;
00543 }
00544
00545
00546 for (tr = new_god->randomitems->items; tr != NULL; tr = tr->next) {
00547 if (tr->item
00548 && tr->item->clone.invisible
00549 && tr->item->clone.type != SPELLBOOK
00550 && tr->item->clone.type != BOOK
00551 && tr->item->clone.type != SPELL)
00552 god_gives_present(op, new_god, tr);
00553 }
00554
00555 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00556 "You become a follower of %s!",
00557 "You become a follower of %s!",
00558 new_god->name);
00559
00560 for (skop = op->inv; skop != NULL; skop = skop->below)
00561 if (skop->type == SKILL && skop->subtype == SK_PRAYING)
00562 break;
00563
00564
00565 if (!skop) {
00566
00567
00568
00569 skop = give_skill_by_name(op, get_archetype_by_type_subtype(SKILL, SK_PRAYING)->clone.skill);
00570 link_player_skills(op);
00571 }
00572
00573 sk_applied = QUERY_FLAG(skop, FLAG_APPLIED);
00574
00575
00576
00577
00578
00579 if ((old_god) && (QUERY_FLAG(old_god, FLAG_UNDEAD))) {
00580 CLEAR_FLAG(skop, FLAG_UNDEAD);
00581 undeadified = 1;
00582 }
00583
00584 if (skop->title) {
00585 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00586 "%s's blessing is withdrawn from you.",
00587 "%s's blessing is withdrawn from you.",
00588 skop->title);
00589
00590
00591 if (sk_applied || undeadified) {
00592 CLEAR_FLAG(skop, FLAG_APPLIED);
00593 (void)change_abil(op, skop);
00594 }
00595 free_string(skop->title);
00596 }
00597
00598
00599 skop->title = add_string(new_god->name);
00600 skop->path_attuned = new_god->path_attuned;
00601 skop->path_repelled = new_god->path_repelled;
00602 skop->path_denied = new_god->path_denied;
00603
00604 memcpy(skop->resist, new_god->resist, sizeof(new_god->resist));
00605
00606
00607
00608
00609 for (i = 0; i < NROFATTACKS; i++)
00610 if (skop->resist[i] > 30
00611 && (i == ATNR_FIRE || i == ATNR_COLD || i == ATNR_ELECTRICITY || i == ATNR_POISON))
00612 skop->resist[i] = 30;
00613
00614 skop->stats.hp = (sint16)new_god->last_heal;
00615 skop->stats.sp = (sint16)new_god->last_sp;
00616 skop->stats.grace = (sint16)new_god->last_grace;
00617 skop->stats.food = (sint16)new_god->last_eat;
00618 skop->stats.luck = (sint8)new_god->stats.luck;
00619
00620 update_priest_flag(new_god, skop, FLAG_SEE_IN_DARK);
00621 update_priest_flag(new_god, skop, FLAG_REFL_SPELL);
00622 update_priest_flag(new_god, skop, FLAG_REFL_MISSILE);
00623 update_priest_flag(new_god, skop, FLAG_STEALTH);
00624 update_priest_flag(new_god, skop, FLAG_MAKE_INVIS);
00625 update_priest_flag(new_god, skop, FLAG_UNDEAD);
00626 update_priest_flag(new_god, skop, FLAG_BLIND);
00627 update_priest_flag(new_god, skop, FLAG_XRAYS);
00628 update_priest_flag(new_god, skop, FLAG_USE_WEAPON);
00629 update_priest_flag(new_god, skop, FLAG_USE_ARMOUR);
00630 update_priest_flag(new_god, skop, FLAG_USE_SHIELD);
00631
00632 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00633 "You are bathed in %s's aura.",
00634 "You are bathed in %s's aura.",
00635 new_god->name);
00636
00637
00638
00639
00640
00641
00642
00643
00644 if (!present_in_ob_by_name(FORCE, "no weapon force", op)) {
00645 if (worship_forbids_use(op, skop, FLAG_USE_WEAPON, "weapons"))
00646 stop_using_item(op, WEAPON, 2);
00647 }
00648 update_priest_flag(new_god, skop, FLAG_USE_ARMOUR);
00649
00650 if (worship_forbids_use(op, skop, FLAG_USE_ARMOUR, "armour")) {
00651 stop_using_item(op, ARMOUR, 1);
00652 stop_using_item(op, HELMET, 1);
00653 stop_using_item(op, BOOTS, 1);
00654 stop_using_item(op, GLOVES, 1);
00655 }
00656
00657 if (worship_forbids_use(op, skop, FLAG_USE_SHIELD, "shield"))
00658 stop_using_item(op, SHIELD, 1);
00659
00660 SET_FLAG(skop, FLAG_APPLIED);
00661 (void)change_abil(op, skop);
00662
00663
00664 if (!sk_applied)
00665 CLEAR_FLAG(skop, FLAG_APPLIED);
00666
00667 check_special_prayers(op, new_god);
00668 }
00669
00683 static int worship_forbids_use(object *op, object *exp_obj, uint32 flag, const char *string) {
00684 if (QUERY_FLAG(&op->arch->clone, flag)) {
00685 if (QUERY_FLAG(op, flag) != QUERY_FLAG(exp_obj, flag)) {
00686 update_priest_flag(exp_obj, op, flag);
00687 if (QUERY_FLAG(op, flag))
00688 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00689 "You may use %s again.",
00690 "You may use %s again.",
00691 string);
00692 else {
00693 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
00694 "You are forbidden to use %s.",
00695 "You are forbidden to use %s.",
00696 string);
00697 return 1;
00698 }
00699 }
00700 }
00701 return 0;
00702 }
00703
00715 static void stop_using_item(object *op, int type, int number) {
00716 object *tmp;
00717
00718 for (tmp = op->inv; tmp && number; tmp = tmp->below)
00719 if (tmp->type == type && QUERY_FLAG(tmp, FLAG_APPLIED)) {
00720 apply_special(op, tmp, AP_UNAPPLY|AP_IGNORE_CURSE);
00721 number--;
00722 }
00723 }
00724
00737 static void update_priest_flag(const object *god, object *exp_ob, uint32 flag) {
00738 if (QUERY_FLAG(god, flag) && !QUERY_FLAG(exp_ob, flag))
00739 SET_FLAG(exp_ob, flag);
00740 else if (QUERY_FLAG(exp_ob, flag) && !QUERY_FLAG(god, flag)) {
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751 CLEAR_FLAG(exp_ob, flag);
00752 }
00753 }
00754
00755
00769 archetype *determine_holy_arch(const object *god, const char *type) {
00770 treasure *tr;
00771 int count;
00772 archetype *last;
00773 object *item;
00774
00775 if (!god || !god->randomitems) {
00776 LOG(llevError, "BUG: determine_holy_arch(): no god or god without randomitems\n");
00777 return NULL;
00778 }
00779
00780 count = 0;
00781 last = NULL;
00782 for (tr = god->randomitems->items; tr != NULL; tr = tr->next) {
00783 if (!tr->item)
00784 continue;
00785 item = &tr->item->clone;
00786 if (item->type == BOOK && item->invisible && item->name == type)
00787 count++;
00788 }
00789 if (count == 0) {
00790 return NULL;
00791 }
00792
00793 count = rndm(1, count);
00794
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 if (count == 0)
00802 return item->other_arch;
00803 }
00804 }
00805
00806 return NULL;
00807 }
00808
00819 static int god_removes_curse(object *op, int remove_damnation) {
00820 object *tmp;
00821 int success = 0;
00822
00823 for (tmp = op->inv; tmp; tmp = tmp->below) {
00824 if (tmp->invisible)
00825 continue;
00826 if (QUERY_FLAG(tmp, FLAG_DAMNED) && !remove_damnation)
00827 continue;
00828 if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
00829 success = 1;
00830 CLEAR_FLAG(tmp, FLAG_DAMNED);
00831 CLEAR_FLAG(tmp, FLAG_CURSED);
00832 CLEAR_FLAG(tmp, FLAG_KNOWN_CURSED);
00833 if (op->type == PLAYER)
00834 esrv_update_item(UPD_FLAGS, op, tmp);
00835 }
00836 }
00837
00838 if (success)
00839 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
00840 "You feel like someone is helping you.", NULL);
00841 return success;
00842 }
00843
00853 static int follower_level_to_enchantments(int level, int difficulty) {
00854 if (difficulty < 1) {
00855 LOG(llevError, "follower_level_to_enchantments(): difficulty %d is invalid\n", difficulty);
00856 return 0;
00857 }
00858
00859 if (level <= 20)
00860 return level/difficulty;
00861 if (level <= 40)
00862 return (20+(level-20)/2)/difficulty;
00863 return (30+(level-40)/4)/difficulty;
00864 }
00865
00884 static int improve_weapon_magic(object *op, object *tr, object *weapon, object *skill) {
00885 int tmp = follower_level_to_enchantments(skill->level, tr->level);
00886
00887 if (weapon->magic < tmp) {
00888 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
00889 "A phosphorescent glow envelops your weapon!", NULL);
00890 weapon->magic++;
00891 if (op->type == PLAYER)
00892 esrv_update_item(UPD_NAME, op, weapon);
00893 weapon->item_power++;
00894 return 1;
00895 }
00896
00897 return 0;
00898 }
00899
00917 static int god_enchants_weapon(object *op, const object *god, object *tr, object *skill) {
00918 char buf[MAX_BUF];
00919 object *weapon;
00920 uint32 attacktype;
00921
00922 for (weapon = op->inv; weapon; weapon = weapon->below)
00923 if ((weapon->type == WEAPON || weapon->type == BOW)
00924 && QUERY_FLAG(weapon, FLAG_APPLIED))
00925 break;
00926 if (weapon == NULL || god_examines_item(god, weapon) <= 0)
00927 return 0;
00928
00929 if (weapon->item_power >= MAX_WEAPON_ITEM_POWER) {
00930 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_INFO,
00931 "%s considers your %s is not worthy to be enchanted any more.",
00932 "%s considers your %s is not worthy to be enchanted any more.",
00933 god->name,
00934 weapon->name);
00935 return 0;
00936 }
00937
00938
00939
00940
00941
00942
00943
00944
00945 if (settings.personalized_blessings) {
00946 const char *divine_owner = get_ob_key_value(weapon, "divine_blessing_name");
00947 const char *owner = get_ob_key_value(weapon, "item_owner");
00948 object *skillop = NULL;
00949
00950 if (divine_owner != NULL) {
00951 if (!strcmp(divine_owner, god->name)) {
00952
00953
00954
00955
00956
00957
00958 return improve_weapon_magic(op, tr, weapon, skill);
00959 }
00960
00961
00962 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_INFO,
00963 "Your %s already belongs to %s !",
00964 "Your %s already belongs to %s !",
00965 weapon->name, divine_owner);
00966 return 0;
00967 } else if ((owner != NULL) && (!strcmp(owner, op->name))) {
00968
00969 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_INFO,
00970 "The %s is not yours, and is magically protected against such changes !",
00971 "The %s is not yours, and is magically protected against such changes !",
00972 weapon->name);
00973 return 0;
00974 }
00975 skillop = find_skill_by_number(op, SK_PRAYING);
00976 if (skillop == NULL) {
00977 LOG(llevError, "god_enchants_weapon: no praying skill object found ?!\n");
00978 snprintf(buf, sizeof(buf), "%d", 1);
00979 } else
00980 snprintf(buf, sizeof(buf), "%"FMT64, skillop->stats.exp);
00981 set_ob_key_value(weapon, "divine_blessing_name", god->name, TRUE);
00982 set_ob_key_value(weapon, "item_owner", op->name, TRUE);
00983 set_ob_key_value(weapon, "item_willpower", buf, TRUE);
00984 }
00985
00986
00987 if (!weapon->title) {
00988 snprintf(buf, sizeof(buf), "of %s", god->name);
00989 weapon->title = add_string(buf);
00990 if (op->type == PLAYER)
00991 esrv_update_item(UPD_NAME, op, weapon);
00992 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
00993 "Your weapon quivers as if struck!", NULL);
00994 }
00995
00996
00997 if (!weapon->slaying && god->slaying) {
00998 weapon->slaying = add_string(god->slaying);
00999 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
01000 "Your %s now hungers to slay enemies of your god!",
01001 "Your %s now hungers to slay enemies of your god!",
01002 weapon->name);
01003 weapon->item_power++;
01004 return 1;
01005 }
01006
01007
01008 attacktype = (weapon->attacktype == 0) ? AT_PHYSICAL : weapon->attacktype;
01009 if ((attacktype&god->attacktype) != god->attacktype) {
01010 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_CHANGE,
01011 "Your weapon suddenly glows!", NULL);
01012 weapon->attacktype = attacktype|god->attacktype;
01013 weapon->item_power++;
01014 return 1;
01015 }
01016
01017
01018 return improve_weapon_magic(op, tr, weapon, skill);
01019 }
01020
01034 static void god_intervention(object *op, const object *god, object *skill) {
01035 treasure *tr;
01036
01037 if (!god || !god->randomitems) {
01038 LOG(llevError, "BUG: god_intervention(): no god or god without randomitems\n");
01039 return;
01040 }
01041
01042 check_special_prayers(op, god);
01043
01044
01045 if (god_examines_priest(op, god) < 0)
01046 return;
01047
01048 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01049 "You feel a holy presence!", NULL);
01050
01051 for (tr = god->randomitems->items; tr != NULL; tr = tr->next) {
01052 object *item;
01053
01054 if (tr->chance <= random_roll(0, 99, op, PREFER_HIGH))
01055 continue;
01056
01057
01058 if (tr->name) {
01059 treasurelist *tl = find_treasurelist(tr->name);
01060 if (tl == NULL)
01061 continue;
01062
01063 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ITEM, MSG_TYPE_ITEM_ADD,
01064 "Something appears before your eyes. You catch it before it falls to the ground.",
01065 NULL);
01066
01067 create_treasure(tl, op, GT_STARTEQUIP|GT_ONLY_GOOD|GT_UPDATE_INV, skill->level, 0);
01068 return;
01069 }
01070
01071 if (!tr->item) {
01072 LOG(llevError, "BUG: empty entry in %s's treasure list\n", god->name);
01073 continue;
01074 }
01075 item = &tr->item->clone;
01076
01077
01078 if (item->type == BOOK && item->invisible
01079 && strcmp(item->name, "grace limit") == 0) {
01080 if (op->stats.grace < item->stats.grace
01081 || op->stats.grace < op->stats.maxgrace) {
01082 object *tmp;
01083
01084
01085
01086
01087 tmp = create_archetype(HOLY_POSSESSION);
01088 cast_change_ability(op, op, tmp, 0, 1);
01089 free_object(tmp);
01090 return;
01091 }
01092 continue;
01093 }
01094
01095
01096 if (item->type == BOOK && item->invisible
01097 && strcmp(item->name, "restore grace") == 0) {
01098 if (op->stats.grace >= 0)
01099 continue;
01100 op->stats.grace = random_roll(0, 9, op, PREFER_HIGH);
01101 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01102 "You are returned to a state of grace.", NULL);
01103 return;
01104 }
01105
01106
01107 if (item->type == BOOK && item->invisible
01108 && strcmp(item->name, "restore hitpoints") == 0) {
01109 if (op->stats.hp >= op->stats.maxhp)
01110 continue;
01111 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01112 "A white light surrounds and heals you!", NULL);
01113 op->stats.hp = op->stats.maxhp;
01114 return;
01115 }
01116
01117
01118 if (item->type == BOOK
01119 && item->invisible
01120 && strcmp(item->name, "restore spellpoints") == 0) {
01121 int max = op->stats.maxsp*(item->stats.maxsp/100.0);
01122
01123 int new_sp = random_roll(1000, 1999, op, PREFER_HIGH)/2000.0*max;
01124 if (op->stats.sp >= max/2)
01125 continue;
01126 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01127 "A blue lightning strikes your head but doesn't hurt you!", NULL);
01128 op->stats.sp = new_sp;
01129 }
01130
01131
01132 if (item->type == BOOK && item->invisible
01133 && strcmp(item->name, "heal spell") == 0) {
01134 object *tmp;
01135 int success;
01136
01137 tmp = create_archetype_by_object_name(item->slaying);
01138
01139 success = cast_heal(op, op, tmp, 0);
01140 free_object(tmp);
01141 if (success)
01142 return;
01143 else
01144 continue;
01145 }
01146
01147
01148 if (item->type == BOOK && item->invisible
01149 && strcmp(item->name, "remove curse") == 0) {
01150 if (god_removes_curse(op, 0))
01151 return;
01152 else
01153 continue;
01154 }
01155
01156
01157 if (item->type == BOOK && item->invisible
01158 && strcmp(item->name, "remove damnation") == 0) {
01159 if (god_removes_curse(op, 1))
01160 return;
01161 else
01162 continue;
01163 }
01164
01165
01166 if (item->type == BOOK && item->invisible
01167 && strcmp(item->name, "heal depletion") == 0) {
01168 object *depl;
01169 archetype *at;
01170 int i;
01171
01172 if ((at = find_archetype(ARCH_DEPLETION)) == NULL) {
01173 LOG(llevError, "Could not find archetype depletion.\n");
01174 continue;
01175 }
01176 depl = present_arch_in_ob(at, op);
01177 if (depl == NULL)
01178 continue;
01179 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01180 "Shimmering light surrounds and restores you!", NULL);
01181 for (i = 0; i < NUM_STATS; i++)
01182 if (get_attr_value(&depl->stats, i))
01183 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE,
01184 MSG_TYPE_ATTRIBUTE_BAD_EFFECT_END,
01185 restore_msg[i], restore_msg[i]);
01186 remove_ob(depl);
01187 free_object(depl);
01188 fix_object(op);
01189 return;
01190 }
01191
01192
01193 if (item->type == BOOK && item->invisible
01194 && strcmp(item->name, "voice_behind") == 0) {
01195 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01196 "You hear a voice from behind you, but you don't dare to "
01197 "turn around:", NULL);
01198 draw_ext_info(NDI_WHITE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01199 item->msg, item->msg);
01200 return;
01201 }
01202
01203
01204 if (item->type == BOOK && item->invisible
01205 && strcmp(item->name, "message") == 0) {
01206 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01207 item->msg, item->msg);
01208 return;
01209 }
01210
01211
01212 if (item->type == BOOK && item->invisible
01213 && strcmp(item->name, "enchant weapon") == 0) {
01214 if (god_enchants_weapon(op, god, item, skill))
01215 return;
01216 else
01217 continue;
01218 }
01219
01220
01221 if (item->type == SPELL) {
01222 if (check_spell_known(op, item->name))
01223 continue;
01224 if (item->level > skill->level)
01225 continue;
01226
01227 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01228 "%s grants you use of a special prayer!",
01229 "%s grants you use of a special prayer!",
01230 god->name);
01231 do_learn_spell(op, item, 1);
01232 return;
01233
01234 }
01235
01236
01237 if (!item->invisible) {
01238 if (god_gives_present(op, god, tr))
01239 return;
01240 else
01241 continue;
01242 }
01243
01244 }
01245
01246 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SKILL, MSG_TYPE_SKILL_PRAY,
01247 "You feel rapture.", NULL);
01248 }
01249
01262 static int god_examines_priest(object *op, const object *god) {
01263 int reaction = 1;
01264 object *item = NULL, *skop;
01265
01266 for (item = op->inv; item; item = item->below) {
01267 if (QUERY_FLAG(item, FLAG_APPLIED)) {
01268 reaction += god_examines_item(god, item)*(item->magic ? abs(item->magic) : 1);
01269 }
01270 }
01271
01272
01273 if (reaction < 0) {
01274 int loss = 10000000;
01275 int angry = abs(reaction);
01276
01277 for (skop = op->inv; skop != NULL; skop = skop->below)
01278 if (skop->type == SKILL && skop->subtype == SK_PRAYING)
01279 break;
01280
01281 if (skop)
01282 loss = 0.05*(float)skop->stats.exp;
01283 change_exp(op, -random_roll(0, loss*angry-1, op, PREFER_LOW), skop ? skop->skill : "none", SK_SUBTRACT_SKILL_EXP);
01284 if (random_roll(0, angry, op, PREFER_LOW)) {
01285 object *tmp = create_archetype(LOOSE_MANA);
01286
01287 cast_magic_storm(op, tmp, op->level+(angry*3));
01288 }
01289 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, op, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
01290 "%s becomes angry and punishes you!",
01291 "%s becomes angry and punishes you!",
01292 god->name);
01293 }
01294 return reaction;
01295 }
01296
01313 static int god_examines_item(const object *god, object *item) {
01314 char buf[MAX_BUF];
01315
01316 if (!god || !item)
01317 return 0;
01318
01319 if (!item->title)
01320 return 1;
01321
01322 snprintf(buf, sizeof(buf), "of %s", god->name);
01323 if (!strcmp(item->title, buf))
01324 return 1;
01325
01326 if (god->title) {
01327 snprintf(buf, sizeof(buf), "of %s", god->title);
01328 if (!strcmp(item->title, buf)) {
01329 if (item->env) {
01330 char name[MAX_BUF];
01331
01332 query_name(item, name, MAX_BUF);
01333 draw_ext_info_format(NDI_UNIQUE|NDI_NAVY, 0, item->env, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
01334 "Heretic! You are using %s!",
01335 "Heretic! You are using %s!",
01336 name);
01337 }
01338 return -1;
01339 }
01340 }
01341 return 0;
01342 }
01343
01354 static const char *get_god_for_race(const char *race) {
01355 godlink *gl = first_god;
01356 const char *godname = NULL;
01357
01358 if (race == NULL)
01359 return NULL;
01360 while (gl) {
01361 if (gl->arch->clone.race && !strcasecmp(gl->arch->clone.race, race)) {
01362 godname = gl->name;
01363 break;
01364 }
01365 gl = gl->next;
01366 }
01367 return godname;
01368 }
01369
01381 int tailor_god_spell(object *spellop, object *caster) {
01382 const object *god = find_god(determine_god(caster));
01383 int caster_is_spell = 0;
01384
01385 if (caster->type == SPELL_EFFECT || caster->type == SPELL)
01386 caster_is_spell = 1;
01387
01388
01389
01390
01391
01392 if (!god && get_owner(caster))
01393 god = find_god(determine_god(get_owner(caster)));
01394
01395 if (!god || (spellop->attacktype&AT_HOLYWORD && !god->race)) {
01396 if (!caster_is_spell)
01397 draw_ext_info(NDI_UNIQUE, 0, caster, MSG_TYPE_ATTRIBUTE, MSG_TYPE_ATTRIBUTE_GOD,
01398 "This prayer is useless unless you worship an appropriate god", NULL);
01399 else
01400 LOG(llevError, "BUG: tailor_god_spell(): no god\n");
01401 free_object(spellop);
01402 return 0;
01403 }
01404
01405
01406 if (spellop->attacktype&AT_HOLYWORD || spellop->attacktype&AT_GODPOWER) {
01407 if (spellop->slaying) {
01408 free_string(spellop->slaying);
01409 spellop->slaying = NULL;
01410 }
01411 if (!caster_is_spell)
01412 spellop->slaying = god->slaying ? add_string(god->slaying) : NULL;
01413 else if (caster->slaying)
01414 spellop->slaying = add_string(caster->slaying);
01415 }
01416
01417
01418 if (spellop->attacktype&AT_GODPOWER)
01419 spellop->attacktype = spellop->attacktype|god->attacktype;
01420
01421
01422 if (spellop->attacktype&AT_HOLYWORD || spellop->attacktype&AT_GODPOWER) {
01423 if (spellop->title)
01424 free_string(spellop->title);
01425 spellop->title = add_string(god->name);
01426 if (spellop->title) {
01427 char buf[MAX_BUF];
01428
01429 snprintf(buf, sizeof(buf), "%s of %s", spellop->name, spellop->title);
01430 FREE_AND_COPY(spellop->name, buf);
01431 FREE_AND_COPY(spellop->name_pl, buf);
01432 }
01433 }
01434
01435 return 1;
01436 }