/* * $Id: magic.c,v 1.103 1999/01/21 13:36:33 kostik Exp $ */ /*************************************************************************** * ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR * * ANATOLIA has been brought to you by ANATOLIA consortium * * Serdar BULUT {Chronos} bulut@rorqual.cc.metu.edu.tr * * Ibrahim Canpunar {Asena} canpunar@rorqual.cc.metu.edu.tr * * Murat BICER {KIO} mbicer@rorqual.cc.metu.edu.tr * * D.Baris ACAR {Powerman} dbacar@rorqual.cc.metu.edu.tr * * By using this code, you have agreed to follow the terms of the * * ANATOLIA license, in the file Anatolia/anatolia.licence * ***************************************************************************/ /*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1995 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@pacinfo.com) * * Gabrielle Taylor (gtaylor@pacinfo.com) * * Brian Moore (rom@rom.efn.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "hometown.h" #include "update.h" #include "fight.h" DECLARE_DO_FUN(do_yell ); DECLARE_DO_FUN(do_look ); DECLARE_DO_FUN(do_stand ); /* * for casting different rooms * returned value is the range */ int allowed_other(CHAR_DATA *ch, int sn) { if (IS_SET(SKILL(sn)->flags, SKILL_RANGE)) return ch->level / 20 + 1; return 0; } /* * The kludgy global is for spells who want more stuff from command line. */ const char *target_name; void do_cast(CHAR_DATA *ch, const char *argument) { char arg1[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; void *vo; int mana; int sn = -1; int target; int door, range; bool cast_far = FALSE; int slevel; int chance = 0; SKILL_DATA *spell; CLASS_DATA *cl; PC_SKILL *ps; int bane_chance; if ((cl = class_lookup(ch->class)) == NULL) return; if (HAS_SKILL(ch, gsn_spellbane)) { char_puts("You are Battle Rager, not the filthy magician.\n", ch); return; } if (is_affected(ch, gsn_shielding)) { char_puts("You reach for the True Source and feel something " "stopping you.\n", ch); return; } if (is_affected(ch, gsn_garble) || is_affected(ch, gsn_deafen)) { char_puts("You can't get the right intonations.\n", ch); return; } target_name = one_argument(argument, arg1); if (arg1[0] == '\0') { char_puts("Cast which what where?\n", ch); return; } if (IS_NPC(ch)) { if (!str_cmp(arg1, "nowait")) { target_name = one_argument(target_name, arg1); if (ch->wait) ch->wait = 0; } else if (ch->wait) { log_printf("%s: wait state %d", ch->name, ch->wait); return; } sn = sn_lookup(arg1); chance = get_skill(ch, sn); } else { if ((ps = skill_vlookup(&ch->pcdata->learned, arg1)) && skill_level(ch, sn = ps->sn) <= ch->level) chance = ps->percent; } if (chance == 0) { char_puts("You don't know any spells of that name.\n", ch); return; } spell = SKILL(sn); if (HAS_SKILL(ch, gsn_vampire) && !is_affected(ch, gsn_vampire) && !IS_SET(spell->flags, SKILL_CLAN)) { char_puts("You must transform to vampire before casting!\n", ch); return; } if (spell->spell_fun == NULL) { char_puts("That's not a spell.\n", ch); return; } if (ch->position < spell->minimum_position) { char_puts("You can't concentrate enough.\n", ch); return; } if (IS_SET(ch->in_room->room_flags, ROOM_NOMAGIC)) { char_puts("Your spell fizzles out and fails.\n", ch); act("$n's spell fizzles out and fails.", ch, NULL, NULL, TO_ROOM); return; } if (!IS_NPC(ch)) { mana = mana_cost(ch, sn); if (ch->mana < mana) { char_puts("You don't have enough mana.\n", ch); return; } } else mana = 0; WAIT_STATE(ch, spell->beats); /* * Locate targets. */ victim = NULL; obj = NULL; vo = NULL; target = TARGET_NONE; bane_chance = 100; switch (spell->target) { default: bug("Do_cast: bad target for sn %d.", sn); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if (target_name[0] == '\0') { if ((victim = ch->fighting) == NULL) { char_puts("Cast the spell on whom?\n", ch); return; } } else { if ((range = allowed_other(ch, sn)) > 0) { if (!(victim = get_char_spell(ch, target_name, &door, range))) return; if (IS_NPC(victim) && victim->in_room != ch->in_room) { if (room_is_private(ch->in_room)) { char_puts("You can't cast this spell from private room right now.\n", ch); return; } if (IS_SET(victim->pIndexData->act, ACT_NOTRACK)) { act_puts("You can't cast this spell to $N at this distance.", ch, NULL, victim, TO_CHAR, POS_DEAD); return; } } cast_far = TRUE; } else if (!(victim = get_char_room(ch, target_name))) { char_puts("They aren't here.\n", ch); return; } } vo = (void *) victim; target = TARGET_CHAR; bane_chance = 2*get_skill(victim, gsn_spellbane)/3; break; case TAR_CHAR_DEFENSIVE: if (target_name[0] == '\0') victim = ch; else if ((victim = get_char_room(ch, target_name)) == NULL) { char_puts("They aren't here.\n", ch); return; } vo = (void *) victim; target = TARGET_CHAR; break; case TAR_CHAR_SELF: if (target_name[0] == '\0') victim = ch; else { if ((victim = get_char_room(ch, target_name)) == NULL || (!IS_NPC(ch) && victim != ch)) { char_puts("You cannot cast this spell " "on another.\n", ch); char_puts("They aren't here.\n", ch); return; } } vo = (void *) victim; target = TARGET_CHAR; break; case TAR_OBJ_INV: if (target_name[0] == '\0') { char_puts("What should the spell be cast upon?\n", ch); return; } if ((obj = get_obj_carry(ch, target_name)) == NULL) { char_puts("You are not carrying that.\n", ch); return; } vo = (void *) obj; target = TARGET_OBJ; break; case TAR_OBJ_CHAR_OFF: if (target_name[0] == '\0') { if ((victim = ch->fighting) == NULL) { char_puts("Cast the spell on whom or what?\n", ch); return; } target = TARGET_CHAR; } else if ((victim = get_char_room(ch, target_name))) target = TARGET_CHAR; if (target == TARGET_CHAR) { if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) { char_puts("You can't do that on your own " "follower.\n", ch); return; } vo = (void *) victim; } else if ((obj = get_obj_here(ch, target_name))) { vo = (void *) obj; target = TARGET_OBJ; } else { char_puts("You don't see that here.\n",ch); return; } break; case TAR_OBJ_CHAR_DEF: if (target_name[0] == '\0') { vo = (void *) ch; target = TARGET_CHAR; } else if ((victim = get_char_room(ch, target_name))) { vo = (void *) victim; target = TARGET_CHAR; } else if ((obj = get_obj_carry(ch, target_name))) { vo = (void *) obj; target = TARGET_OBJ; } else { char_puts("You don't see that here.\n",ch); return; } break; } if (spell->target == TAR_CHAR_OFFENSIVE || (spell->target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) { if (is_safe(ch, victim)) return; if (!IS_NPC(ch) && !IS_NPC(victim) && victim != ch && ch->fighting != victim && victim->fighting != ch && !IS_AFFECTED(victim, AFF_CHARM)) doprintf(do_yell, victim, "Die, %s, you sorcerous dog!", PERS(ch,victim)); } if (str_cmp(spell->name, "ventriloquate")) say_spell(ch, sn); if (!victim) victim = ch; if (victim && is_affected(victim, gsn_spellbane) && number_percent() < bane_chance) { if (ch == victim) { act_puts("Your spellbane deflects the spell!", ch, NULL, NULL, TO_CHAR, POS_DEAD); act("$n's spellbane deflects the spell!", ch, NULL, NULL, TO_ROOM); damage(ch, ch, 3 * ch->level, gsn_spellbane, DAM_NEGATIVE, TRUE); } else { act_puts("$N deflects your spell!", ch, NULL, victim, TO_CHAR, POS_DEAD); act("You deflect $n's spell!", ch, NULL, victim, TO_VICT); act("$N deflects $n's spell!", ch, NULL, victim, TO_NOTVICT); if (!is_safe(victim, ch)) damage(victim, ch, 3 * victim->level, gsn_spellbane, DAM_NEGATIVE, TRUE); } return; } if (number_percent() > chance) { char_puts("You lost your concentration.\n", ch); check_improve(ch, sn, FALSE, 1); ch->mana -= mana / 2; if (cast_far) cast_far = FALSE; } else { if (IS_SET(cl->flags, CLASS_MAGIC)) slevel = ch->level - UMAX(0,(ch->level / 20)); else slevel = ch->level - UMAX(5,(ch->level / 10)); if ((chance = get_skill(ch, gsn_spell_craft))) { if (number_percent() < chance) { slevel = ch->level; check_improve(ch, gsn_spell_craft, TRUE, 1); } else check_improve(ch, gsn_spell_craft, FALSE, 1); } if ((chance = get_skill(ch, gsn_improved_maladiction)) && IS_SET(spell->group, GROUP_MALADICTIONS)) { if (number_percent() < chance) { slevel = ch->level; slevel += chance/20; check_improve(ch, gsn_improved_maladiction, TRUE, 1); } else check_improve(ch, gsn_improved_maladiction, FALSE, 1); } if ((chance = get_skill(ch, gsn_improved_benediction)) && IS_SET(spell->group, GROUP_BENEDICTIONS)) { if (number_percent() < chance) { slevel = ch->level; slevel += chance/10; check_improve(ch, gsn_improved_benediction, TRUE, 1); } else check_improve(ch, gsn_improved_benediction, FALSE, 1); } if ((chance = get_skill(ch, gsn_mastering_spell)) && number_percent() < chance) { slevel += number_range(1,4); check_improve(ch, gsn_mastering_spell, TRUE, 1); } if (!IS_NPC(ch) && get_curr_stat(ch, STAT_INT) > 21) slevel += get_curr_stat(ch,STAT_INT) - 21; if (slevel < 1) slevel = 1; ch->mana -= mana; spell->spell_fun(sn, IS_NPC(ch) ? ch->level : slevel, ch, vo, target); check_improve(ch, sn, TRUE, 1); } if (cast_far && door != -1) path_to_track(ch, victim, door); else if ((spell->target == TAR_CHAR_OFFENSIVE || (spell->target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) && victim != ch && victim->master != ch) { CHAR_DATA *vch; CHAR_DATA *vch_next; for (vch = ch->in_room->people; vch; vch = vch_next) { vch_next = vch->next_in_room; if (victim == vch && victim->fighting == NULL) { if (victim->position != POS_SLEEPING) multi_hit(victim, ch, TYPE_UNDEFINED); break; } } } } /* * Cast spells at targets using a magical object. */ void obj_cast_spell(int sn, int level, CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj) { void *vo; int target = TARGET_NONE; SKILL_DATA *spell; int bane_chance; if (sn <= 0 || (spell = skill_lookup(sn)) == NULL || spell->spell_fun == NULL) return; bane_chance = 100; switch (spell->target) { default: bug("Obj_cast_spell: bad target for sn %d.", sn); return; case TAR_IGNORE: vo = NULL; break; case TAR_CHAR_OFFENSIVE: if (victim == NULL) victim = ch->fighting; if (victim == NULL) { char_puts("You can't do that.\n", ch); return; } if (is_safe(ch, victim)) { char_puts("Something isn't right...\n",ch); return; } vo = (void *) victim; target = TARGET_CHAR; bane_chance = 2 * get_skill(victim, gsn_spellbane) / 3; break; case TAR_CHAR_DEFENSIVE: case TAR_CHAR_SELF: if (victim == NULL) victim = ch; vo = (void *) victim; target = TARGET_CHAR; break; case TAR_OBJ_INV: if (obj == NULL) { char_puts("You can't do that.\n", ch); return; } vo = (void *) obj; target = TARGET_OBJ; break; case TAR_OBJ_CHAR_OFF: if (victim == NULL && obj == NULL) if (ch->fighting != NULL) victim = ch->fighting; else { char_puts("You can't do that.\n", ch); return; } if (victim) { if (is_safe(ch, victim)) { char_puts("Somehting isn't right...\n", ch); return; } vo = (void *) victim; target = TARGET_CHAR; } else { vo = (void *) obj; target = TARGET_OBJ; } break; case TAR_OBJ_CHAR_DEF: if (victim == NULL && obj == NULL) { vo = (void *) ch; target = TARGET_CHAR; } else if (victim != NULL) { vo = (void *) victim; target = TARGET_CHAR; } else { vo = (void *) obj; target = TARGET_OBJ; } break; } if (!victim) victim = ch; if (is_affected(victim, gsn_spellbane) && number_percent() < bane_chance) { if (ch == victim) { act_puts("Your spellbane deflects the spell!", ch, NULL, NULL, TO_CHAR, POS_DEAD); act("$n's spellbane deflects the spell!", ch, NULL, NULL, TO_ROOM); damage(ch, ch, 10 * level, gsn_spellbane, DAM_NEGATIVE, TRUE); } else { act_puts("$N deflects your spell!", ch, NULL, victim, TO_CHAR, POS_DEAD); act("You deflect $n's spell!", ch, NULL, victim, TO_VICT); act("$N deflects $n's spell!", ch, NULL, victim, TO_NOTVICT); if (!is_safe(victim, ch)) damage(victim, ch, 10 * victim->level, gsn_spellbane, DAM_NEGATIVE, TRUE); } return; } if (target == TARGET_OBJ && ((OBJ_DATA*) vo)->extracted) return; target_name = str_empty; spell->spell_fun(sn, level, ch, vo, target); if ((spell->target == TAR_CHAR_OFFENSIVE || (spell->target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) && victim != ch && victim->master != ch) { CHAR_DATA *vch; CHAR_DATA *vch_next; for (vch = ch->in_room->people; vch; vch = vch_next) { vch_next = vch->next_in_room; if (victim == vch && victim->fighting == NULL) { multi_hit(victim, ch, TYPE_UNDEFINED); break; } } } } /* * Spell functions. */ void spell_acid_blast(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 18); if (saves_spell(level, victim, DAM_ACID)) dam /= 2; damage(ch, victim, dam, sn,DAM_ACID,TRUE); return; } void spell_armor(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim, sn)) { if (victim == ch) char_puts("You are already armored.\n",ch); else act("$N is already armored.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 7 + level / 6; af.modifier = -1 * UMAX(20,10 + level / 4); /* af.modifier = -20;*/ af.location = APPLY_AC; af.bitvector = 0; affect_to_char(victim, &af); char_puts("You feel someone protecting you.\n", victim); if (ch != victim) act("$N is protected by your magic.",ch,NULL,victim,TO_CHAR); return; } void spell_bless(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim; OBJ_DATA *obj; AFFECT_DATA af; /* deal with the object case first */ if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (IS_OBJ_STAT(obj,ITEM_BLESS)) { act("$p is already blessed.",ch,obj,NULL,TO_CHAR); return; } if (IS_OBJ_STAT(obj,ITEM_EVIL)) { AFFECT_DATA *paf; paf = affect_find(obj->affected,gsn_curse); if (!saves_dispel(level,paf != NULL ? paf->level : obj->level,0)) { if (paf != NULL) affect_remove_obj(obj,paf); act("$p glows a pale blue.",ch,obj,NULL,TO_ALL); REMOVE_BIT(obj->extra_flags,ITEM_EVIL); return; } else { act("The evil of $p is too powerful for you to overcome.", ch,obj,NULL,TO_CHAR); return; } } af.where = TO_OBJECT; af.type = sn; af.level = level; af.duration = (6 + level / 2); af.location = APPLY_SAVES; af.modifier = -1; af.bitvector = ITEM_BLESS; affect_to_obj(obj,&af); act("$p glows with a holy aura.",ch,obj,NULL,TO_ALL); return; } /* character target */ victim = (CHAR_DATA *) vo; if (victim->position == POS_FIGHTING || is_affected(victim, sn)) { if (victim == ch) char_puts("You are already blessed.\n",ch); else act("$N already has divine favor.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (6 + level / 2); af.location = APPLY_HITROLL; af.modifier = level / 8; af.bitvector = 0; affect_to_char(victim, &af); af.location = APPLY_SAVING_SPELL; af.modifier = 0 - level / 8; affect_to_char(victim, &af); char_puts("You feel righteous.\n", victim); if (ch != victim) act("You grant $N the favor of your god.",ch,NULL,victim,TO_CHAR); return; } void spell_blindness(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_BLIND) || saves_spell(level,victim,DAM_OTHER)) { char_puts("You failed.\n", ch); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.location = APPLY_HITROLL; af.modifier = -4; af.duration = 3+level / 15; af.bitvector = AFF_BLIND; affect_to_char(victim, &af); char_puts("You are blinded!\n", victim); act("$n appears to be blinded.",victim,NULL,NULL,TO_ROOM); return; } void spell_burning_hands(int sn,int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level , 2) + 7; if (saves_spell(level, victim,DAM_FIRE)) dam /= 2; damage(ch, victim, dam, sn, DAM_FIRE,TRUE); return; } void spell_call_lightning(int sn, int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam; if (!IS_OUTSIDE(ch)) { char_puts("You must be out of doors.\n", ch); return; } if (weather_info.sky < SKY_RAINING) { char_puts("You need bad weather.\n", ch); return; } dam = dice(level, 9); char_puts("Gods' lightning strikes your foes!\n", ch); act("$n calls lightning to strike $s foes!", ch, NULL, NULL, TO_ROOM); for (vch = char_list; vch != NULL; vch = vch_next) { vch_next = vch->next; if (vch->in_room == NULL) continue; if (vch->in_room == ch->in_room) { if (is_safe_spell(ch, vch, TRUE)) continue; damage(ch, vch, saves_spell(level, vch, DAM_LIGHTNING) ? dam / 2 : dam, sn,DAM_LIGHTNING,TRUE); continue; } if (vch->in_room->area == ch->in_room->area && IS_OUTSIDE(vch) && IS_AWAKE(vch)) char_puts("Lightning flashes in the sky.\n", vch); } } /* RT calm spell stops all fighting in the room */ void spell_calm(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *vch; int mlevel = 0; int count = 0; int high_level = 0; int chance; AFFECT_DATA af; /* get sum of all mobile levels in the room */ for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (vch->position == POS_FIGHTING) { count++; if (IS_NPC(vch)) mlevel += vch->level; else mlevel += vch->level/2; high_level = UMAX(high_level,vch->level); } } /* compute chance of stopping combat */ chance = 4 * level - high_level + 2 * count; if (IS_IMMORTAL(ch)) /* always works */ mlevel = 0; if (number_range(0, chance) >= mlevel) { /* hard to stop large fights */ for (vch = ch->in_room->people; vch; vch = vch->next_in_room) { if (IS_NPC(vch) && (IS_SET(vch->imm_flags, IMM_MAGIC) || IS_SET(vch->pIndexData->act, ACT_UNDEAD))) return; if (IS_AFFECTED(vch, AFF_CALM | AFF_BERSERK) || is_affected(vch, gsn_frenzy)) return; char_puts("A wave of calm passes over you.\n", vch); if (vch->fighting || vch->position == POS_FIGHTING) stop_fighting(vch, FALSE); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level/4; af.location = APPLY_HITROLL; if (!IS_NPC(vch)) af.modifier = -5; else af.modifier = -2; af.bitvector = AFF_CALM; affect_to_char(vch, &af); af.location = APPLY_DAMROLL; affect_to_char(vch, &af); } } } void spell_cancellation(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; bool found = FALSE; level += 2; if ((!IS_NPC(ch) && IS_NPC(victim) && (!IS_AFFECTED(ch, AFF_CHARM) || ch->master != victim)) || (IS_NPC(ch) && !IS_NPC(victim)) || (!IS_NPC(victim) && victim != ch && IS_SET(victim->plr_flags, PLR_NOCANCEL))) { char_puts("You failed, try dispel magic.\n",ch); return; } /* unlike dispel magic, the victim gets NO save */ /* begin running through the spells */ if (check_dispel(level,victim,sn_lookup("armor"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("enhanced armor"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("bless"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("blindness"))) { found = TRUE; act("$n is no longer blinded.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("calm"))) { found = TRUE; act("$n no longer looks so peaceful...",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("change sex"))) { found = TRUE; act("$n looks more like $mself again.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("charm person"))) { found = TRUE; act("$n regains $s free will.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("chill touch"))) { found = TRUE; act("$n looks warmer.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("curse"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect evil"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect good"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect hidden"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect invis"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect hidden"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect magic"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("faerie fire"))) { act("$n's outline fades.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("fly"))) { act("$n falls to the ground!",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,gsn_frenzy)) { act("$n no longer looks so wild.",victim,NULL,NULL,TO_ROOM);; found = TRUE; } if (check_dispel(level,victim,sn_lookup("giant strength"))) { act("$n no longer looks so mighty.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("haste"))) { act("$n is no longer moving so quickly.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("infravision"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("invis"))) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("mass invis"))) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("pass door"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection evil"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection good"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("sanctuary"))) { act("The white aura around $n's body vanishes.", victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level, victim, sn_lookup("black shroud"))) { act("The black aura around $n's body vanishes.", victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("shield"))) { act("The shield protecting $n vanishes.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("sleep"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("slow"))) { act("$n is no longer moving so slowly.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("stone skin"))) { act("$n's skin regains its normal texture.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("weaken"))) { act("$n looks stronger.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("shielding"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("web"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("fear"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection heat"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection cold"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("magic resistance"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("hallucination"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("terangreal"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("power word stun"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("corruption"))) { act("$n looks healthier.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("web"))) { act("The webs around $n dissolve.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (found) char_puts("Ok.\n", ch); else char_puts("Spell failed.\n",ch); } void spell_cause_light(int sn, int level, CHAR_DATA *ch, void *vo,int target) { damage(ch, (CHAR_DATA *) vo, dice(1, 8) + level / 3, sn,DAM_HARM,TRUE); return; } void spell_cause_critical(int sn,int level,CHAR_DATA *ch,void *vo,int target) { damage(ch, (CHAR_DATA *) vo, dice(3, 8) + level - 6, sn,DAM_HARM,TRUE); return; } void spell_cause_serious(int sn,int level,CHAR_DATA *ch,void *vo,int target) { damage(ch, (CHAR_DATA *) vo, dice(2, 8) + level / 2, sn,DAM_HARM,TRUE); return; } void spell_chain_lightning(int sn,int level,CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; CHAR_DATA *vch,*last_vict,*next_vict; bool found; int dam; /* first strike */ act("A lightning bolt leaps from $n's hand and arcs to $N.", ch,NULL,victim,TO_ROOM); act("A lightning bolt leaps from your hand and arcs to $N.", ch,NULL,victim,TO_CHAR); act("A lightning bolt leaps from $n's hand and hits you!", ch,NULL,victim,TO_VICT); dam = dice(level,6); if (saves_spell(level,victim,DAM_LIGHTNING)) dam /= 3; damage(ch,victim,dam,sn,DAM_LIGHTNING,TRUE); last_vict = victim; level -= 4; /* decrement damage */ /* new targets */ while (level > 0) { found = FALSE; for (vch = ch->in_room->people; vch; vch = next_vict) { next_vict = vch->next_in_room; if (vch == last_vict) continue; if (is_safe_spell(ch, vch, TRUE)) { act("The bolt passes around $n's body.", ch, NULL, NULL, TO_ROOM); act("The bolt passes around your body.", ch, NULL, NULL, TO_CHAR); continue; } found = TRUE; last_vict = vch; act("The bolt arcs to $n!", vch, NULL, NULL, TO_ROOM); act("The bolt hits you!", vch, NULL, NULL, TO_CHAR); dam = dice(level,6); if (saves_spell(level, vch, DAM_LIGHTNING)) dam /= 3; damage(ch, vch, dam, sn, DAM_LIGHTNING, TRUE); level -= 4; /* decrement damage */ } /* end target searching loop */ if (found) continue; /* no target found, hit the caster */ if (ch == NULL) return; if (last_vict == ch) { /* no double hits */ act("The bolt seems to have fizzled out.", ch, NULL, NULL, TO_ROOM); act("The bolt grounds out through your body.", ch, NULL, NULL, TO_CHAR); return; } last_vict = ch; act("The bolt arcs to $n...whoops!", ch, NULL, NULL, TO_ROOM); char_puts("You are struck by your own lightning!\n", ch); dam = dice(level,6); if (saves_spell(level, ch, DAM_LIGHTNING)) dam /= 3; damage(ch, ch, dam, sn, DAM_LIGHTNING, TRUE); level -= 4; /* decrement damage */ } /* now go back and find more targets */ } void spell_healing_light(int sn, int level, CHAR_DATA *ch, void *vo,int target) { AFFECT_DATA af,af2; if (is_affected_room(ch->in_room, sn)) { char_puts("This room has already been healed by light.\n",ch); return; } af.where = TO_ROOM_CONST; af.type = sn; af.level = level; af.duration = level / 25; af.location = APPLY_ROOM_HEAL; af.modifier = level; af.bitvector = 0; affect_to_room(ch->in_room, &af); af2.where = TO_AFFECTS; af2.type = sn; af2.level = level; af2.duration = level / 10; af2.modifier = 0; af2.location = APPLY_NONE; af2.bitvector = 0; affect_to_char(ch, &af2); char_puts("The room starts to be filled with healing light.\n", ch); act("The room starts to be filled with $n's healing light.",ch,NULL,NULL,TO_ROOM); } void spell_charm_person(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; char buf[MAX_INPUT_LENGTH]; AFFECT_DATA af; if (count_charmed(ch)) return; if (victim == ch) { char_puts("You like yourself even better!\n", ch); return; } if (!IS_NPC(victim) && !IS_NPC(ch)) level+=get_curr_stat(ch,STAT_CHA)-get_curr_stat(victim,STAT_CHA); if (IS_AFFECTED(victim, AFF_CHARM) || IS_AFFECTED(ch, AFF_CHARM) || (ch->sex == SEX_MALE && level < victim->level) || (ch->sex == SEX_FEMALE && level < (victim->level + 2)) || IS_SET(victim->imm_flags, IMM_CHARM) || saves_spell(level, victim, DAM_CHARM) || (IS_NPC(victim) && victim->pIndexData->pShop != NULL) || (victim->in_room && IS_SET(victim->in_room->room_flags, ROOM_BATTLE_ARENA))) return; if (is_safe(ch, victim)) return; if (victim->master) stop_follower(victim); add_follower(victim, ch); victim->leader = ch; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = number_fuzzy(level / 5); af.location = 0; af.modifier = 0; af.bitvector = AFF_CHARM; affect_to_char(victim, &af); act("Isn't $n just so nice?", ch, NULL, victim, TO_VICT); if (ch != victim) act("$N looks at you with adoring eyes.", ch, NULL, victim, TO_CHAR); if (IS_NPC(victim) && !IS_NPC(ch)) { victim->last_fought=ch; if (number_percent() < (4 + (victim->level - ch->level)) * 10) add_mind(victim, ch->name); else if (victim->in_mind == NULL) { sprintf(buf, "%d", victim->in_room->vnum); victim->in_mind = str_dup(buf); } } } void spell_chill_touch(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; int dam; dam = number_range(1, level); if (!saves_spell(level, victim, DAM_COLD)) { act("$n turns blue and shivers.", victim, NULL, NULL, TO_ROOM); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 6; af.location = APPLY_STR; af.modifier = -1; af.bitvector = 0; affect_join(victim, &af); } else dam /= 2; damage(ch, victim, dam, sn, DAM_COLD, TRUE); } void spell_colour_spray(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level,3) + 13; if (saves_spell(level, victim, DAM_LIGHT)) dam /= 2; else spell_blindness(sn_lookup("blindness"), level/2, ch, (void *) victim, TARGET_CHAR); damage(ch, victim, dam, sn, DAM_LIGHT, TRUE); } void spell_continual_light(int sn,int level,CHAR_DATA *ch,void *vo,int target) { OBJ_DATA *light; if (target_name[0] != '\0') /* do a glow on some object */ { light = get_obj_carry(ch,target_name); if (light == NULL) { char_puts("You don't see that here.\n",ch); return; } if (IS_OBJ_STAT(light,ITEM_GLOW)) { act("$p is already glowing.",ch,light,NULL,TO_CHAR); return; } SET_BIT(light->extra_flags,ITEM_GLOW); act("$p glows with a white light.",ch,light,NULL,TO_ALL); return; } light = create_obj(get_obj_index(OBJ_VNUM_LIGHT_BALL), 0); obj_to_room(light, ch->in_room); act("$n twiddles $s thumbs and $p appears.", ch, light, NULL, TO_ROOM); act("You twiddle your thumbs and $p appears.", ch, light, NULL, TO_CHAR); return; } void spell_control_weather(int sn,int level,CHAR_DATA *ch,void *vo,int target) { if (!str_cmp(target_name, "better")) weather_info.change += dice(level / 3, 4); else if (!str_cmp(target_name, "worse")) weather_info.change -= dice(level / 3, 4); else { char_puts ("Do you want it to get better or worse?\n", ch); return; } char_puts("Ok.\n", ch); return; } void spell_create_food(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *mushroom; mushroom = create_obj(get_obj_index(OBJ_VNUM_MUSHROOM), 0); mushroom->value[0] = level / 2; mushroom->value[1] = level; obj_to_room(mushroom, ch->in_room); act("$p suddenly appears.", ch, mushroom, NULL, TO_ROOM); act("$p suddenly appears.", ch, mushroom, NULL, TO_CHAR); return; } void spell_create_rose(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *rose; if (target_name[0] == '\0') { char_puts("What rose do you want to create?\n", ch); return; } rose = create_named_obj(get_obj_index(OBJ_VNUM_ROSE), 0, target_name); rose->ed = ed_new2(rose->pIndexData->ed, target_name); act("$n has created $p", ch, rose, NULL, TO_ROOM); act("You create $p", ch, rose, NULL, TO_CHAR); obj_to_char(rose, ch); } void spell_create_spring(int sn,int level,CHAR_DATA *ch,void *vo,int target) { OBJ_DATA *spring; spring = create_obj(get_obj_index(OBJ_VNUM_SPRING), 0); spring->timer = level; obj_to_room(spring, ch->in_room); act("$p flows from the ground.", ch, spring, NULL, TO_ROOM); act("$p flows from the ground.", ch, spring, NULL, TO_CHAR); return; } void spell_create_water(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; int water; if (obj->pIndexData->item_type != ITEM_DRINK_CON) { char_puts("It is unable to hold water.\n", ch); return; } if (obj->value[2] != LIQ_WATER && obj->value[1] != 0) { char_puts("It contains some other liquid.\n", ch); return; } water = UMIN(level * (weather_info.sky >= SKY_RAINING ? 4 : 2), obj->value[0] - obj->value[1]); if (water > 0) { obj->value[2] = LIQ_WATER; obj->value[1] += water; if (!is_name("water", obj->name)) { const char *p = obj->name; obj->name = str_add(obj->name, " water", NULL); free_string(p); } act("$p is filled.", ch, obj, NULL, TO_CHAR); } } void spell_cure_blindness(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; if (!is_affected(victim, gsn_blindness)) { if (victim == ch) char_puts("You aren't blind.\n",ch); else act("$N doesn't appear to be blinded.",ch,NULL,victim,TO_CHAR); return; } if (check_dispel(level,victim,gsn_blindness)) { char_puts("Your vision returns!\n", victim); act("$n is no longer blinded.",victim,NULL,NULL,TO_ROOM); } else char_puts("Spell failed.\n",ch); } void spell_cure_critical(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; heal = dice(3, 8) + level / 2 ; victim->hit = UMIN(victim->hit + heal, victim->max_hit); update_pos(victim); char_puts("You feel better!\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } /* RT added to cure plague */ void spell_cure_disease(int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; if (!is_affected(victim, gsn_plague)) { if (victim == ch) char_puts("You aren't ill.\n",ch); else act("$N doesn't appear to be diseased.",ch,NULL,victim,TO_CHAR); return; } if (check_dispel(level,victim,gsn_plague)) { char_puts("Your sores vanish.\n",victim); act("$n looks relieved as $s sores vanish.",victim,NULL,NULL,TO_ROOM); } else char_puts("Spell failed.\n",ch); } void spell_cure_light(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; heal = dice(1, 8) + level / 4 + 5; victim->hit = UMIN(victim->hit + heal, victim->max_hit); update_pos(victim); char_puts("You feel better!\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_cure_poison(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; if (!is_affected(victim, gsn_poison)) { if (victim == ch) char_puts("You aren't poisoned.\n",ch); else act("$N doesn't appear to be poisoned.",ch,NULL,victim,TO_CHAR); return; } if (check_dispel(level,victim,gsn_poison)) { char_puts("A warm feeling runs through your body.\n",victim); act("$n looks much better.",victim,NULL,NULL,TO_ROOM); } else char_puts("Spell failed.\n",ch); } void spell_cure_serious(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; heal = dice(2, 8) + level / 3 + 10 ; victim->hit = UMIN(victim->hit + heal, victim->max_hit); update_pos(victim); char_puts("You feel better!\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_curse(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; OBJ_DATA *obj; AFFECT_DATA af; /* deal with the object case first */ if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (IS_OBJ_STAT(obj,ITEM_EVIL)) { act("$p is already filled with evil.",ch,obj,NULL,TO_CHAR); return; } if (IS_OBJ_STAT(obj,ITEM_BLESS)) { AFFECT_DATA *paf; paf = affect_find(obj->affected,sn_lookup("bless")); if (!saves_dispel(level,paf != NULL ? paf->level : obj->level,0)) { if (paf != NULL) affect_remove_obj(obj,paf); act("$p glows with a red aura.",ch,obj,NULL,TO_ALL); REMOVE_BIT(obj->extra_flags,ITEM_BLESS); return; } else { act("The holy aura of $p is too powerful for you to overcome.", ch,obj,NULL,TO_CHAR); return; } } af.where = TO_OBJECT; af.type = sn; af.level = level; af.duration = (8 + level / 5); af.location = APPLY_SAVES; af.modifier = +1; af.bitvector = ITEM_EVIL; affect_to_obj(obj,&af); act("$p glows with a malevolent aura.",ch,obj,NULL,TO_ALL); return; } /* character curses */ victim = (CHAR_DATA *) vo; if (IS_AFFECTED(victim,AFF_CURSE) || saves_spell(level,victim,DAM_NEGATIVE)) return; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (8 + level / 10); af.location = APPLY_HITROLL; af.modifier = -1 * (level / 8); af.bitvector = AFF_CURSE; affect_to_char(victim, &af); af.location = APPLY_SAVING_SPELL; af.modifier = level / 8; affect_to_char(victim, &af); char_puts("You feel unclean.\n", victim); if (ch != victim) act("$N looks very uncomfortable.",ch,NULL,victim,TO_CHAR); return; } /* RT replacement demonfire spell */ void spell_demonfire(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (!IS_NPC(ch) && !IS_EVIL(ch)) { victim = ch; char_puts("The demons turn upon you!\n",ch); } if (victim != ch) { act("$n calls forth the demons of Hell upon $N!", ch,NULL,victim,TO_ROOM); act("$n has assailed you with the demons of Hell!", ch,NULL,victim,TO_VICT); char_puts("You conjure forth the demons of hell!\n",ch); } dam = dice(level, 10); if (saves_spell(level, victim,DAM_NEGATIVE)) dam /= 2; spell_curse(gsn_curse, 3 * level / 4, ch, (void *) victim, TARGET_CHAR); damage(ch, victim, dam, sn, DAM_NEGATIVE ,TRUE); } /* added by chronos */ void spell_bluefire(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (!IS_NPC(ch) && !IS_NEUTRAL(ch)) { victim = ch; char_puts("Your blue fire turn upon you!\n",ch); } if (victim != ch) { act("$n calls forth the blue fire of earth $N!", ch,NULL,victim,TO_ROOM); act("$n has assailed you with the neutrals of earth!", ch,NULL,victim,TO_VICT); char_puts("You conjure forth the blue fire!\n",ch); } dam = dice(level, 10); if (saves_spell(level, victim,DAM_FIRE)) dam /= 2; damage(ch, victim, dam, sn, DAM_FIRE ,TRUE); } void spell_detect_evil(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_DETECT_EVIL)) { if (victim == ch) char_puts("You can already sense evil.\n",ch); else act("$N can already detect evil.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (5 + level / 3); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_EVIL; affect_to_char(victim, &af); char_puts("Your eyes tingle.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_detect_good(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_DETECT_GOOD)) { if (victim == ch) char_puts("You can already sense good.\n",ch); else act("$N can already detect good.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (5 + level / 3); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_GOOD; affect_to_char(victim, &af); char_puts("Your eyes tingle.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_detect_hidden(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_DETECT_HIDDEN)) { if (victim == ch) char_puts("You are already as alert as you can be.\n", ch); else act("$N can already sense hidden lifeforms.", ch, NULL, victim, TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 5 + level / 3; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DETECT_HIDDEN; affect_to_char(victim, &af); char_puts("Your awareness improves.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); } void spell_detect_fade(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_DETECT_FADE)) { if (victim == ch) char_puts("You are already as alert as you can be.\n", ch); else act("$N can already sense faded lifeforms.", ch, NULL, victim, TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 5 + level / 3; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DETECT_FADE; affect_to_char(victim, &af); char_puts("Your awareness improves.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); } void spell_detect_invis(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_DETECT_INVIS)) { if (victim == ch) char_puts("You can already see invisible.\n",ch); else act("$N can already see invisible things.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (5 + level / 3); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_INVIS; affect_to_char(victim, &af); char_puts("Your eyes tingle.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_detect_magic(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_DETECT_MAGIC)) { if (victim == ch) char_puts("You can already sense magical auras.\n",ch); else act("$N can already detect magic.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (5 + level / 3); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_MAGIC; affect_to_char(victim, &af); char_puts("Your eyes tingle.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_detect_poison(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; if (obj->pIndexData->item_type == ITEM_DRINK_CON || obj->pIndexData->item_type == ITEM_FOOD) { if (obj->value[3] != 0) char_puts("You smell poisonous fumes.\n", ch); else char_puts("It looks delicious.\n", ch); } else { char_puts("It doesn't look poisoned.\n", ch); } return; } void spell_dispel_evil(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (!IS_NPC(ch) && IS_EVIL(ch)) victim = ch; if (IS_GOOD(victim)) { act("Gods protects $N.", ch, NULL, victim, TO_ROOM); return; } if (IS_NEUTRAL(victim)) { act("$N does not seem to be affected.", ch, NULL, victim, TO_CHAR); return; } if (victim->hit > (ch->level * 4)) dam = dice(level, 4); else dam = UMAX(victim->hit, dice(level,4)); if (saves_spell(level, victim,DAM_HOLY)) dam /= 2; damage(ch, victim, dam, sn, DAM_HOLY ,TRUE); } void spell_dispel_good(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (!IS_NPC(ch) && IS_GOOD(ch)) victim = ch; if (IS_EVIL(victim)) { act("$N is protected by $S evil.", ch, NULL, victim, TO_ROOM); return; } if (IS_NEUTRAL(victim)) { act("$N does not seem to be affected.", ch, NULL, victim, TO_CHAR); return; } if (victim->hit > (ch->level * 4)) dam = dice(level, 4); else dam = UMAX(victim->hit, dice(level,4)); if (saves_spell(level, victim,DAM_NEGATIVE)) dam /= 2; damage(ch, victim, dam, sn, DAM_NEGATIVE ,TRUE); } /* modified for enhanced use */ void spell_dispel_magic(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; bool found = FALSE; if (saves_spell(level, victim,DAM_OTHER)) { char_puts("You feel a brief tingling sensation.\n",victim); char_puts("You failed.\n", ch); return; } /* begin running through the spells */ if (check_dispel(level,victim,sn_lookup("armor"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("enhanced armor"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("bless"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("blindness"))) { found = TRUE; act("$n is no longer blinded.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("calm"))) { found = TRUE; act("$n no longer looks so peaceful...",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("change sex"))) { found = TRUE; act("$n looks more like $mself again.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("charm person"))) { found = TRUE; act("$n regains $s free will.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("chill touch"))) { found = TRUE; act("$n looks warmer.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,sn_lookup("curse"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect evil"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect good"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect hidden"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect invis"))) found = TRUE; found = TRUE; if (check_dispel(level,victim,sn_lookup("detect hidden"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("detect magic"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("faerie fire"))) { act("$n's outline fades.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("fly"))) { act("$n falls to the ground!",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim, gsn_frenzy)) { act("$n no longer looks so wild.",victim,NULL,NULL,TO_ROOM);; found = TRUE; } if (check_dispel(level,victim,sn_lookup("giant strength"))) { act("$n no longer looks so mighty.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("haste"))) { act("$n is no longer moving so quickly.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("infravision"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("invis"))) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("mass invis"))) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("pass door"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection evil"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection good"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("sanctuary"))) { act("The white aura around $n's body vanishes.", victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level, victim, sn_lookup("black shroud"))) { act("The black aura around $n's body vanishes.", victim,NULL,NULL,TO_ROOM); found = TRUE; } if (IS_AFFECTED(victim,AFF_SANCTUARY) && !saves_dispel(level, victim->level,-1) && !is_affected(victim,sn_lookup("sanctuary"))) { REMOVE_BIT(victim->affected_by,AFF_SANCTUARY); act("The white aura around $n's body vanishes.", victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("shield"))) { act("The shield protecting $n vanishes.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("sleep"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("slow"))) { act("$n is no longer moving so slowly.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("stone skin"))) { act("$n's skin regains its normal texture.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("weaken"))) { act("$n looks stronger.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("shielding"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("web"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("fear"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection heat"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("protection cold"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("magic resistance"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("hallucination"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("terangreal"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("power word stun"))) found = TRUE; if (check_dispel(level,victim,sn_lookup("corruption"))) { act("$n looks healthier.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (check_dispel(level,victim,sn_lookup("web"))) { act("The webs around $n dissolve.",victim,NULL,NULL,TO_ROOM); found = TRUE; } if (found) char_puts("Ok.\n", ch); else char_puts("Spell failed.\n",ch); return; } void spell_earthquake(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; char_puts("The earth trembles beneath your feet!\n", ch); act("$n makes the earth tremble and shiver.", ch, NULL, NULL, TO_ROOM); for (vch = char_list; vch != NULL; vch = vch_next) { vch_next = vch->next; if (vch->in_room == NULL) continue; if (vch->in_room == ch->in_room) { if (is_safe_spell(ch, vch, TRUE)) continue; if (IS_AFFECTED(vch,AFF_FLYING)) damage(ch, vch, 0, sn, DAM_BASH, TRUE); else damage(ch, vch, level + dice(2, 8), sn, DAM_BASH,TRUE); continue; } if (vch->in_room->area == ch->in_room->area) char_puts("The earth trembles and shivers.\n", vch); } } void spell_enchant_armor(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; int result, fail; int ac_bonus, added; bool ac_found = FALSE; if (obj->pIndexData->item_type != ITEM_ARMOR) { char_puts("That isn't an armor.\n",ch); return; } if (obj->wear_loc != -1) { char_puts("The item must be carried to be enchanted.\n",ch); return; } /* this means they have no bonus */ ac_bonus = 0; fail = 25; /* base 25% chance of failure */ /* find the bonuses */ if (!IS_SET(obj->extra_flags, ITEM_ENCHANTED)) for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next) { if (paf->location == APPLY_AC) { ac_bonus = paf->modifier; ac_found = TRUE; fail += 5 * (ac_bonus * ac_bonus); } else /* things get a little harder */ fail += 20; } for (paf = obj->affected; paf != NULL; paf = paf->next) { if (paf->location == APPLY_AC) { ac_bonus = paf->modifier; ac_found = TRUE; fail += 5 * (ac_bonus * ac_bonus); } else /* things get a little harder */ fail += 20; } /* apply other modifiers */ fail -= level; if (IS_OBJ_STAT(obj,ITEM_BLESS)) fail -= 15; if (IS_OBJ_STAT(obj,ITEM_GLOW)) fail -= 5; fail = URANGE(5,fail,85); result = number_percent(); /* the moment of truth */ if (result < (fail / 5)) /* item destroyed */ { act("$p flares blindingly... and evaporates!",ch,obj,NULL,TO_CHAR); act("$p flares blindingly... and evaporates!",ch,obj,NULL,TO_ROOM); extract_obj(obj); return; } if (result < (fail / 3)) /* item disenchanted */ { AFFECT_DATA *paf_next; act("$p glows brightly, then fades...oops.",ch,obj,NULL,TO_CHAR); act("$p glows brightly, then fades.",ch,obj,NULL,TO_ROOM); /* remove all affects */ for (paf = obj->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; aff_free(paf); } obj->affected = NULL; SET_BIT(obj->extra_flags, ITEM_ENCHANTED); return; } if (result <= fail) /* failed, no bad result */ { char_puts("Nothing seemed to happen.\n",ch); return; } /* okay, move all the old flags into new vectors if we have to */ if (!IS_SET(obj->extra_flags, ITEM_ENCHANTED)) { AFFECT_DATA *af_new; SET_BIT(obj->extra_flags, ITEM_ENCHANTED); for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next) { af_new = aff_new(); af_new->next = obj->affected; obj->affected = af_new; af_new->where = paf->where; af_new->type = UMAX(0,paf->type); af_new->level = paf->level; af_new->duration = paf->duration; af_new->location = paf->location; af_new->modifier = paf->modifier; af_new->bitvector = paf->bitvector; } } if (result <= (90 - level/5)) /* success! */ { act("$p shimmers with a gold aura.",ch,obj,NULL,TO_CHAR); act("$p shimmers with a gold aura.",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags, ITEM_MAGIC); added = -1; } else /* exceptional enchant */ { act("$p glows a brillant gold!",ch,obj,NULL,TO_CHAR); act("$p glows a brillant gold!",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags,ITEM_MAGIC); SET_BIT(obj->extra_flags,ITEM_GLOW); added = -2; } /* now add the enchantments */ if (obj->level < LEVEL_HERO) obj->level = UMIN(LEVEL_HERO - 1,obj->level + 1); if (ac_found) { for (paf = obj->affected; paf != NULL; paf = paf->next) { if (paf->location == APPLY_AC) { paf->type = sn; paf->modifier += added; paf->level = UMAX(paf->level,level); } } } else /* add a new affect */ { paf = aff_new(); paf->where = TO_OBJECT; paf->type = sn; paf->level = level; paf->duration = -1; paf->location = APPLY_AC; paf->modifier = added; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } } void spell_enchant_weapon(int sn,int level,CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; int result, fail; int hit_bonus, dam_bonus, added; bool hit_found = FALSE, dam_found = FALSE; if (obj->pIndexData->item_type != ITEM_WEAPON) { char_puts("That isn't a weapon.\n",ch); return; } if (obj->wear_loc != -1) { char_puts("The item must be carried to be enchanted.\n",ch); return; } /* this means they have no bonus */ hit_bonus = 0; dam_bonus = 0; fail = 25; /* base 25% chance of failure */ /* find the bonuses */ if (!IS_SET(obj->extra_flags, ITEM_ENCHANTED)) for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next) { if (paf->location == APPLY_HITROLL) { hit_bonus = paf->modifier; hit_found = TRUE; fail += 2 * (hit_bonus * hit_bonus); } else if (paf->location == APPLY_DAMROLL) { dam_bonus = paf->modifier; dam_found = TRUE; fail += 2 * (dam_bonus * dam_bonus); } else /* things get a little harder */ fail += 25; } for (paf = obj->affected; paf != NULL; paf = paf->next) { if (paf->location == APPLY_HITROLL) { hit_bonus = paf->modifier; hit_found = TRUE; fail += 2 * (hit_bonus * hit_bonus); } else if (paf->location == APPLY_DAMROLL) { dam_bonus = paf->modifier; dam_found = TRUE; fail += 2 * (dam_bonus * dam_bonus); } else /* things get a little harder */ fail += 25; } /* apply other modifiers */ fail -= 3 * level/2; if (IS_OBJ_STAT(obj,ITEM_BLESS)) fail -= 15; if (IS_OBJ_STAT(obj,ITEM_GLOW)) fail -= 5; fail = URANGE(5,fail,95); result = number_percent(); /* the moment of truth */ if (result < (fail / 5)) /* item destroyed */ { act("$p shivers violently and explodes!",ch,obj,NULL,TO_CHAR); act("$p shivers violently and explodeds!",ch,obj,NULL,TO_ROOM); extract_obj(obj); return; } if (result < (fail / 2)) /* item disenchanted */ { AFFECT_DATA *paf_next; act("$p glows brightly, then fades...oops.",ch,obj,NULL,TO_CHAR); act("$p glows brightly, then fades.",ch,obj,NULL,TO_ROOM); /* remove all affects */ for (paf = obj->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; aff_free(paf); } obj->affected = NULL; SET_BIT(obj->extra_flags, ITEM_ENCHANTED); return; } if (result <= fail) /* failed, no bad result */ { char_puts("Nothing seemed to happen.\n",ch); return; } /* okay, move all the old flags into new vectors if we have to */ if (!IS_SET(obj->extra_flags, ITEM_ENCHANTED)) { AFFECT_DATA *af_new; SET_BIT(obj->extra_flags, ITEM_ENCHANTED); for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next) { af_new = aff_new(); af_new->next = obj->affected; obj->affected = af_new; af_new->where = paf->where; af_new->type = UMAX(0,paf->type); af_new->level = paf->level; af_new->duration = paf->duration; af_new->location = paf->location; af_new->modifier = paf->modifier; af_new->bitvector = paf->bitvector; } } if (result <= (100 - level/5)) /* success! */ { act("$p glows blue.",ch,obj,NULL,TO_CHAR); act("$p glows blue.",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags, ITEM_MAGIC); added = 1; } else /* exceptional enchant */ { act("$p glows a brillant blue!",ch,obj,NULL,TO_CHAR); act("$p glows a brillant blue!",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags,ITEM_MAGIC); SET_BIT(obj->extra_flags,ITEM_GLOW); added = 2; } /* now add the enchantments */ if (obj->level < LEVEL_HERO - 1) obj->level = UMIN(LEVEL_HERO - 1,obj->level + 1); if (dam_found) { for (paf = obj->affected; paf != NULL; paf = paf->next) { if (paf->location == APPLY_DAMROLL) { paf->type = sn; paf->modifier += added; paf->level = UMAX(paf->level,level); if (paf->modifier > 4) SET_BIT(obj->extra_flags,ITEM_HUM); } } } else /* add a new affect */ { paf = aff_new(); paf->where = TO_OBJECT; paf->type = sn; paf->level = level; paf->duration = -1; paf->location = APPLY_DAMROLL; paf->modifier = added; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } if (hit_found) { for (paf = obj->affected; paf != NULL; paf = paf->next) { if (paf->location == APPLY_HITROLL) { paf->type = sn; paf->modifier += added; paf->level = UMAX(paf->level,level); if (paf->modifier > 4) SET_BIT(obj->extra_flags,ITEM_HUM); } } } else /* add a new affect */ { paf = aff_new(); paf->type = sn; paf->level = level; paf->duration = -1; paf->location = APPLY_HITROLL; paf->modifier = added; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } } /* * Drain XP, MANA, HP. * Caster gains HP. */ void spell_energy_drain(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (saves_spell(level, victim,DAM_NEGATIVE)) { char_puts("You feel a momentary chill.\n",victim); return; } if (victim->level <= 2) { dam = ch->hit + 1; } else { gain_exp(victim, 0 - number_range(level/5, 3 * level / 5)); victim->mana /= 2; victim->move /= 2; dam = dice(1, level); ch->hit += dam; } char_puts("You feel your life slipping away!\n",victim); char_puts("Wow....what a rush!\n",ch); damage(ch, victim, dam, sn, DAM_NEGATIVE, TRUE); } void spell_hellfire(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; damage(ch, victim, dice(level, 7), sn, DAM_FIRE, TRUE); } void spell_iceball(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam; int movedam; dam = dice(level , 12); movedam = number_range(ch->level, 2 * ch->level); for (vch = ch->in_room->people; vch; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch, vch, TRUE)) continue; if (saves_spell(level, vch, DAM_COLD)) dam /= 2; vch->move -= UMIN(vch->move, movedam); damage(ch, vch, dam, sn, DAM_COLD, TRUE); } } void spell_fireball(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 15); if (saves_spell(level, victim, DAM_FIRE)) dam /= 2; damage(ch, victim, dam, sn, DAM_FIRE ,TRUE); } void spell_fireproof(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA af; if (IS_OBJ_STAT(obj,ITEM_BURN_PROOF)) { act("$p is already protected from burning.",ch,obj,NULL,TO_CHAR); return; } af.where = TO_OBJECT; af.type = sn; af.level = level; af.duration = number_fuzzy(level / 4); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = ITEM_BURN_PROOF; affect_to_obj(obj,&af); act("You protect $p from fire.",ch,obj,NULL,TO_CHAR); act("$p is surrounded by a protective aura.",ch,obj,NULL,TO_ROOM); } void spell_flamestrike(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 10); if (saves_spell(level, victim,DAM_FIRE)) dam /= 2; damage(ch, victim, dam, sn, DAM_FIRE ,TRUE); } void spell_faerie_fire(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_FAERIE_FIRE)) return; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 10 + level / 5; af.location = APPLY_AC; af.modifier = 2 * level; af.bitvector = AFF_FAERIE_FIRE; affect_to_char(victim, &af); char_puts("You are surrounded by a pink outline.\n", victim); act("$n is surrounded by a pink outline.", victim, NULL, NULL, TO_ROOM); } void spell_faerie_fog(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *ich; act("$n conjures a cloud of purple smoke.", ch, NULL, NULL, TO_ROOM); char_puts("You conjure a cloud of purple smoke.\n", ch); for (ich = ch->in_room->people; ich != NULL; ich = ich->next_in_room) { if (ich->invis_level > 0) continue; if (ich == ch || saves_spell(level, ich, DAM_OTHER)) continue; affect_bit_strip(ich, TO_AFFECTS, AFF_INVIS | AFF_IMP_INVIS); REMOVE_BIT(ich->affected_by, AFF_HIDE | AFF_FADE | AFF_CAMOUFLAGE | AFF_INVIS | AFF_IMP_INVIS); act("$n is revealed!", ich, NULL, NULL, TO_ROOM); char_puts("You are revealed!\n", ich); } } void spell_floating_disc(int sn, int level,CHAR_DATA *ch,void *vo,int target) { OBJ_DATA *disc, *floating; floating = get_eq_char(ch,WEAR_FLOAT); if (floating != NULL && IS_OBJ_STAT(floating,ITEM_NOREMOVE)) { act("You can't remove $p.",ch,floating,NULL,TO_CHAR); return; } disc = create_obj(get_obj_index(OBJ_VNUM_DISC), 0); disc->value[0] = ch->level * 10; /* 10 pounds per level capacity */ disc->value[3] = ch->level * 5; /* 5 pounds per level max per item */ disc->timer = ch->level * 2 - number_range(0,level / 2); act("$n has created a floating black disc.",ch,NULL,NULL,TO_ROOM); char_puts("You create a floating disc.\n",ch); obj_to_char(disc,ch); wear_obj(ch,disc,TRUE); return; } void spell_fly(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_FLYING)) { if (victim == ch) char_puts("You are already airborne.\n",ch); else act("$N doesn't need your help to fly.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level + 3; af.location = 0; af.modifier = 0; af.bitvector = AFF_FLYING; affect_to_char(victim, &af); char_puts("Your feet rise off the ground.\n", victim); act("$n's feet rise off the ground.", victim, NULL, NULL, TO_ROOM); } /* RT clerical berserking spell */ void spell_frenzy(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim,sn) || IS_AFFECTED(victim,AFF_BERSERK)) { if (victim == ch) char_puts("You are already in a frenzy.\n",ch); else act("$N is already in a frenzy.",ch,NULL,victim,TO_CHAR); return; } if (is_affected(victim,sn_lookup("calm"))) { if (victim == ch) char_puts("Why don't you just relax for a while?\n",ch); else act("$N doesn't look like $e wants to fight anymore.", ch,NULL,victim,TO_CHAR); return; } if ((IS_GOOD(ch) && !IS_GOOD(victim)) || (IS_NEUTRAL(ch) && !IS_NEUTRAL(victim)) || (IS_EVIL(ch) && !IS_EVIL(victim)) ) { act("Your god doesn't seem to like $N",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level / 3; af.modifier = level / 6; af.bitvector = 0; af.location = APPLY_HITROLL; affect_to_char(victim,&af); af.location = APPLY_DAMROLL; affect_to_char(victim,&af); af.modifier = 10 * (level / 12); af.location = APPLY_AC; affect_to_char(victim,&af); char_puts("You are filled with holy wrath!\n",victim); act("$n gets a wild look in $s eyes!",victim,NULL,NULL,TO_ROOM); } void spell_gate(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; bool gate_pet; if ((victim = get_char_world(ch, target_name)) == NULL || victim->level >= level + 3 || saves_spell(level, victim, DAM_OTHER) || !can_gate(ch, victim)) { char_puts("You failed.\n", ch); return; } if (ch->pet != NULL && ch->in_room == ch->pet->in_room) gate_pet = TRUE; else gate_pet = FALSE; act("$n steps through a gate and vanishes.", ch, NULL, NULL, TO_ROOM); char_puts("You step through a gate and vanish.\n", ch); char_from_room(ch); char_to_room(ch, victim->in_room); act("$n has arrived through a gate.", ch, NULL, NULL, TO_ROOM); do_look(ch, "auto"); if (gate_pet) { if (ch->pet->position != POS_STANDING) do_stand(ch->pet, str_empty); act("$n steps through a gate and vanishes.", ch->pet, NULL, NULL, TO_ROOM); char_puts("You step through a gate and vanish.\n", ch->pet); char_from_room(ch->pet); char_to_room(ch->pet, victim->in_room); act("$n has arrived through a gate.", ch->pet, NULL, NULL, TO_ROOM); do_look(ch->pet, "auto"); } } void spell_giant_strength(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim, sn)) { if (victim == ch) char_puts("You are already as strong as you can get!\n",ch); else act("$N can't get any stronger.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (10 + level / 3); af.location = APPLY_STR; af.modifier = UMAX(2,level / 10); af.bitvector = 0; affect_to_char(victim, &af); char_puts("Your muscles surge with heightened power!\n", victim); act("$n's muscles surge with heightened power.",victim,NULL,NULL,TO_ROOM); return; } void spell_harm(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = UMAX( 20, victim->hit - dice(1,4)); if (saves_spell(level, victim,DAM_HARM)) dam = UMIN(50, dam / 2); dam = UMIN(100, dam); damage(ch, victim, dam, sn, DAM_HARM ,TRUE); } /* RT haste spell */ void spell_haste(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim, sn) || IS_AFFECTED(victim,AFF_HASTE) || (IS_NPC(victim) && IS_SET(victim->pIndexData->off_flags, OFF_FAST))) { if (victim == ch) char_puts("You can't move any faster!\n",ch); else act("$N is already moving as fast as $E can.", ch, NULL, victim, TO_CHAR); return; } if (IS_AFFECTED(victim,AFF_SLOW)) { if (!check_dispel(level,victim,sn_lookup("slow"))) { if (victim != ch) char_puts("Spell failed.\n",ch); char_puts("You feel momentarily faster.\n",victim); return; } act("$n is moving less slowly.",victim,NULL,NULL,TO_ROOM); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; if (victim == ch) af.duration = level/2; else af.duration = level/4; af.location = APPLY_DEX; af.modifier = UMAX(2,level / 12); af.bitvector = AFF_HASTE; affect_to_char(victim, &af); char_puts("You feel yourself moving more quickly.\n", victim); act("$n is moving more quickly.",victim,NULL,NULL,TO_ROOM); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_heal(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; victim->hit = UMIN(victim->hit + 100 + level / 10, victim->max_hit); update_pos(victim); char_puts("A warm feeling fills your body.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_heat_metal(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj_lose, *obj_next; int dam = 0; bool fail = TRUE; if (!saves_spell(level + 2,victim,DAM_FIRE) && !IS_SET(victim->imm_flags,IMM_FIRE)) { for (obj_lose = victim->carrying; obj_lose != NULL; obj_lose = obj_next) { obj_next = obj_lose->next_content; if (number_range(1,2 * level) > obj_lose->level && !saves_spell(level,victim,DAM_FIRE) && is_metal(obj_lose) && !IS_OBJ_STAT(obj_lose,ITEM_BURN_PROOF)) { switch (obj_lose->pIndexData->item_type) { case ITEM_ARMOR: if (obj_lose->wear_loc != -1) /* remove the item */ { if (can_drop_obj(victim,obj_lose) && (obj_lose->weight / 10) < number_range(1,2 * get_curr_stat(victim,STAT_DEX)) && remove_obj(victim, obj_lose->wear_loc, TRUE)) { act("$n yelps and throws $p to the ground!", victim,obj_lose,NULL,TO_ROOM); act("You remove and drop $p before it burns you.", victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 3); obj_from_char(obj_lose); obj_to_room(obj_lose, victim->in_room); fail = FALSE; } else /* stuck on the body! ouch! */ { act("Your skin is seared by $p!", victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level)); fail = FALSE; } } else /* drop it if we can */ { if (can_drop_obj(victim,obj_lose)) { act("$n yelps and throws $p to the ground!", victim,obj_lose,NULL,TO_ROOM); act("You and drop $p before it burns you.", victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 6); obj_from_char(obj_lose); obj_to_room(obj_lose, victim->in_room); fail = FALSE; } else /* cannot drop */ { act("Your skin is seared by $p!", victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 2); fail = FALSE; } } break; case ITEM_WEAPON: if (obj_lose->wear_loc != -1) /* try to drop it */ { if (IS_WEAPON_STAT(obj_lose,WEAPON_FLAMING)) continue; if (can_drop_obj(victim,obj_lose) && remove_obj(victim,obj_lose->wear_loc,TRUE)) { act("$n is burned by $p, and throws it to the ground.", victim,obj_lose,NULL,TO_ROOM); char_puts( "You throw your red-hot weapon to the ground!\n", victim); dam += 1; obj_from_char(obj_lose); obj_to_room(obj_lose,victim->in_room); fail = FALSE; } else /* YOWCH! */ { char_puts("Your weapon sears your flesh!\n", victim); dam += number_range(1,obj_lose->level); fail = FALSE; } } else /* drop it if we can */ { if (can_drop_obj(victim,obj_lose)) { act("$n throws a burning hot $p to the ground!", victim,obj_lose,NULL,TO_ROOM); act("You and drop $p before it burns you.", victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 6); obj_from_char(obj_lose); obj_to_room(obj_lose, victim->in_room); fail = FALSE; } else /* cannot drop */ { act("Your skin is seared by $p!", victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 2); fail = FALSE; } } break; } } } } if (fail) { char_puts("Your spell had no effect.\n", ch); char_puts("You feel momentarily warmer.\n",victim); } else /* damage! */ { if (saves_spell(level,victim,DAM_FIRE)) dam = 2 * dam / 3; damage(ch,victim,dam,sn,DAM_FIRE,TRUE); } } /* RT really nasty high-level attack spell */ void spell_holy_word(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam; int sn_bless, sn_curse; if ((sn_bless = sn_lookup("bless")) < 0 || (sn_curse = sn_lookup("curse")) < 0) return; act("$n utters a word of divine power!", ch, NULL, NULL, TO_ROOM); char_puts("You utter a word of divine power.\n", ch); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if ((IS_GOOD(ch) && IS_GOOD(vch)) || (IS_EVIL(ch) && IS_EVIL(vch)) || (IS_NEUTRAL(ch) && IS_NEUTRAL(vch))) { char_puts("You feel full more powerful.\n", vch); spell_frenzy(gsn_frenzy, level, ch, vch, TARGET_CHAR); spell_bless(sn_bless, level, ch, vch, TARGET_CHAR); continue; } if (is_safe_spell(ch, vch, TRUE)) continue; if ((IS_GOOD(ch) && IS_EVIL(vch)) || (IS_EVIL(ch) && IS_GOOD(vch))) { spell_curse(sn_curse, level, ch, vch, TARGET_CHAR); char_puts("You are struck down!\n",vch); dam = dice(level, 6); damage(ch, vch, dam, sn, DAM_ENERGY, TRUE); continue; } if (IS_NEUTRAL(ch)) { spell_curse(sn_curse, level/2, ch, vch, TARGET_CHAR); char_puts("You are struck down!\n", vch); dam = dice(level, 4); damage(ch, vch, dam, sn, DAM_ENERGY, TRUE); } } char_puts("You feel drained.\n", ch); gain_exp(ch, -1 * number_range(1,10) * 5); ch->move /= (4/3); ch->hit /= (4/3); } void spell_identify(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; BUFFER *output; output = buf_new(-1); format_obj(output, obj); if (!IS_SET(obj->extra_flags, ITEM_ENCHANTED)) format_obj_affects(output, obj->pIndexData->affected, FOA_F_NODURATION | FOA_F_NOAFFECTS); format_obj_affects(output, obj->affected, FOA_F_NOAFFECTS); page_to_char(buf_string(output), ch); buf_free(output); } void spell_infravision(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_INFRARED)) { if (victim == ch) char_puts("You can already see in the dark.\n", ch); else act("$N already has infravision.\n", ch, NULL, victim,TO_CHAR); return; } act("$n's eyes glow red.\n", ch, NULL, NULL, TO_ROOM); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 2 * level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INFRARED; affect_to_char(victim, &af); char_puts("Your eyes glow red.\n", victim); } void spell_invisibility(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; OBJ_DATA *obj; AFFECT_DATA af; /* object invisibility */ if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (IS_OBJ_STAT(obj,ITEM_INVIS)) { act("$p is already invisible.",ch,obj,NULL,TO_CHAR); return; } af.where = TO_OBJECT; af.type = sn; af.level = level; af.duration = level / 4 + 12; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = ITEM_INVIS; affect_to_obj(obj,&af); act("$p fades out of sight.",ch,obj,NULL,TO_ALL); return; } /* character invisibility */ victim = (CHAR_DATA *) vo; if (IS_AFFECTED(victim, AFF_INVIS)) return; act("$n fades out of existence.", victim, NULL, NULL, TO_ROOM); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (level / 8 + 10); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INVIS; affect_to_char(victim, &af); char_puts("You fade out of existence.\n", victim); return; } void spell_know_alignment(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; char *msg; if (IS_GOOD(victim)) msg = "$N has a pure and good aura."; else if (IS_NEUTRAL(victim)) msg = "$N act as no align."; else msg = "$N is the embodiment of pure evil!."; act(msg, ch, NULL, victim, TO_CHAR); if (!IS_NPC(victim)) { if (victim->ethos == 1) msg = "$N upholds the laws."; else if (victim->ethos == 2) msg = "$N seems ambivalent to society."; else if (victim->ethos == 3) msg = "$N seems very chaotic."; else msg = "$N doesn't know where they stand on the laws."; act(msg, ch, NULL, victim, TO_CHAR); } return; } void spell_lightning_bolt(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level,4) + 12; if (saves_spell(level, victim,DAM_LIGHTNING)) dam /= 2; damage(ch, victim, dam, sn, DAM_LIGHTNING ,TRUE); } void spell_locate_object(int sn, int level, CHAR_DATA *ch, void *vo,int target) { BUFFER *buffer = NULL; OBJ_DATA *obj; OBJ_DATA *in_obj; int number = 0, max_found; number = 0; max_found = IS_IMMORTAL(ch) ? 200 : 2 * level; for (obj = object_list; obj != NULL; obj = obj->next) { if (!can_see_obj(ch, obj) || !is_name(target_name, obj->name) || IS_OBJ_STAT(obj,ITEM_NOLOCATE) || number_percent() > 2 * level || ch->level < obj->level) continue; if (buffer == NULL) buffer = buf_new(-1); number++; for (in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj) ; if (in_obj->carried_by != NULL && can_see(ch,in_obj->carried_by)) buf_printf(buffer, "One is carried by %s\n", PERS(in_obj->carried_by, ch)); else { if (IS_IMMORTAL(ch) && in_obj->in_room != NULL) buf_printf(buffer, "One is in %s [Room %d]\n", mlstr_cval(in_obj->in_room->name, ch), in_obj->in_room->vnum); else buf_printf(buffer, "One is in %s\n", in_obj->in_room == NULL ? "somewhere" : mlstr_cval(in_obj->in_room->name, ch)); } if (number >= max_found) break; } if (buffer == NULL) char_puts("Nothing like that in heaven or earth.\n", ch); else { page_to_char(buf_string(buffer),ch); buf_free(buffer); } } void spell_magic_missile(int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const int dam_each[] = { 0, 3, 3, 4, 4, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14 }; int dam; if (is_affected(ch, gsn_protective_shield)) { const char *text = ch->level > 4 ? "missiles" : "missile"; act("Your magic $t fizzle out near your victim.", ch, NULL, victim, TO_CHAR); act("Your shield blocks $N's magic $t.", victim, text, ch, TO_CHAR); return; } level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); if (ch->level > 50) dam = level / 4; else dam = number_range(dam_each[level] / 2, dam_each[level] * 2); if (saves_spell(level, victim, DAM_ENERGY)) dam /= 2; damage(ch, victim, dam, sn, DAM_ENERGY ,TRUE); if (ch->level > 4) { dam = number_range(dam_each[level] / 2, dam_each[level] * 2); if (saves_spell(level, victim, DAM_ENERGY)) dam /= 2; damage(ch, victim, dam, sn, DAM_ENERGY ,TRUE); } if (ch->level > 8) { dam = number_range(dam_each[level] / 2, dam_each[level] * 2); if (saves_spell(level, victim,DAM_ENERGY)) dam /= 2; damage(ch, victim, dam, sn, DAM_ENERGY ,TRUE); } if (ch->level > 12) { dam = number_range(dam_each[level] / 2, dam_each[level] * 2); if (saves_spell(level, victim,DAM_ENERGY)) dam /= 2; damage(ch, victim, dam, sn, DAM_ENERGY ,TRUE); } if (ch->level > 16) { dam = number_range(dam_each[level] / 2, dam_each[level] * 2); if (saves_spell(level, victim,DAM_ENERGY)) dam /= 2; damage(ch, victim, dam, sn, DAM_ENERGY ,TRUE); } } void spell_mass_healing(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *gch; int heal_num, refresh_num; heal_num = sn_lookup("heal"); refresh_num = sn_lookup("refresh"); for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) if ((IS_NPC(ch) && IS_NPC(gch)) || (!IS_NPC(ch) && !IS_NPC(gch))) { spell_heal(heal_num, level, ch, (void *) gch, TARGET_CHAR); spell_refresh(refresh_num, level, ch, (void *) gch, TARGET_CHAR); } } void spell_mass_invis(int sn, int level, CHAR_DATA *ch, void *vo, int target) { AFFECT_DATA af; CHAR_DATA *gch; for (gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room) { if (!is_same_group(gch, ch) || IS_AFFECTED(gch, AFF_INVIS)) continue; act("$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM); char_puts("You slowly fade out of existence.\n", gch); af.where = TO_AFFECTS; af.type = sn; af.level = level/2; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INVIS; affect_to_char(gch, &af); } char_puts("Ok.\n", ch); return; } void spell_pass_door(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_PASS_DOOR)) { if (victim == ch) char_puts("You are already out of phase.\n",ch); else act("$N is already shifted out of phase.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = number_fuzzy(level / 4); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_PASS_DOOR; affect_to_char(victim, &af); act("$n turns translucent.", victim, NULL, NULL, TO_ROOM); char_puts("You turn translucent.\n", victim); return; } /* RT plague spell, very nasty */ void spell_plague(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (saves_spell(level,victim,DAM_DISEASE) || (IS_NPC(victim) && IS_SET(victim->pIndexData->act, ACT_UNDEAD))) { if (ch == victim) char_puts("You feel momentarily ill, but it passes.\n",ch); else act("$N seems to be unaffected.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level * 3/4; af.duration = (10 + level / 10); af.location = APPLY_STR; af.modifier = -1 * UMAX(1,3 + level / 15); af.bitvector = AFF_PLAGUE; affect_join(victim,&af); char_puts ("You scream in agony as plague sores erupt from your skin.\n",victim); act("$n screams in agony as plague sores erupt from $s skin.", victim,NULL,NULL,TO_ROOM); } void spell_poison(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim; OBJ_DATA *obj; AFFECT_DATA af; if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (obj->pIndexData->item_type == ITEM_FOOD || obj->pIndexData->item_type == ITEM_DRINK_CON) { if (IS_OBJ_STAT(obj,ITEM_BLESS) || IS_OBJ_STAT(obj,ITEM_BURN_PROOF)) { act("Your spell fails to corrupt $p.",ch,obj,NULL,TO_CHAR); return; } obj->value[3] = 1; act("$p is infused with poisonous vapors.",ch,obj,NULL,TO_ALL); return; } if (obj->pIndexData->item_type == ITEM_WEAPON) { if (IS_WEAPON_STAT(obj,WEAPON_FLAMING) || IS_WEAPON_STAT(obj,WEAPON_FROST) || IS_WEAPON_STAT(obj,WEAPON_VAMPIRIC) || IS_WEAPON_STAT(obj,WEAPON_SHARP) || IS_WEAPON_STAT(obj,WEAPON_VORPAL) || IS_WEAPON_STAT(obj,WEAPON_SHOCKING) || IS_WEAPON_STAT(obj,WEAPON_HOLY) || IS_OBJ_STAT(obj,ITEM_BLESS) || IS_OBJ_STAT(obj,ITEM_BURN_PROOF)) { act("You can't seem to envenom $p.",ch,obj,NULL,TO_CHAR); return; } if (IS_WEAPON_STAT(obj,WEAPON_POISON)) { act("$p is already envenomed.",ch,obj,NULL,TO_CHAR); return; } af.where = TO_WEAPON; af.type = sn; af.level = level / 2; af.duration = level/8; af.location = 0; af.modifier = 0; af.bitvector = WEAPON_POISON; affect_to_obj(obj,&af); act("$p is coated with deadly venom.",ch,obj,NULL,TO_ALL); return; } act("You can't poison $p.",ch,obj,NULL,TO_CHAR); return; } victim = (CHAR_DATA *) vo; if (saves_spell(level, victim,DAM_POISON)) { act("$n turns slightly green, but it passes.",victim,NULL,NULL,TO_ROOM); char_puts("You feel momentarily ill, but it passes.\n",victim); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (10 + level / 10); af.location = APPLY_STR; af.modifier = -2; af.bitvector = AFF_POISON; affect_join(victim, &af); char_puts("You feel very sick.\n", victim); act("$n looks very ill.",victim,NULL,NULL,TO_ROOM); return; } void spell_protection_evil(int sn,int level,CHAR_DATA *ch,void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_PROTECT_EVIL) || IS_AFFECTED(victim, AFF_PROTECT_GOOD)) { if (victim == ch) char_puts("You are already protected.\n",ch); else act("$N is already protected.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (10 + level / 5); af.location = APPLY_SAVING_SPELL; af.modifier = -(1 + level/10); af.bitvector = AFF_PROTECT_EVIL; affect_to_char(victim, &af); char_puts("You feel holy and pure.\n", victim); if (ch != victim) act("$N is protected from evil.",ch,NULL,victim,TO_CHAR); return; } void spell_protection_good(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_PROTECT_GOOD) || IS_AFFECTED(victim, AFF_PROTECT_EVIL)) { if (victim == ch) char_puts("You are already protected.\n",ch); else act("$N is already protected.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (10 + level / 5); af.location = APPLY_SAVING_SPELL; af.modifier = -(1+level/10); af.bitvector = AFF_PROTECT_GOOD; affect_to_char(victim, &af); char_puts("You feel aligned with darkness.\n", victim); if (ch != victim) act("$N is protected from good.",ch,NULL,victim,TO_CHAR); return; } void spell_ray_of_truth (int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam, align; if (IS_EVIL(ch)) { victim = ch; char_puts("The energy explodes inside you!\n",ch); } if (victim != ch) { act("$n raises $s hand, and a blinding ray of light shoots forth!", ch,NULL,NULL,TO_ROOM); char_puts( "You raise your hand and a blinding ray of light shoots forth!\n", ch); } if (IS_GOOD(victim)) { act("$n seems unharmed by the light.",victim,NULL,victim,TO_ROOM); char_puts("The light seems powerless to affect you.\n",victim); return; } dam = dice(level, 10); if (saves_spell(level, victim,DAM_HOLY)) dam /= 2; align = victim->alignment; align -= 350; if (align < -1000) align = -1000 + (align + 1000) / 3; dam = (dam * align * align) / 1000000; spell_blindness(gsn_blindness, 3 * level / 4, ch, (void *) victim, TARGET_CHAR); damage(ch, victim, dam, sn, DAM_HOLY ,TRUE); } void spell_recharge(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; int chance, percent; if (obj->pIndexData->item_type != ITEM_WAND && obj->pIndexData->item_type != ITEM_STAFF) { char_puts("That item does not carry charges.\n",ch); return; } if (obj->value[3] >= 3 * level / 2) { char_puts("Your skills are not great enough for that.\n",ch); return; } if (obj->value[1] == 0) { char_puts("That item has already been recharged once.\n",ch); return; } chance = 40 + 2 * level; chance -= obj->value[3]; /* harder to do high-level spells */ chance -= (obj->value[1] - obj->value[2]) * (obj->value[1] - obj->value[2]); chance = UMAX(level/2,chance); percent = number_percent(); if (percent < chance / 2) { act("$p glows softly.",ch,obj,NULL,TO_CHAR); act("$p glows softly.",ch,obj,NULL,TO_ROOM); obj->value[2] = UMAX(obj->value[1],obj->value[2]); obj->value[1] = 0; return; } else if (percent <= chance) { int chargeback,chargemax; act("$p glows softly.",ch,obj,NULL,TO_CHAR); act("$p glows softly.",ch,obj,NULL,TO_CHAR); chargemax = obj->value[1] - obj->value[2]; if (chargemax > 0) chargeback = UMAX(1,chargemax * percent / 100); else chargeback = 0; obj->value[2] += chargeback; obj->value[1] = 0; return; } else if (percent <= UMIN(95, 3 * chance / 2)) { char_puts("Nothing seems to happen.\n",ch); if (obj->value[1] > 1) obj->value[1]--; return; } else /* whoops! */ { act("$p glows brightly and explodes!",ch,obj,NULL,TO_CHAR); act("$p glows brightly and explodes!",ch,obj,NULL,TO_ROOM); extract_obj(obj); } } void spell_refresh(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; victim->move = UMIN(victim->move + level, victim->max_move); if (victim->max_move == victim->move) char_puts("You feel fully refreshed!\n",victim); else char_puts("You feel less tired.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_remove_curse(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; OBJ_DATA *obj; bool found = FALSE; /* do object cases first */ if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (IS_OBJ_STAT(obj,ITEM_NODROP) || IS_OBJ_STAT(obj,ITEM_NOREMOVE)) { if (!IS_OBJ_STAT(obj,ITEM_NOUNCURSE) && !saves_dispel(level + 2,obj->level,0)) { REMOVE_BIT(obj->extra_flags,ITEM_NODROP); REMOVE_BIT(obj->extra_flags,ITEM_NOREMOVE); act("$p glows blue.",ch,obj,NULL,TO_ALL); return; } act("The curse on $p is beyond your power.",ch,obj,NULL,TO_CHAR); return; } else { char_puts("Nothing happens...\n", ch); return; } } /* characters */ victim = (CHAR_DATA *) vo; if (check_dispel(level,victim,gsn_curse)) { char_puts("You feel better.\n",victim); act("$n looks more relaxed.",victim,NULL,NULL,TO_ROOM); } for (obj = victim->carrying; (obj != NULL && !found); obj = obj->next_content) { if ((IS_OBJ_STAT(obj,ITEM_NODROP) || IS_OBJ_STAT(obj,ITEM_NOREMOVE)) && !IS_OBJ_STAT(obj,ITEM_NOUNCURSE)) { /* attempt to remove curse */ if (!saves_dispel(level,obj->level,0)) { found = TRUE; REMOVE_BIT(obj->extra_flags,ITEM_NODROP); REMOVE_BIT(obj->extra_flags,ITEM_NOREMOVE); act("Your $p glows blue.",victim,obj,NULL,TO_CHAR); act("$n's $p glows blue.",victim,obj,NULL,TO_ROOM); } } } } void spell_sanctuary(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_SANCTUARY)) { if (victim == ch) char_puts("You are already in sanctuary.\n",ch); else act("$N is already in sanctuary.",ch,NULL,victim,TO_CHAR); return; } if (is_affected(victim, sn_lookup("black shroud"))) { if (victim == ch) char_puts("But you are surrounded by black shroud.\n", ch); else act("But $n is surrounded by black shroud.\n", ch, NULL, victim, TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level / 6; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SANCTUARY; affect_to_char(victim, &af); act("$n is surrounded by a white aura.", victim, NULL, NULL, TO_ROOM); char_puts("You are surrounded by a white aura.\n", victim); return; } void spell_black_shroud (int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA*) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_SANCTUARY)) { if (victim==ch) char_puts("But you are in sanctuary.\n", ch); else act("But $N in sanctuary.", ch, NULL, victim,TO_CHAR); return; } if (!IS_EVIL(ch)) { char_puts("The gods are infuriated!.\n", ch); damage(ch, ch, dice(level, IS_GOOD(ch)?2:1), TYPE_HIT, DAM_HOLY,TRUE); return; } if (!IS_EVIL(victim)) { act("Your god does not seems to like $N", ch, NULL, victim, TO_CHAR); return; } if (is_affected(victim, sn)) { if (victim==ch) char_puts("You are already protected.\n", ch); else act("$N is already protected.\n", ch, NULL, victim, TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level/6; af.location = APPLY_SAVING_SPELL; af.modifier = -1; af.bitvector = 0; affect_to_char(victim, &af); act ("$n is surrounded by black aura.", victim, NULL, NULL, TO_ROOM); char_puts("You are surrounded by black aura.\n", victim); return; } void spell_shield(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim, sn)) { if (victim == ch) char_puts("You are already shielded from harm.\n",ch); else act("$N is already protected by a shield.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (8 + level / 3); af.location = APPLY_AC; af.modifier = -1 * UMAX(20,10 + level / 3); /* af.modifier = -20;*/ af.bitvector = 0; affect_to_char(victim, &af); act("$n is surrounded by a force shield.", victim, NULL, NULL, TO_ROOM); char_puts("You are surrounded by a force shield.\n", victim); return; } void spell_shocking_grasp(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const int dam_each[] = { 6, 8, 10, 12, 14, 16, 18, 20, 25, 29, 33, 36, 39, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57 }; int dam; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); if (ch->level > 50) dam = level / 2 ; else dam = number_range(dam_each[level] / 2, dam_each[level] * 2); if (saves_spell(level, victim,DAM_LIGHTNING)) dam /= 2; damage(ch, victim, dam, sn, DAM_LIGHTNING ,TRUE); } void spell_sleep(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_SLEEP) || (IS_NPC(victim) && IS_SET(victim->pIndexData->act, ACT_UNDEAD)) || level < victim->level || saves_spell(level, victim, DAM_CHARM)) return; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 1 + level/10; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; affect_join(victim, &af); if (IS_AWAKE(victim)) { char_puts("You feel very sleepy ..... zzzzzz.\n", victim); act("$n goes to sleep.", victim, NULL, NULL, TO_ROOM); victim->position = POS_SLEEPING; } return; } void spell_slow(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim, sn) || IS_AFFECTED(victim,AFF_SLOW)) { if (victim == ch) char_puts("You can't move any slower!\n",ch); else act("$N can't get any slower than that.", ch,NULL,victim,TO_CHAR); return; } if (saves_spell(level,victim,DAM_OTHER) || IS_SET(victim->imm_flags,IMM_MAGIC)) { if (victim != ch) char_puts("Nothing seemed to happen.\n",ch); char_puts("You feel momentarily lethargic.\n",victim); return; } if (IS_AFFECTED(victim,AFF_HASTE)) { if (!check_dispel(level,victim,sn_lookup("haste"))) { if (victim != ch) char_puts("Spell failed.\n",ch); char_puts("You feel momentarily slower.\n",victim); return; } act("$n is moving less quickly.",victim,NULL,NULL,TO_ROOM); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (4 + level / 12); af.location = APPLY_DEX; af.modifier = - UMAX(2,level / 12); af.bitvector = AFF_SLOW; affect_to_char(victim, &af); char_puts("You feel yourself slowing d o w n...\n", victim); act("$n starts to move in slow motion.",victim,NULL,NULL,TO_ROOM); return; } void spell_stone_skin(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(ch, sn)) { if (victim == ch) char_puts("Your skin is already as hard as a rock.\n",ch); else act("$N is already as hard as can be.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (10 + level / 5); af.location = APPLY_AC; af.modifier = -1 * UMAX(40,20 + level / 2); /*af.modifier=-40;*/ af.bitvector = 0; affect_to_char(victim, &af); act("$n's skin turns to stone.", victim, NULL, NULL, TO_ROOM); char_puts("Your skin turns to stone.\n", victim); return; } void spell_summon(int sn, int level, CHAR_DATA *ch, void *vo,int target) { bool failed = FALSE; CHAR_DATA *victim; if ((victim = get_char_world(ch, target_name)) == NULL || victim->in_room == NULL) { char_puts("You failed.\n", ch); return; } if (victim == ch || victim->level >= level + 3 || victim->fighting != NULL || !can_see_room(ch, victim->in_room) || IS_SET(ch->in_room->room_flags, ROOM_SAFE | ROOM_NORECALL | ROOM_PEACE | ROOM_NOSUMMON) || IS_SET(victim->in_room->room_flags, ROOM_SAFE | ROOM_NORECALL | ROOM_PEACE | ROOM_NOSUMMON) || IS_SET(ch->in_room->area->flags, AREA_UNDER_CONSTRUCTION) || room_is_private(ch->in_room) || IS_SET(victim->imm_flags, IMM_SUMMON) || (victim->in_room->exit[0] == NULL && victim->in_room->exit[1] == NULL && victim->in_room->exit[2] == NULL && victim->in_room->exit[3] == NULL && victim->in_room->exit[4] == NULL && victim->in_room->exit[5] == NULL)) failed = TRUE; else if (IS_NPC(victim)) { if (victim->pIndexData->pShop != NULL || saves_spell(level, victim, DAM_OTHER) || IS_SET(victim->pIndexData->act, ACT_AGGRESSIVE) || IS_SET(ch->in_room->room_flags, ROOM_NOMOB)) failed = TRUE; } else { if (victim->level >= LEVEL_HERO || ((!in_PK(ch, victim) || ch->in_room->area != victim->in_room->area) && IS_SET(victim->plr_flags, PLR_NOSUMMON)) || guild_check(victim, ch->in_room) < 0) failed = TRUE; } if (failed) { char_puts("You failed.\n", ch); return; } if (IS_NPC(victim) && victim->in_mind == NULL) { char buf[MAX_INPUT_LENGTH]; sprintf(buf,"%d",victim->in_room->vnum); victim->in_mind = str_dup(buf); } act("$n disappears suddenly.", victim, NULL, NULL, TO_ROOM); char_from_room(victim); char_to_room(victim, ch->in_room); act("$n arrives suddenly.", victim, NULL, NULL, TO_ROOM); act("$n has summoned you!", ch, NULL, victim, TO_VICT); do_look(victim, "auto"); } void spell_teleport(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; ROOM_INDEX_DATA *pRoomIndex; if (victim->in_room == NULL || IS_SET(victim->in_room->room_flags, ROOM_NORECALL) || (victim != ch && IS_SET(victim->imm_flags,IMM_SUMMON)) || (!IS_NPC(ch) && victim->fighting != NULL) || (victim != ch && (saves_spell(level - 5, victim,DAM_OTHER)))) { char_puts("You failed.\n", ch); return; } pRoomIndex = get_random_room(victim); if (victim != ch) char_puts("You have been teleported!\n", victim); act("$n vanishes!", victim, NULL, NULL, TO_ROOM); char_from_room(victim); char_to_room(victim, pRoomIndex); act("$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM); do_look(victim, "auto"); } void spell_bamf(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; ROOM_INDEX_DATA* pRoomIndex; AREA_DATA *pArea; if (victim->in_room == NULL || saves_spell(level, victim, DAM_OTHER)) { send_to_char("You failed.\n",ch); return; } pArea = victim->in_room->area; for (;;) { pRoomIndex = get_room_index(number_range(pArea->min_vnum, pArea->max_vnum)); if (pRoomIndex && can_see_room(victim, pRoomIndex) && !room_is_private(pRoomIndex) && !IS_SET(pRoomIndex->room_flags, ROOM_SAFE | ROOM_PEACE)) break; } if (victim != ch) char_puts("You have been teleported.\n", victim); act("$n vanishes.", victim, NULL, NULL, TO_ROOM); char_from_room(victim); char_to_room(victim, pRoomIndex); act("$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM); do_look(victim, "auto"); } void spell_ventriloquate(int sn, int level, CHAR_DATA *ch,void *vo,int target) { char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char speaker[MAX_INPUT_LENGTH]; CHAR_DATA *vch; target_name = one_argument(target_name, speaker); sprintf(buf1, "%s says '{G%s{x'.\n", speaker, target_name); sprintf(buf2, "Someone makes %s say '{G%s{x'.\n", speaker, target_name); buf1[0] = UPPER(buf1[0]); for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (!is_name(speaker, vch->name)) char_puts(saves_spell(level,vch,DAM_OTHER) ? buf2 : buf1, vch); } return; } void spell_weaken(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim, sn) || saves_spell(level, victim,DAM_OTHER)) return; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (4 + level / 12); af.location = APPLY_STR; af.modifier = -1 * (2 + level / 12); af.bitvector = AFF_WEAKEN; affect_to_char(victim, &af); char_puts("You feel your strength slip away.\n", victim); act("$n looks tired and weak.",victim,NULL,NULL,TO_ROOM); return; } /* RT recall spell is back */ void spell_word_of_recall(int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; ROOM_INDEX_DATA *location; int to_room_vnum; if ((ch->class == CLASS_SAMURAI) && (ch->fighting) && (victim == NULL)) { char_puts("Your honour doesn't let you recall!.\n",ch); return; } if (victim != NULL) { if ((victim->fighting) && (victim->class == CLASS_SAMURAI)) { char_puts("You can't cast this spell to a honourable fighting Samurai!.\n", ch); return; } } if (IS_NPC(victim)) return; to_room_vnum = get_recall(victim); if ((location = get_room_index(to_room_vnum)) == NULL) { char_puts("You are completely lost.\n",victim); return; } if (victim->desc != NULL && IS_PUMPED(victim)) { char_puts("You are too pumped to pray now.\n",victim); return; } act("$n prays for transportation!", ch, NULL, NULL, TO_ROOM); if (IS_SET(victim->in_room->room_flags, ROOM_NORECALL) || IS_AFFECTED(victim, AFF_CURSE) || IS_RAFFECTED(victim->in_room, RAFF_CURSE)) { char_puts("Spell failed.\n", victim); return; } if (victim->fighting) { if (victim == ch) gain_exp(victim, 0 - (victim->level + 25)); stop_fighting(victim, TRUE); } ch->move /= 2; act("$n disappears.", victim, NULL, NULL, TO_ROOM); char_from_room(victim); char_to_room(victim, location); act("$n appears in the room.", victim, NULL, NULL, TO_ROOM); do_look(victim, "auto"); if (victim->pet) { act("$n disappears.", ch->pet, NULL, NULL, TO_ROOM); char_from_room(victim->pet); char_to_room(victim->pet, location); act("$n appears in the room.", ch->pet, NULL, NULL, TO_ROOM); do_look(victim->pet, "auto"); } } /* * Draconian spells. */ void spell_acid_breath(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam,hp_dam,dice_dam,hpch; act("$n spits acid at $N.",ch,NULL,victim,TO_NOTVICT); act("$n spits a stream of corrosive acid at you.",ch,NULL,victim,TO_VICT); act("You spit acid at $N.",ch,NULL,victim,TO_CHAR); hpch = UMAX(12,ch->hit); hp_dam = number_range(hpch/11 + 1, hpch/6); dice_dam = dice(level,16); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); if (saves_spell(level,victim,DAM_ACID)) { acid_effect(victim,level/2,dam/4,TARGET_CHAR); damage(ch,victim,dam/2,sn,DAM_ACID,TRUE); } else { acid_effect(victim,level,dam,TARGET_CHAR); damage(ch,victim,dam,sn,DAM_ACID,TRUE); } } void spell_fire_breath(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; CHAR_DATA *vch, *vch_next; int dam,hp_dam,dice_dam; int hpch; act("$n breathes forth a cone of fire.",ch,NULL,victim,TO_NOTVICT); act("$n breathes a cone of hot fire over you!",ch,NULL,victim,TO_VICT); act("You breath forth a cone of fire.",ch,NULL,NULL,TO_CHAR); hpch = UMAX(10, ch->hit); hp_dam = number_range(hpch/9+1, hpch/5); dice_dam = dice(level,20); dam = UMAX(hp_dam + dice_dam /10, dice_dam + hp_dam / 10); fire_effect(victim->in_room,level,dam/2,TARGET_ROOM); for (vch = victim->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch,vch,TRUE) || (IS_NPC(vch) && IS_NPC(ch) && (ch->fighting != vch /*|| vch->fighting != ch */))) continue; if (vch == victim) /* full damage */ { if (saves_spell(level,vch,DAM_FIRE)) { fire_effect(vch,level/2,dam/4,TARGET_CHAR); damage(ch,vch,dam/2,sn,DAM_FIRE,TRUE); } else { fire_effect(vch,level,dam,TARGET_CHAR); damage(ch,vch,dam,sn,DAM_FIRE,TRUE); } } else /* partial damage */ { if (saves_spell(level - 2,vch,DAM_FIRE)) { fire_effect(vch,level/4,dam/8,TARGET_CHAR); damage(ch,vch,dam/4,sn,DAM_FIRE,TRUE); } else { fire_effect(vch,level/2,dam/4,TARGET_CHAR); damage(ch,vch,dam/2,sn,DAM_FIRE,TRUE); } } } } void spell_frost_breath(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; CHAR_DATA *vch, *vch_next; int dam,hp_dam,dice_dam, hpch; act("$n breathes out a freezing cone of frost!",ch,NULL,victim,TO_NOTVICT); act("$n breathes a freezing cone of frost over you!", ch,NULL,victim,TO_VICT); act("You breath out a cone of frost.",ch,NULL,NULL,TO_CHAR); hpch = UMAX(12,ch->hit); hp_dam = number_range(hpch/11 + 1, hpch/6); dice_dam = dice(level,16); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); cold_effect(victim->in_room,level,dam/2,TARGET_ROOM); for (vch = victim->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch,vch,TRUE) || (IS_NPC(vch) && IS_NPC(ch) && (ch->fighting != vch /*|| vch->fighting != ch*/))) continue; if (vch == victim) /* full damage */ { if (saves_spell(level,vch,DAM_COLD)) { cold_effect(vch,level/2,dam/4,TARGET_CHAR); damage(ch,vch,dam/2,sn,DAM_COLD,TRUE); } else { cold_effect(vch,level,dam,TARGET_CHAR); damage(ch,vch,dam,sn,DAM_COLD,TRUE); } } else { if (saves_spell(level - 2,vch,DAM_COLD)) { cold_effect(vch,level/4,dam/8,TARGET_CHAR); damage(ch,vch,dam/4,sn,DAM_COLD,TRUE); } else { cold_effect(vch,level/2,dam/4,TARGET_CHAR); damage(ch,vch,dam/2,sn,DAM_COLD,TRUE); } } } } void spell_gas_breath(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam,hp_dam,dice_dam,hpch; act("$n breathes out a cloud of poisonous gas!",ch,NULL,NULL,TO_ROOM); act("You breath out a cloud of poisonous gas.",ch,NULL,NULL,TO_CHAR); hpch = UMAX(16,ch->hit); hp_dam = number_range(hpch/15+1,8); dice_dam = dice(level,12); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); poison_effect(ch->in_room,level,dam,TARGET_ROOM); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch,vch,TRUE) || (IS_NPC(ch) && IS_NPC(vch) && (ch->fighting == vch || vch->fighting == ch))) continue; if (saves_spell(level,vch,DAM_POISON)) { poison_effect(vch,level/2,dam/4,TARGET_CHAR); damage(ch,vch,dam/2,sn,DAM_POISON,TRUE); } else { poison_effect(vch,level,dam,TARGET_CHAR); damage(ch,vch,dam,sn,DAM_POISON,TRUE); } } } void spell_lightning_breath(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam,hp_dam,dice_dam,hpch; act("$n breathes a bolt of lightning at $N.",ch,NULL,victim,TO_NOTVICT); act("$n breathes a bolt of lightning at you!",ch,NULL,victim,TO_VICT); act("You breathe a bolt of lightning at $N.",ch,NULL,victim,TO_CHAR); hpch = UMAX(10,ch->hit); hp_dam = number_range(hpch/9+1,hpch/5); dice_dam = dice(level,20); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); if (saves_spell(level,victim,DAM_LIGHTNING)) { shock_effect(victim,level/2,dam/4,TARGET_CHAR); damage(ch,victim,dam/2,sn,DAM_LIGHTNING,TRUE); } else { shock_effect(victim,level,dam,TARGET_CHAR); damage(ch,victim,dam,sn,DAM_LIGHTNING,TRUE); } } /* * Spells for mega1.are from Glop/Erkenbrand. */ void spell_general_purpose(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = number_range(25, 100); if (saves_spell(level, victim, DAM_PIERCE)) dam /= 2; damage(ch, victim, dam, sn, DAM_PIERCE ,TRUE); } void spell_high_explosive(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = number_range(30, 120); if (saves_spell(level, victim, DAM_PIERCE)) dam /= 2; damage(ch, victim, dam, sn, DAM_PIERCE ,TRUE); } void spell_find_object(int sn, int level, CHAR_DATA *ch, void *vo,int target) { BUFFER *buffer = NULL; OBJ_DATA *obj; OBJ_DATA *in_obj; int number = 0, max_found; number = 0; max_found = IS_IMMORTAL(ch) ? 200 : 2 * level; for (obj = object_list; obj != NULL; obj = obj->next) { if (!can_see_obj(ch, obj) || !is_name(target_name, obj->name) || number_percent() > 2 * level || ch->level < obj->level) continue; if (buffer == NULL) buffer = buf_new(-1); number++; for (in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj) ; if (in_obj->carried_by != NULL && can_see(ch,in_obj->carried_by)) buf_printf(buffer, "One is carried by %s\n", PERS(in_obj->carried_by, ch)); else { if (IS_IMMORTAL(ch) && in_obj->in_room != NULL) buf_printf(buffer, "One is in %s [Room %d]\n", mlstr_cval(in_obj->in_room->name, ch), in_obj->in_room->vnum); else buf_printf(buffer, "One is in %s\n", in_obj->in_room == NULL ? "somewhere" : mlstr_cval(in_obj->in_room->name, ch)); } if (number >= max_found) break; } if (buffer == NULL) char_puts("Nothing like that in heaven or earth.\n", ch); else { page_to_char(buf_string(buffer),ch); buf_free(buffer); } } void spell_lightning_shield(int sn, int level, CHAR_DATA *ch, void *vo,int target) { AFFECT_DATA af,af2; if (is_affected_room(ch->in_room, sn)) { char_puts("This room has already shielded.\n",ch); return; } if (is_affected(ch,sn)) { char_puts("This spell is used too recently.\n",ch); return; } af.where = TO_ROOM_AFFECTS; af.type = sn; af.level = ch->level; af.duration = level / 40; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = RAFF_LSHIELD; affect_to_room(ch->in_room, &af); af2.where = TO_AFFECTS; af2.type = sn; af2.level = ch->level; af2.duration = level / 10; af2.modifier = 0; af2.location = APPLY_NONE; af2.bitvector = 0; affect_to_char(ch, &af2); ch->in_room->owner = str_dup(ch->name); char_puts("The room starts to be filled with lightnings.\n", ch); act("The room starts to be filled with $n's lightnings.",ch,NULL,NULL,TO_ROOM); return; } void spell_shocking_trap(int sn, int level, CHAR_DATA *ch, void *vo,int target) { AFFECT_DATA af,af2; if (is_affected_room(ch->in_room, sn)) { char_puts("This room has already trapped with shocks waves.\n",ch); return; } if (is_affected(ch,sn)) { char_puts("This spell is used too recently.\n",ch); return; } af.where = TO_ROOM_AFFECTS; af.type = sn; af.level = ch->level; af.duration = level / 40; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = RAFF_SHOCKING; affect_to_room(ch->in_room, &af); af2.where = TO_AFFECTS; af2.type = sn; af2.level = level; af2.duration = ch->level / 10; af2.modifier = 0; af2.location = APPLY_NONE; af2.bitvector = 0; affect_to_char(ch, &af2); char_puts("The room starts to be filled with shock waves.\n", ch); act("The room starts to be filled with $n's shock waves.",ch,NULL,NULL,TO_ROOM); return; } void spell_acid_arrow(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 12); if (saves_spell(level, victim, DAM_ACID)) dam /= 2; damage(ch, victim, dam, sn,DAM_ACID,TRUE); } /* energy spells */ void spell_etheral_fist(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 12); if (saves_spell(level, victim, DAM_ENERGY)) dam /= 2; act("A fist of black, otherworldly ether rams into $N, leaving $M looking stunned!" ,ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_ENERGY,TRUE); } void spell_spectral_furor(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 8); if (saves_spell(level, victim, DAM_ENERGY)) dam /= 2; act("The fabric of the cosmos strains in fury about $N!", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_ENERGY,TRUE); } void spell_disruption(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 9); if (saves_spell(level, victim, DAM_ENERGY)) dam /= 2; act("A weird energy encompasses $N, causing you to question $S continued existence.", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_ENERGY,TRUE); } void spell_sonic_resonance(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 7); if (saves_spell(level, victim, DAM_ENERGY)) dam /= 2; act("A cylinder of kinetic energy enshrouds $N causing $S to resonate.", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_ENERGY,TRUE); } /* mental */ void spell_mind_wrack(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 7); if (saves_spell(level, victim, DAM_MENTAL)) dam /= 2; act("$n stares intently at $N, causing $N to seem very lethargic.", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_MENTAL,TRUE); } void spell_mind_wrench(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 9); if (saves_spell(level, victim, DAM_MENTAL)) dam /= 2; act("$n stares intently at $N, causing $N to seem very hyperactive.", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_MENTAL,TRUE); } /* acid */ void spell_sulfurus_spray(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 7); if (saves_spell(level, victim, DAM_ACID)) dam /= 2; act("A stinking spray of sulfurous liquid rains down on $N." , ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_ACID,TRUE); } void spell_caustic_font(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 9); if (saves_spell(level, victim, DAM_ACID)) dam /= 2; act("A fountain of caustic liquid forms below $N. The smell of $S degenerating tissues is revolting! ", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_ACID,TRUE); } void spell_acetum_primus(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 8); if (saves_spell(level, victim, DAM_ACID)) dam /= 2; act("A cloak of primal acid enshrouds $N, sparks form as it consumes all it touches. ", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_ACID,TRUE); } /* Electrical */ void spell_galvanic_whip(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 7); if (saves_spell(level, victim, DAM_LIGHTNING)) dam /= 2; act("$n conjures a whip of ionized particles, which lashes ferociously at $N.", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_LIGHTNING,TRUE); } void spell_magnetic_trust(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 8); if (saves_spell(level, victim, DAM_LIGHTNING)) dam /= 2; act("An unseen energy moves nearby, causing your hair to stand on end!", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_LIGHTNING,TRUE); } void spell_quantum_spike(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice(level, 9); if (saves_spell(level, victim, DAM_LIGHTNING)) dam /= 2; act("$N seems to dissolve into tiny unconnected particles, then is painfully reassembled.", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_LIGHTNING,TRUE); } /* negative */ void spell_hand_of_undead(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (saves_spell(level, victim, DAM_NEGATIVE)) { char_puts("You feel a momentary chill.\n",victim); return; } if (IS_NPC(victim) && IS_SET(victim->pIndexData->act, ACT_UNDEAD)) { char_puts("Your victim is unaffected by hand of undead.\n",ch); return; } if (victim->level <= 2) dam = ch->hit + 1; else { dam = dice(level, 10); victim->mana /= 2; victim->move /= 2; ch->hit += dam / 2; } char_puts("You feel your life slipping away!\n",victim); act("$N is grasped by an incomprehensible hand of undead!", ch,NULL,victim,TO_NOTVICT); damage(ch, victim, dam, sn,DAM_NEGATIVE,TRUE); } /* travel via astral plains */ void spell_astral_walk(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; bool gate_pet; if ((victim = get_char_world(ch, target_name)) == NULL || victim->level >= level + 3 || saves_spell(level, victim, DAM_OTHER) || !can_gate(ch, victim)) { char_puts("You failed.\n", ch); return; } if (ch->pet != NULL && ch->in_room == ch->pet->in_room) gate_pet = TRUE; else gate_pet = FALSE; act("$n disappears in a flash of light!",ch,NULL,NULL,TO_ROOM); char_printf(ch,"You travel via astral planes and go to %s.\n",victim->name); char_from_room(ch); char_to_room(ch,victim->in_room); act("$n appears in a flash of light!",ch,NULL,NULL,TO_ROOM); do_look(ch,"auto"); if (gate_pet) { act("$n disappears in a flash of light!",ch->pet,NULL,NULL,TO_ROOM); char_printf(ch->pet, "You travel via astral planes and go to %s.\n",victim->name); char_from_room(ch->pet); char_to_room(ch->pet,victim->in_room); act("$n appears in a flash of light!",ch->pet,NULL,NULL,TO_ROOM); do_look(ch->pet,"auto"); } } /* vampire version astral walk */ void spell_mist_walk(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; if ((victim = get_char_world(ch, target_name)) == NULL || victim->level >= level - 5 || saves_spell(level, victim, DAM_OTHER) || !can_gate(ch, victim)) { char_puts("You failed.\n", ch); return; } act("$n dissolves into a cloud of glowing mist, then vanishes!",ch,NULL,NULL,TO_ROOM); char_puts("You dissolve into a cloud of glowing mist, then flow to your target.\n",ch); char_from_room(ch); char_to_room(ch,victim->in_room); act("A cloud of glowing mist engulfs you, then withdraws to unveil $n!",ch,NULL,NULL,TO_ROOM); do_look(ch,"auto"); } /* Cleric version of astra_walk */ void spell_solar_flight(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; if (time_info.hour > 18 || time_info.hour < 8) { char_puts("You need sunlight for solar flight.\n",ch); return; } if ((victim = get_char_world(ch, target_name)) == NULL || victim->level >= level + 1 || saves_spell(level, victim, DAM_OTHER) || !can_gate(ch, victim)) { char_puts("You failed.\n", ch); return; } act("$n disappears in a blinding flash of light!",ch,NULL,NULL,TO_ROOM); char_puts("You dissolve in a blinding flash of light!.\n",ch); char_from_room(ch); char_to_room(ch,victim->in_room); act("$n appears in a blinding flash of light!",ch,NULL,NULL,TO_ROOM); do_look(ch,"auto"); } /* travel via astral plains */ void spell_helical_flow(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; if ((victim = get_char_world(ch, target_name)) == NULL || victim->level >= level + 3 || saves_spell(level, victim, DAM_OTHER) || !can_gate(ch, victim)) { char_puts("You failed.\n", ch); return; } act("$n coils into an ascending column of colour, vanishing into thin air.",ch,NULL,NULL,TO_ROOM); char_puts("You coils into an ascending column of colour, and vanishing into thin air.\n",ch); char_from_room(ch); char_to_room(ch,victim->in_room); act("A coil of colours descends from above, revealing $n as it dissipates.",ch,NULL,NULL,TO_ROOM); do_look(ch,"auto"); } void spell_corruption(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim,AFF_CORRUPTION)) { act("$N is already corrupting.\n",ch,NULL,victim,TO_CHAR); return; } if (saves_spell(level, victim, DAM_NEGATIVE) || (IS_NPC(victim) && IS_SET(victim->pIndexData->act, ACT_UNDEAD))) { if (ch == victim) char_puts("You feel momentarily ill, but it passes.\n",ch); else act("$N seems to be unaffected.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level * 3/4; af.duration = (10 + level / 5); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_CORRUPTION; affect_join(victim,&af); char_puts ("You scream in agony as you start to decay into dust.\n",victim); act("$n screams in agony as $n start to decay into dust.", victim,NULL,NULL,TO_ROOM); } void spell_hurricane(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam,hp_dam,dice_dam,hpch; act("$n prays the gods of the storm for help.",ch,NULL,NULL,TO_NOTVICT); act("You pray the gods of the storm to help you.",ch,NULL,NULL,TO_CHAR); hpch = UMAX(16,ch->hit); hp_dam = number_range(hpch/15+1,8); dice_dam = dice(level,12); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch,vch,TRUE) || (IS_NPC(ch) && IS_NPC(vch) && (ch->fighting == vch || vch->fighting == ch))) continue; if (!IS_AFFECTED(vch,AFF_FLYING)) dam /= 2; if (vch->size == SIZE_TINY) dam *= 1.5; else if (vch->size == SIZE_SMALL) dam *= 1.3; else if (vch->size == SIZE_MEDIUM) dam *= 1; else if (vch->size == SIZE_LARGE) dam *= 0.9; else if (vch->size == SIZE_HUGE) dam *= 0.7; else dam *= 0.5; if (saves_spell(level,vch,DAM_OTHER)) damage(ch,vch,dam/2,sn,DAM_OTHER,TRUE); else damage(ch,vch,dam,sn,DAM_OTHER,TRUE); } } void spell_detect_undead(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim, AFF_DETECT_UNDEAD)) { if (victim == ch) char_puts("You can already sense undead.\n",ch); else act("$N can already detect undead.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (5 + level / 3); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_UNDEAD; affect_to_char(victim, &af); char_puts("Your eyes tingle.\n", victim); if (ch != victim) char_puts("Ok.\n", ch); return; } void spell_take_revenge(int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj; OBJ_DATA *in_obj; ROOM_INDEX_DATA *room = NULL; bool found = FALSE; if (IS_NPC(ch) && !IS_SET(ch->plr_flags, PLR_GHOST)) { char_puts("It is too late to take revenge.\n",ch); return; } for (obj = object_list; obj != NULL; obj = obj->next) { if (obj->pIndexData->vnum != OBJ_VNUM_CORPSE_PC /* XXX */ || !is_name(ch->name, mlstr_mval(obj->short_descr))) continue; found = TRUE; for (in_obj = obj; in_obj->in_obj; in_obj = in_obj->in_obj) ; if (in_obj->carried_by != NULL) room = in_obj->carried_by->in_room; else room = in_obj->in_room; break; } if (!found || room == NULL) char_puts("Unluckily your corpse is devoured.\n", ch); else { char_from_room(ch); char_to_room(ch, room); do_look(ch,"auto"); } return; }