/*************************************************************************** * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills and Dug Michael. * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ #include "emud.h" /* Local functions. */ void say_spell args( ( CHAR_DATA *ch, int sn ) ); int multi_spell_level args( ( CHAR_DATA *ch, int sn ) ); int can_cast_spell args( ( CHAR_DATA *ch, int sn ) ); int caster_levels args( ( CHAR_DATA *ch ) ); bool is_safe_magic args( ( CHAR_DATA *ch, CHAR_DATA *victim, int sn ) ); int magic_modify args( ( CHAR_DATA *ch, CHAR_DATA *victim, int sn, int level ) ); bool can_mass_cast args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); #define DO_SPELL(spell) void spell( int sn, int level, CHAR_DATA *ch, void *vo, int target ) int value; /* This is the value after the target */ void make_char_fight_char( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("make_char_fight_char(%p,%p)",ch,victim); if (ch == NULL || victim == NULL || victim->position == POS_DEAD) { pop_call(); return; } if (ch == victim) { pop_call(); return; } /* set recently fought */ if (!IS_NPC(ch) && IS_NPC(victim)) { if (ch->leader && !IS_NPC(ch->leader)) { victim->npcdata->pvnum_last_hit = ch->leader->pcdata->pvnum; } else { victim->npcdata->pvnum_last_hit = ch->pcdata->pvnum; } } pop_call(); return; } /* Lookup a skill by name. */ int skill_lookup( char *name ) { int sn; push_call("skill_lookup(%p)",name); for (sn = 0 ; sn < MAX_SKILL ; sn++) { if (tolower(name[0]) == skill_table[sn].name[0]) { if (!strcmp(name, skill_table[sn].name)) { pop_call(); return sn; } } } for (sn = 0 ; sn < MAX_SKILL ; sn++) { if (tolower(name[0]) == skill_table[sn].name[0]) { if (is_multi_name_short(name, skill_table[sn].name)) { pop_call(); return sn; } } } pop_call(); return -1; } /* Lookup a skill by slot number. Used for object loading. */ int slot_lookup( int slot ) { int sn; push_call("slot_lookup(%p)",slot); if (slot <= 0) { pop_call(); return 0; } for (sn = 0 ; sn < MAX_SKILL ; sn++ ) { if (slot == skill_table[sn].slot) { pop_call(); return sn; } } bug("slot_lookup: bad slot %d.", slot); if (IS_SET(mud->flags, MUD_EMUD_BOOTDB)) { abort(); } pop_call(); return -1; } /* Utter mystical words for an sn. */ void say_spell( CHAR_DATA *ch, int sn ) { char buf [MAX_STRING_LENGTH]; char buf2 [MAX_STRING_LENGTH]; CHAR_DATA *rch; char *pName; int iSyl; int length; struct syl_type { char *old; char *new; }; static const struct syl_type syl_table[] = { { " ", " " }, { "ar", "abra" }, { "au", "kada" }, { "bless", "fido" }, { "blind", "nose" }, { "bur", "mosa" }, { "cu", "judi" }, { "de", "oculo" }, { "en", "unso" }, { "hance", "sch" }, { "light", "dies" }, { "lo", "hi" }, { "mor", "zak" }, { "move", "sido" }, { "ob", "kn" }, { "ness", "lacri" }, { "ning", "illa" }, { "per", "duda" }, { "ra", "gru" }, { "re", "candus" }, { "son", "sabru" }, { "tect", "infra" }, { "tri", "cula" }, { "ven", "nofo" }, { "a", "a" }, { "b", "b" }, { "c", "q" }, { "d", "e" }, { "e", "z" }, { "f", "y" }, { "g", "o" }, { "h", "p" }, { "i", "u" }, { "j", "y" }, { "k", "t" }, { "l", "r" }, { "m", "w" }, { "n", "i" }, { "o", "a" }, { "p", "s" }, { "q", "d" }, { "r", "f" }, { "s", "g" }, { "t", "h" }, { "u", "j" }, { "v", "z" }, { "w", "x" }, { "x", "n" }, { "y", "l" }, { "z", "k" }, { "", "" } }; push_call("say_spell(%p,%p)",ch,sn); buf[0] = '\0'; for (pName = skill_table[sn].name ; *pName != '\0' ; pName += length) { for (iSyl = 0 ; (length = strlen(syl_table[iSyl].old)) != 0 ; iSyl++) { if (!str_prefix(syl_table[iSyl].old, pName)) { strcat(buf, syl_table[iSyl].new); break; } } if ( length == 0 ) { length = 1; } } sprintf( buf2, "$n utters the words, '%s'.", buf ); sprintf( buf, "$n utters the words, '%s'.", skill_table[sn].name ); /* make wizcloaked gods even more invis, their uttering cannot be heard... */ if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WIZCLOAK)) { pop_call(); return; } for (rch = ch->in_room->first_person ; rch ; rch = rch->next_in_room) { if (rch != ch) { if (IS_NPC(rch) || !IS_SET(rch->pcdata->spam, 4096)) { if (IS_NPC(rch) || learned(rch, sn) == 0 || (IS_AFFECTED(ch, AFF2_QUICKEN) && !IS_AFFECTED(rch, AFF2_QUICKEN)) || (skill_table[sn].follower && which_god(ch) != which_god(rch)) || (skill_table[sn].race && ch->race != rch->race)) { act(buf2, ch, NULL, rch, TO_VICT); } else { act(buf, ch, NULL, rch, TO_VICT); } } } } pop_call(); return; } /* Compute a saving throw. Negative apply's make saving throw better. */ bool saves_spell( int level, CHAR_DATA *ch, CHAR_DATA *victim ) { CHAR_DATA *fch; int range, point; push_call("saves_spell(%p,%p,%p)",level,ch,victim); point = 50 + level * 3 / 4; if (IS_NPC(victim)) { range = 100 + victim->level / 2 - GET_SAVING_THROW(victim) * 2; } else { range = 100 - GET_SAVING_THROW(victim) * 4; } /* Add a bit of distraction to tanking spell casters - Chaos 7/11/96 */ for (fch = ch->in_room->first_person ; fch != NULL ; fch = fch->next_in_room) { if (fch != ch && fch->fighting != NULL && fch->fighting->who == ch) { range += fch->level/5; } } range -= get_curr_int(ch); if (IS_AFFECTED(victim, AFF_PROTECT_EVIL) && IS_EVIL(ch)) { range += 15; } if (IS_AFFECTED(victim, AFF_PROTECT_GOOD) && IS_GOOD(ch)) { range += 15; } if (range > 1 && number_range(1, range) >= point) { pop_call(); return(TRUE); /* Spell Fails */ } else { pop_call(); return( FALSE ); /* Spell Works */ } /* Chaos changing to universal scaling system 12/16/94 */ } /* The kludgy global is for spells who want more stuff from command line. */ char *target_name; void do_cast( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; void *vo; int mana, sn, level, percentage, target; push_call("do_cast(%p,%p)",ch,argument); if (strlen(argument) > 100) { *(argument+80)='\0'; } percentage = 100; argument = one_argument(argument, arg1); /* Grab reduced spell strength percentage value - Chaos 7/26/96 */ if (*arg1 != '\0' && is_number(arg1)) { percentage = atol(arg1); argument = one_argument(argument, arg1); percentage = URANGE(1, percentage, 100); } target_name = argument; argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); if (strlen(target_name) > 50) { target_name[50] = '\0'; } if (arg1[0] == '\0') { send_to_char( "Cast which what where?\n\r", ch ); pop_call(); return; } value = -1; /* Default value */ if (is_number(arg2)) /* Special numbers only spell */ { value = atol(arg2); strcpy( arg2, ""); if (value < 1) { value = -1; /* Default value */ } } else if (arg3[0] != '\0') /* Read the extra value - Chaos 2/8/95 */ { value = atol( arg3 ); if ( value < 1 ) { value = -1; /* Default value */ } } sn = skill_lookup( arg1 ); if (sn < 0 || !is_spell(sn)) { if (!IS_NPC(ch) && ch->desc == NULL) { log_printf("[%u] casting unknown spell: %s", ch->pIndexData->vnum, arg1); } send_to_char( "That is not a spell.\n\r", ch ); pop_call(); return; } if ((level = can_cast_spell(ch, sn)) == -1) { pop_call(); return; } if (is_safe_magic(ch, NULL, sn)) { pop_call(); return; } mana = get_mana(ch, sn); level = level * percentage / 100 ; if (level < 1) { level = 1; } /* Locate targets. */ victim = NULL; obj = NULL; vo = NULL; target = skill_table[sn].target; switch (target) { default: bug( "do_cast: bad target for sn %d.", sn ); pop_call(); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if (arg2[0] == '\0') { if (ch->fighting == NULL || ch->fighting->who == NULL) { send_to_char( "Cast the spell on whom?\n\r", ch ); pop_call(); return; } victim = ch->fighting->who; } else { if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_CHAR_DEFENSIVE: if (arg2[0] == '\0') { victim = ch; } else { if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "They aren't here.\n\r", ch ); pop_call(); return; } } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_CHAR_SELF: if (arg2[0] != '\0' && !is_name_short(arg2, ch->name)) { send_to_char( "You cannot cast this spell on another.\n\r", ch ); pop_call(); return; } vo = (void *) ch; break; case TAR_OBJ_INV: if (arg2[0] == '\0') { send_to_char( "What should the spell be cast upon?\n\r", ch ); pop_call(); return; } if ((obj = get_obj_carry(ch, arg2)) == NULL) { send_to_char( "You are not carrying that.\n\r", ch ); pop_call(); return; } vo = (void *) obj; break; case TAR_OBJ_CHAR_DEF: if (arg2[0] == '\0') { victim = ch; } else if ((victim = get_char_room(ch, arg2)) == NULL) { if ((obj = get_obj_carry(ch, arg2)) == NULL) { send_to_char( "Who or what should the spell be cast upon?\n\r", ch ); pop_call(); return; } } if (victim) { if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } target = TAR_CHAR_DEFENSIVE; vo = (void *) victim; } else { target = TAR_OBJ_INV; vo = (void *) obj; } break; case TAR_OBJ_CHAR_OFF: if (arg2[0] == '\0') { if (who_fighting(ch) == NULL) { send_to_char("Cast the spell on whom?\n\r", ch); pop_call(); return; } victim = ch->fighting->who; } else if ((victim = get_char_room(ch, arg2)) == NULL) { if ((obj = get_obj_carry(ch, arg2)) == NULL) { send_to_char( "Who or what should the spell be cast upon?\n\r", ch ); pop_call(); return; } } if (victim) { if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } target = TAR_CHAR_OFFENSIVE; vo = (void *) victim; } else { target = TAR_OBJ_INV; vo = (void *) obj; } break; } if (!IS_IMMORTAL(ch) && ch->mana < mana) { send_to_char( "You don't have enough mana.\n\r", ch ); pop_call(); return; } if (strcasecmp( skill_table[sn].name, "ventriloquate" ) ) { say_spell( ch, sn ); } if (IS_AFFECTED(ch, AFF2_QUICKEN)) { wait_state( ch, skill_table[sn].beats * 4 / 5 ); } else { wait_state( ch, skill_table[sn].beats ); } if (!IS_IMMORTAL(ch) && number_percent() > learned(ch, sn)) { if (ch->fighting != NULL) { switch (number_bits(3)) { case 0 : send_to_char( "This round of battle is too hectic to concentrate properly.\n\r", ch ); break; case 1 : send_to_char( "There wasn't enough time this round to complete the casting.\n\r", ch ); break; case 2 : send_to_char( "Despite your efforts you only produce worthless smoke.\n\r", ch ); break; case 3 : send_to_char( "You lose control over your magic and only scorch the ground.\n\r", ch ); break; case 4 : send_to_char( "The air sizzles with magic, but you fail to strike your victim.\n\r", ch ); break; case 5 : send_to_char( "You hesitate mid-way through the casting and nothing happens.\n\r", ch ); break; default: send_to_char( "You lost your concentration.\n\r", ch ); break; } } else { switch (number_bits(3)) { case 0 : send_to_char( "A tickle in your nose prevents you from keeping your concentration.\n\r", ch ); break; case 1 : send_to_char( "An itch on your leg keeps you from properly casting your spell.\n\r", ch ); break; case 2 : send_to_char( "Something in your throat prevents you from uttering the proper phrase.\n\r", ch ); break; case 3 : send_to_char( "A twitch in your eye disrupts your concentration for a moment.\n\r", ch ); break; case 4 : send_to_char( "You get a mental block mid-way through the casting.\n\r", ch ); break; default: send_to_char( "You lost your concentration.\n\r", ch ); break; } } ch->mana -= mana / 2; } else { if (!IS_IMMORTAL(ch)) { ch->mana -= mana; } if (number_bits(1) == 0 && is_affected(ch, gsn_mana_shackles)) { switch (number_bits(2)) { case 0: act("Your magical shackles send searing lightning through you as you cast.", ch, NULL, NULL, TO_CHAR); act("$n's magical shackles send searing lightning through $m as $e casts.", ch, NULL, NULL, TO_ROOM); break; case 1: act("You reel in shock as your magical shackles claw into you as you cast.", ch, NULL, NULL, TO_CHAR); act("$n reels in shock as $s magical shackles claw into $m as $e casts.", ch, NULL, NULL, TO_ROOM); break; case 2: act("Your magical shackles shock you to the core as you cast.", ch, NULL, NULL, TO_CHAR); act("$n's magical shackles shock $m to the core as $e casts.", ch, NULL, NULL, TO_ROOM); break; case 3: act("You scream out in agony as your magical shackles shock you as you cast.", ch, NULL, NULL, TO_CHAR); act("$n screams out in agony as $s magical shackles shock $m as $e casts.", ch, NULL, NULL, TO_ROOM); break; } ch->hit -= number_range(mana*3, mana*6); } if (victim && victim != ch && !IS_NPC(victim) && target == TAR_CHAR_OFFENSIVE) { if (IS_AWAKE(victim) && number_percent() < learned(victim, gsn_lightning_reflexes) / 4) { switch (number_bits(2)) { case 0: act("You dive away from $n's $t with a lightning fast reflex.", ch, skill_table[sn].noun_damage, victim, TO_VICT); act("$N dives away from your $t with a lightning fast reflex.", ch, skill_table[sn].noun_damage, victim, TO_CHAR); break; case 1: act("You avoid $n's $t with a lightning fast side step.", ch, skill_table[sn].noun_damage, victim, TO_VICT); act("$N avoids your $t with a lightning fast side step.", ch, skill_table[sn].noun_damage, victim, TO_CHAR); break; case 2: act("You throw your body aside escaping from $n's $t.", ch, skill_table[sn].noun_damage, victim, TO_VICT); act("$N throws $S body aside escaping from your $t.", ch, skill_table[sn].noun_damage, victim, TO_CHAR); break; case 3: act("You deftly move aside watching $n's $t go past.", ch, skill_table[sn].noun_damage, victim, TO_VICT); act("$N deftly moves aside watching your $t go past.", ch, skill_table[sn].noun_damage, victim, TO_CHAR); break; } check_improve(victim, gsn_lightning_reflexes); pop_call(); return; } } if (victim && victim != ch && number_range(0, 4) == 0) { if (is_affected(victim, gsn_magic_mirror)) { act("White lightning surrounds you, reflecting $n's magic.", ch, NULL, victim, TO_VICT ); act("White lightning surrounds $N, reflecting your magic.", ch, NULL, victim, TO_CHAR ); act("White lightning surrounds $N, reflecting $n's magic.", ch, NULL, victim, TO_NOTVICT ); vo = (void *) ch; ch = victim; } } level = magic_modify(ch, victim, sn, level); (*skill_table[sn].spell_fun) (sn, level, ch, vo, target); check_improve(ch, sn); } if (target == TAR_CHAR_OFFENSIVE) { if (victim != ch && victim->fighting == NULL) { make_char_fight_char( ch, victim ); multi_hit( victim, ch, TYPE_UNDEFINED ); } } pop_call(); return; } /* 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; push_call("obj_cast_spell(%p,%p,%p,%p,%p)",sn,level,ch,victim,obj); if (sn <= 0) { pop_call(); return; } if (sn <= MAX_SKILL && skill_table[sn].slot == -1) { pop_call(); return; } if (is_safe_magic(ch, NULL, sn)) { pop_call(); return; } if (sn >= MAX_SKILL || skill_table[sn].spell_fun == 0) { if (obj != NULL) { log_printf("obj_cast_spell: Vnum %u bad sn %d.", obj->pIndexData->vnum, sn); } else { log_printf("Unknown item cast sn %d", sn); } pop_call(); return; } level = level * caster_levels(ch) / UMAX(1, ch->level); target = skill_table[sn].target; switch (target) { default: bug( "obj_cast_spell: bad target for sn %d.", sn ); pop_call(); return; case TAR_IGNORE: vo = NULL; break; case TAR_CHAR_OFFENSIVE: if (victim == ch || victim == NULL) { if (who_fighting(ch)) { victim = ch->fighting->who; } } if (victim == NULL) { send_to_char( "You can't do that.\n\r", ch ); pop_call(); return; } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_CHAR_DEFENSIVE: if (victim == NULL) { victim = ch; } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_CHAR_SELF: if (victim == NULL) { victim = ch; } vo = (void *) ch; break; case TAR_OBJ_INV: if (obj == NULL) { send_to_char( "You can't do that.\n\r", ch ); pop_call(); return; } vo = (void *) obj; break; case TAR_OBJ_CHAR_DEF: if (victim) { if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } target = TAR_CHAR_DEFENSIVE; vo = (void *) victim; } else { target = TAR_OBJ_INV; vo = (void *) obj; } break; case TAR_OBJ_CHAR_OFF: if (victim) { if (victim == ch && who_fighting(ch)) { victim = ch->fighting->who; } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } target = TAR_CHAR_OFFENSIVE; vo = (void *) victim; } else { target = TAR_OBJ_INV; vo = (void *) obj; } break; } target_name = ""; level = magic_modify(ch, victim, sn, level); (*skill_table[sn].spell_fun) ( sn, level, ch, vo, target ); if (target == TAR_CHAR_OFFENSIVE) { if (victim != ch && victim->fighting == NULL) { make_char_fight_char( ch, victim ); multi_hit( victim, ch, TYPE_UNDEFINED ); } } pop_call(); return; } /* Magical Totem casting spells on the room */ void totem_cast_spell( OBJ_DATA *obj ) { CHAR_DATA *totem, *rch, *rch_next; int sn, level, target; push_call("totem_cast_spell(%p)",obj); if (obj->in_room == NULL) { pop_call(); return; } if (obj->in_room->area->nplayer == 0) { pop_call(); return; } if ((totem = mob_index[MOB_VNUM_TOTEM]->first_instance) == NULL) { pop_call(); return; } target_name = ""; STRFREE(totem->short_descr); totem->short_descr = STRDUPE(obj->short_descr); char_to_room(totem, obj->in_room->vnum); act("The air thickens with magic as $n starts to hum.", totem, NULL, NULL, TO_ROOM); for (rch = obj->in_room->first_person ; rch ; rch = rch_next) { rch_next = rch->next_in_room; if (rch == totem) { continue; } if (IS_NPC(rch) && IS_AFFECTED(rch, AFF_ETHEREAL)) { continue; } if (is_affected(rch, gsn_anti_magic_shell)) { continue; } sn = obj->value[number_range(0,3)]; if (!is_spell(sn)) { continue; } level = obj->level; level = magic_modify(totem, rch, sn, level); target = skill_table[sn].target; switch (target) { case TAR_OBJ_CHAR_OFF: target = TAR_CHAR_OFFENSIVE; break; case TAR_OBJ_CHAR_DEF: target = TAR_CHAR_DEFENSIVE; break; } (*skill_table[sn].spell_fun) (sn, level, totem, rch, target); } char_to_room(totem, ROOM_VNUM_TOTEM); pop_call(); return; } /* Takes any offensive spell for a sorcerer and defensive spell for a shaman and applies it to all the appropriate char's. Costs more mana than the combined casts, but takes less time. */ void do_mass( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; CHAR_DATA *victim, *next_vict; int sn, sha_mlv, sor_mlv, level, mana, target; push_call("do_mass(%p,%p)",ch,argument); argument = one_argument( argument, arg1 ); if (arg1[0] == '\0') { send_to_char( "Cast which what where?\n\r", ch ); pop_call(); return; } if (!IS_NPC(ch) && multi(ch, gsn_mass) == -1) { send_to_char( "You can't do that!\n\r", ch ); pop_call(); return; } if (number_percent() > learned(ch, gsn_mass)) { send_to_char("You failed to enter the proper state of mind to amass that much energy!\n\r",ch); wait_state(ch, skill_table[gsn_mass].beats); pop_call(); return; } sn = skill_lookup( arg1 ); if (sn < 0 || !is_spell(sn)) { send_to_char( "That is not a spell.\n\r", ch ); if (!IS_NPC(ch) && ch->desc == NULL) { log_printf("[%u] massing unknown spell: %s", ch->pIndexData->vnum, arg1); } pop_call(); return; } if ((level = can_cast_spell(ch, sn)) == -1) { pop_call(); return; } sha_mlv = (IS_NPC(ch) || IS_IMMORTAL(ch)) ? 100 : ch->pcdata->mclass[CLASS_SHAMAN]; sor_mlv = (IS_NPC(ch) || IS_IMMORTAL(ch)) ? 100 : ch->pcdata->mclass[CLASS_SORCERER]; target = skill_table[sn].target; switch (target) { case TAR_CHAR_OFFENSIVE: case TAR_OBJ_CHAR_OFF: if (sor_mlv < skill_table[gsn_mass].skill_level[CLASS_SORCERER]) { send_to_char( "You don't have enough skill in the proper class!\n\r", ch ); pop_call(); return; } target = TAR_CHAR_OFFENSIVE; break; case TAR_CHAR_DEFENSIVE: case TAR_OBJ_CHAR_DEF: if (sha_mlv < skill_table[gsn_mass].skill_level[CLASS_SHAMAN]) { send_to_char( "You don't have enough skill in the proper class!\n\r", ch ); pop_call(); return; } target = TAR_CHAR_DEFENSIVE; break; default: send_to_char("You would kill yourself trying to amass that much energy!\n\r",ch); pop_call(); return; } if (is_safe_magic(ch, NULL, sn)) { pop_call(); return; } mana = get_mana(ch, sn) * 5 / 4; /* Locate targets. */ switch (target) { case TAR_CHAR_OFFENSIVE: send_to_char("You unleash your magic upon your foes!\n\r", ch); break; case TAR_CHAR_DEFENSIVE: send_to_char("You sent forth your magic to aid your group.\n\r", ch); break; } for (victim = ch->in_room->last_person ; victim ; victim = next_vict) { next_vict = victim->prev_in_room; switch (target) { case TAR_CHAR_OFFENSIVE: if (!can_mass_cast(ch, victim)) { continue; } if (!IS_IMMORTAL(ch) && ch->mana < mana) { act("You don't have enough mana for $N.", ch, NULL, victim, TO_CHAR); wait_state( ch, skill_table[sn].beats ); pop_call(); return; } if (!IS_IMMORTAL(ch) && number_percent() > learned(ch, sn)) { act("You lost your concentration on $N.", ch, NULL, victim, TO_CHAR); ch->mana -= mana / 2; continue; } if (!IS_IMMORTAL(ch)) { ch->mana -= mana; } level = magic_modify(ch, victim, sn, level); (*skill_table[sn].spell_fun) (sn, level, ch, victim, target); check_improve(ch, sn); if (victim != ch && victim->fighting == NULL) { make_char_fight_char( ch, victim ); multi_hit( victim, ch, TYPE_UNDEFINED ); } break; case TAR_CHAR_DEFENSIVE: if (!is_same_group(ch, victim)) { continue; } if (is_safe_magic(ch, victim, sn)) { continue; } if (!IS_IMMORTAL(ch) && ch->mana < mana) { act("You don't have enough mana for $N.",ch,NULL,victim,TO_CHAR); wait_state( ch, skill_table[sn].beats ); pop_call(); return; } if (!IS_IMMORTAL(ch) && number_percent() > learned(ch, sn)) { act("You lost your concentration on $N.",ch,NULL,victim,TO_CHAR); ch->mana -= mana / 2; continue; } if (!IS_IMMORTAL(ch)) { ch->mana -= mana; } level = magic_modify(ch, victim, sn, level); (*skill_table[sn].spell_fun) ( sn, level, ch, victim, target ); check_improve(ch, sn); break; } } if (IS_AFFECTED(ch, AFF2_QUICKEN)) { wait_state( ch, skill_table[sn].beats * 2 * 4 / 5); } else { wait_state( ch, skill_table[sn].beats * 2); } check_improve(ch, gsn_mass); pop_call(); return; } /* Finds target in adjusting room and casts the spell on it for double mana cost. */ void do_range_cast( CHAR_DATA *ch, char *argument ) { char *arg1,buf1[MAX_INPUT_LENGTH]; char *arg2,buf2[MAX_INPUT_LENGTH]; char *arg3,buf3[MAX_INPUT_LENGTH]; ROOM_INDEX_DATA *temp_room; EXIT_DATA *pexit; CHAR_DATA *victim, *next_victim; void *vo; int mana, sn, dir, level, target; long long actn; push_call("do_range_cast(%p,%p)",ch,argument); if (!IS_NPC(ch) && multi(ch, gsn_range_cast) == -1) { send_to_char("Better leave the envisioning to the rangecasters.\n\r", ch); pop_call(); return; } if (strlen( argument) > 120 ) { *(argument+120)='\0'; } target_name = one_argument( argument, buf1 ); target_name = one_argument( target_name, buf2 ); target_name = one_argument( target_name, buf3 ); /* Get proper room for given direction */ if ((dir = direction_door(buf1)) == -1) { if ((dir = direction_door(buf2)) == -1) { if ((dir = direction_door(buf3)) == -1) { send_to_char("Range cast which direction?\n\r",ch); pop_call(); return; } /* buf3 is direction */ arg1=buf1; arg2=buf2; arg3=buf3; } /* buf2 is direction */ arg1=buf1; arg2=buf3; arg3=buf2; } else { /* buf1 is direction */ arg1=buf2; arg2=buf3; arg3=buf1; } pexit = get_exit(ch->in_room->vnum, dir); if (pexit == NULL || room_index[pexit->to_room]->area != ch->in_room->area || IS_SET(ch->in_room->exit[dir]->exit_info, EX_CLOSED)) { send_to_char( "You can't range cast in that direction!\n\r", ch ); pop_call(); return; } for (victim = room_index[pexit->to_room]->first_person ; victim ; victim = victim->next_in_room) { if (IS_NPC(victim) && (victim->pIndexData->pShop != NULL)) { send_to_char( "You can't range cast into a shop!\n\r", ch ); pop_call(); return; } } if (arg1[0] == '\0') { send_to_char( "Cast which what where?\n\r", ch ); pop_call(); return; } sn = skill_lookup( arg1 ); if (sn < 0 || !is_spell(sn)) { if (!IS_NPC(ch) && ch->desc == NULL) { log_printf("[%u] rangecast unknown spell: %s", ch->pIndexData->vnum, arg1); } send_to_char( "That is not a spell.\n\r", ch ); pop_call(); return; } if ((level = can_cast_spell(ch, sn)) == -1) { pop_call(); return; } if (is_safe_magic(ch, NULL, sn)) { pop_call(); return; } target = skill_table[sn].target; switch (target) { case TAR_OBJ_CHAR_DEF: target = TAR_CHAR_DEFENSIVE; break; case TAR_OBJ_CHAR_OFF: target = TAR_CHAR_OFFENSIVE; break; } if (IS_SET(room_index[pexit->to_room]->room_flags, ROOM_SAFE) && (target != TAR_CHAR_DEFENSIVE)) { send_to_char( "You can't range cast in that direction!\n\r", ch ); pop_call(); return; } mana = 3 * get_mana(ch, sn); /* Locate targets. */ victim = NULL; vo = NULL; temp_room = ch->in_room; switch ( target ) { default: bug( "do_range_cast: bad target for sn %d.", sn ); pop_call(); return; case TAR_CHAR_SELF: case TAR_OBJ_INV: send_to_char("That type of target is not allowed at range.\n\r",ch); pop_call(); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if (arg2[0] == '\0') { send_to_char( "Range cast whom?\n\r", ch ); pop_call(); return; } ch->in_room = room_index[pexit->to_room]; if ((victim = get_char_room(ch, arg2)) == NULL) { send_to_char( "They aren't there.\n\r", ch ); ch->in_room = temp_room; pop_call(); return; } ch->in_room = temp_room; if (victim == ch) { send_to_char( "They aren't there.\n\r", ch ); pop_call(); return; } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; case TAR_CHAR_DEFENSIVE: if (arg2[0] == '\0') { send_to_char( "Range cast whom?\n\r", ch ); pop_call(); return; } ch->in_room = room_index[pexit->to_room]; if ((victim = get_char_room( ch, arg2 ) ) == NULL) { send_to_char( "They aren't there.\n\r", ch ); ch->in_room = temp_room; pop_call(); return; } ch->in_room = temp_room; if (victim == ch) { send_to_char( "They aren't there.\n\r", ch ); pop_call(); return; } if (is_safe_magic(ch, victim, sn)) { pop_call(); return; } vo = (void *) victim; break; } if (!IS_IMMORTAL(ch) && ch->mana < mana) { send_to_char( "You don't have enough mana.\n\r", ch ); pop_call(); return; } if (number_percent() > learned(ch, gsn_range_cast)) { send_to_char("You envisioned the area but failed to remain focussed.\n\r",ch); wait_state(ch, skill_table[sn].beats/2); pop_call(); return; } wait_state( ch, skill_table[sn].beats); send_to_char("You close your eyes, envision the area, and cast!\n\r",ch); if (!IS_IMMORTAL(ch) && number_percent() > learned(ch, sn)) { send_to_char( "You lost your concentration.\n\r", ch ); ch->mana -= mana / 2; pop_call(); return; } if (!IS_IMMORTAL(ch)) { ch->mana -= mana; } char_from_room(ch); char_to_room(ch, pexit->to_room); /* turn off autosac, autoloot */ actn = ch->act; REMOVE_BIT(ch->act, PLR_AUTOSAC|PLR_AUTOLOOT|PLR_AUTO_SPLIT); level = magic_modify(ch, victim, sn, level); (*skill_table[sn].spell_fun) ( sn, level, ch, vo, target ); check_improve(ch, sn); if (target == TAR_CHAR_OFFENSIVE) { make_char_fight_char( ch, victim ); } ch->act = actn; char_from_room(ch); char_to_room(ch, temp_room->vnum); /* Move some creatures into room of caster */ if (target == TAR_CHAR_DEFENSIVE) { pop_call(); return; } if (target == TAR_IGNORE) { if (skill_table[sn].minimum_position != POS_FIGHTING) { pop_call(); return; } } for (victim = room_index[pexit->to_room]->last_person ; victim ; victim = next_victim) { next_victim = victim->prev_in_room; if (victim->fighting != NULL && victim->fighting->who != ch) { continue; } if (victim->fighting == NULL && number_bits(2) != 0) { continue; } if (!IS_NPC(victim) || !IS_IMMORTAL(victim) || IS_AFFECTED(victim, AFF_ETHEREAL) || number_bits(3) == 0) { continue; } char_from_room(victim); char_to_room(victim, ch->in_room->vnum); act("$n arrives, glaring around angrily!", victim, NULL, NULL, TO_ROOM); if (!IS_NPC(ch) && victim->npcdata->pvnum_last_hit == ch->pcdata->pvnum) { make_char_fight_char( ch, victim ); multi_hit( victim, ch, TYPE_UNDEFINED ); } } pop_call(); return; } /* Returns -1 if one cannot cast the spell, otherwise it Returns the spell level - Scandum 01/04/2002 */ int can_cast_spell( CHAR_DATA *ch, int sn ) { int level; push_call("can_cast_spell(%p,%p)",ch,sn); if (IS_NPC(ch)) { level = UMAX(ch->level * 3 / 4, 1); pop_call(); return(level); } if (!IS_IMMORTAL(ch)) { if (!IS_SET(skill_table[sn].race, 1 << ch->race) && multi(ch, sn) == -1) { send_to_char( "You cannot cast that spell.\n\r", ch ); pop_call(); return(-1); } } if (IS_IMMORTAL(ch) || IS_SET(skill_table[sn].race, 1 << ch->race)) { level = ch->level; } else { level = multi_spell_level(ch, sn); level = level * ch->pcdata->learned[sn] / 100 + 1; } /* Added SFOL check and bonus based on int of caster, ranging from 103% to 139% for a 0 to 10 reinc lvl 95 human - Scandum 30-03-2002 */ if (IS_IMMORTAL(ch) || (skill_table[sn].follower == SFOL_NONE) || (skill_table[sn].follower & SFOL_ULMO && ch->pcdata->god == GOD_ULMO) || (skill_table[sn].follower & SFOL_DEMISE && ch->pcdata->god == GOD_DEMISE) || (skill_table[sn].follower & SFOL_GAIA && ch->pcdata->god == GOD_GAIA) || (skill_table[sn].follower & SFOL_ILUVATAR && ch->pcdata->god == GOD_ILUVATAR) || (skill_table[sn].follower & SFOL_HYPNOS && ch->pcdata->god == GOD_HYPNOS) || (skill_table[sn].follower & SFOL_MANWE && ch->pcdata->god == GOD_MANWE)) { if (get_curr_int(ch) > 28) { level = level * get_curr_int(ch) / 28; } } else { send_to_char( "You lack the skill with the elements to cast that spell.\n\r", ch ); pop_call(); return(-1); } pop_call(); return(level); } /* Returns TRUE and gives appropriate spams if one cannot cast a spell on the victim, if victim is NULL only room and ch based stuff is checked - Scandum 01-04-2002 */ bool is_safe_magic( CHAR_DATA *ch, CHAR_DATA *victim, int sn) { push_call("is_safe_magic(%p,%p)",ch,victim); if (is_affected(ch, gsn_anti_magic_shell)) { if ((victim && victim != ch) || skill_table[sn].target == TAR_IGNORE) { send_to_char("The flows of magic shatter against the shell surrounding you.\n\r", ch); pop_call(); return TRUE; } } if (find_keeper(ch) != NULL) { ch_printf(ch, "%s%s tells you 'No magic in here! You punk!'\n\r", get_color_string(ch,COLOR_SPEACH,VT102_BOLD), capitalize(find_keeper(ch)->short_descr)); pop_call(); return TRUE; } if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { if (skill_table[sn].target == TAR_IGNORE) { if (skill_table[sn].minimum_position == POS_FIGHTING) { send_to_char( "You cannot do that here.\n\r", ch); pop_call(); return TRUE; } } if (skill_table[sn].target == TAR_CHAR_OFFENSIVE || skill_table[sn].target == TAR_OBJ_CHAR_OFF) { send_to_char( "You cannot do that here.\n\r", ch); pop_call(); return TRUE; } } if (ch->position < skill_table[sn].minimum_position) { send_to_char( "You can't concentrate enough.\n\r", ch ); pop_call(); return TRUE; } if (victim == NULL) { pop_call(); return FALSE; } if (victim == ch) { pop_call(); return FALSE; } if (is_affected(victim, gsn_anti_magic_shell)) { act("The flows of magic shatter against the shell surrounding $N.", ch, NULL, victim, TO_CHAR); pop_call(); return TRUE; } if (ch->fighting != NULL && ch->fighting->who == victim) { pop_call(); return FALSE; } if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { pop_call(); return FALSE; } switch (skill_table[sn].target) { default: bug( "is_safe_magic: bad target for sn %d.", sn ); pop_call(); return TRUE; break; case TAR_CHAR_OFFENSIVE: case TAR_OBJ_CHAR_OFF: if (IS_NPC(ch) && ch->fighting == NULL && ch->hit < ch->max_hit / 2) { if (ch->desc == NULL) { pop_call(); return TRUE; } } if (ch->desc) { if (!IS_NPC(victim)) { send_to_char( "You must MURDER a player.\n\r", ch); pop_call(); return TRUE; } } if (!IS_NPC(ch)) { ch->pcdata->just_died_ctr = 0; } if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM) && victim->master != NULL) { if (victim->master == ch) { raw_kill( victim ); pop_call(); return TRUE; } } if (ch->fighting == NULL || ch->fighting->who != victim ) { if (!IS_NPC(ch) && IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM)) { send_to_char( "You cannot kill a slave.\n\r", ch); pop_call(); return TRUE; } } if (IS_NPC(victim) && victim->fighting != NULL && !IS_NPC(ch) && !is_same_group(ch, victim->fighting->who)) { ch_printf(ch, "%s seems to be busy!\n\r", capitalize(get_name(victim))); pop_call(); return TRUE; } if (check_recently_fought(ch, victim)) { ch_printf(ch, "%s was recently fought. Try later.\n\r", capitalize(get_name(victim))); pop_call(); return TRUE; } break; case TAR_CHAR_DEFENSIVE: case TAR_OBJ_CHAR_DEF: if (!IS_NPC(ch) && victim->fighting != NULL) { if (!IS_NPC(victim) && !IS_NPC(victim->fighting->who)) { ch_printf(ch ,"%s seems to be busy!\n\r", capitalize(get_name(victim))); pop_call(); return TRUE; } if (!is_same_group(ch, victim)) { ch_printf(ch ,"%s seems to be busy!\n\r", capitalize(get_name(victim))); pop_call(); return TRUE; } } break; } pop_call(); return FALSE; } /* true if victim is a legal target for a mass attack - Scandum 01/04/2002 */ bool can_mass_cast( CHAR_DATA *ch, CHAR_DATA *victim ) { push_call("can_mass_cast(%p,%p)",ch,victim); if (victim == ch) { pop_call(); return FALSE; } if (is_affected(victim, gsn_anti_magic_shell)) { act("The flows of magic shatter against a shell surrounding $N.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } if (victim->fighting && victim->fighting->who == ch) { pop_call(); return TRUE; } if (victim->fighting && !is_same_group(ch, victim->fighting->who)) { pop_call(); return FALSE; } if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_ETHEREAL)) { pop_call(); return FALSE; } if (is_same_group(ch, victim)) { pop_call(); return FALSE; } if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { pop_call(); return TRUE; } if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM)) { pop_call(); return FALSE; } if (!IS_NPC(ch) && !IS_NPC(victim)) { pop_call(); return FALSE; } if (IS_NPC(ch) && ch->desc && !IS_NPC(victim)) { pop_call(); return FALSE; } if (check_recently_fought(ch, victim)) { pop_call(); return FALSE; } pop_call(); return TRUE; } void do_mana( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; int sn; push_call("do_mana(%p,%p)",ch,argument); if (*argument == '\0') { send_to_char("Usage: mana <spell name>.\n\r", ch); pop_call(); return; } sn = skill_lookup( argument ); if (sn < 0 || !is_spell(sn)) { send_to_char( "That is not a spell.\n\r", ch ); pop_call(); return; } if ((can_cast_spell(ch, sn)) == -1) { pop_call(); return; } sprintf( buf, "Mana usage for '%s' is: %d\n\r", skill_table[sn].name, get_mana( ch, sn)); send_to_char( buf, ch); pop_call(); return; } int get_mana( CHAR_DATA *ch, int sn) { int mana,mnx,cnt; push_call("get_mana(%p,%p)",ch,sn); if (IS_NPC(ch) || IS_SET(skill_table[sn].race, 1 << ch->race)) { mana = skill_table[sn].min_mana; } else { cnt = multi(ch, sn); mnx = skill_table[sn].skill_level[cnt] / 2 + 1; mana = 50 * mnx / (ch->pcdata->mclass[cnt] + mnx - skill_table[sn].skill_level[cnt]) - (get_curr_wis(ch)-13) / 2; mana = UMAX(skill_table[sn].min_mana, mana); } if (IS_AFFECTED(ch, AFF2_QUICKEN)) { mana += mana; } pop_call(); return(mana); } void do_move( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; int sn, cnt, move; push_call("do_move(%p,%p)",ch,argument); sn = skill_lookup( argument ); if( sn < 0 || is_spell(sn)) { send_to_char( "That doesn't cost any movement.\n\r", ch ); pop_call(); return; } cnt = multi( ch, sn); if(cnt==-1 && !IS_NPC(ch)) { send_to_char( "You can't do that.\n\r", ch ); pop_call(); return; } move = IS_NPC(ch) ? 0 : skill_table[sn].min_mana; sprintf(buf,"Movement usage for '%s' is: %d\n\r",skill_table[sn].name,move); send_to_char(buf,ch); pop_call(); return; } bool is_spell(int sn) { push_call("is_spell(%p)",sn); if (sn > 0 && sn < MAX_SKILL && IS_SET(skill_table[sn].flags, FSKILL_SPELL)) { pop_call(); return TRUE; } pop_call(); return FALSE; } int caster_levels( CHAR_DATA *ch ) { int levels; push_call("caster_levels(%p)",ch); if (IS_NPC(ch)) { pop_call(); return( ch->level ); } levels = ch->pcdata->mclass[ CLASS_DRUID ]; levels += ch->pcdata->mclass[ CLASS_SORCERER ]; levels += ch->pcdata->mclass[ CLASS_SHAMAN ]; levels += ch->pcdata->mclass[ CLASS_WARLOCK ]; /* Non specialist caster-levels count only half 21/10/2000 - Manwe */ levels += ch->pcdata->mclass[ CLASS_WARRIOR ] / 2; levels += ch->pcdata->mclass[ CLASS_MARAUDER ] / 2; levels += ch->pcdata->mclass[ CLASS_GLADIATOR ] / 2; levels += ch->pcdata->mclass[ CLASS_NINJA ] / 2; if (levels > ch->level) { levels = ch->level; } pop_call(); return( levels ); } int magic_modify( CHAR_DATA *ch, CHAR_DATA *victim, int sn, int level ) { int dam_type = DAM_THRUST; push_call("damage_modify(%p,%p,%p,%p)",ch,victim,sn,level); if (level <= 0) { pop_call(); return 0; } if (victim == NULL) { pop_call(); return level; } switch (skill_table[sn].target) { case TAR_CHAR_DEFENSIVE: case TAR_OBJ_CHAR_DEF: if (!IS_IMMORTAL(ch) && victim != ch) { if (level > victim->level * 2) { level = victim->level * 2; } } break; } dam_type = skill_table[sn].dam_type; if (dam_type == DAM_NONE) { pop_call(); return level; } if (dam_type == god_table[which_god(victim)].resistance) { level = level * 75 / 100; } if (IS_UNDEAD(victim)) { if (IS_SET(DAM_LIFE|DAM_POISON|DAM_EVIL, dam_type)) { level = level * 75 / 100; } } if (IS_SET(race_table[victim->race].res_low, dam_type)) { level = level * 90 / 100; } if (IS_SET(race_table[victim->race].res_high, dam_type)) { level = level * 80 / 100; } if (IS_SET(race_table[victim->race].vul_low, dam_type)) { level = level * 110 / 100; } if (IS_SET(race_table[victim->race].vul_high, dam_type)) { level = level * 120 / 100; } level = UMAX(1, level); pop_call(); return level; } int multi_spell_level( CHAR_DATA *ch, int sn) { int cnt, mlv; push_call("multi_spell_level(%p,%p)",ch,sn); mlv = 0; if (IS_NPC(ch)) { mlv = ch->level; pop_call(); return(mlv); } for (cnt = 0 ; cnt < MAX_CLASS ; cnt++) { if (skill_table[sn].skill_level[cnt] < MAX_LEVEL) { mlv += ch->pcdata->mclass[cnt]; } else if (cnt >= 4) { mlv += ch->pcdata->mclass[cnt] * 3 / 4; } else { mlv += ch->pcdata->mclass[cnt] * 1 / 4; } } if (mlv > ch->level) { mlv = ch->level; } if (ch->race == RACE_HUMAN) { mlv += ch->pcdata->reincarnation; } pop_call(); return(mlv); } ROOM_INDEX_DATA *get_rift_room( CHAR_DATA *ch, int rift_number) { ROOM_INDEX_DATA *rift_room; push_call("get_rift_room(%p,%p)",ch,rift_number); srand(value + ch->pcdata->pvnum + 1); while (TRUE) { rift_room = get_room_index(rand() % 20000); if (rift_room == NULL) { continue; } if (IS_SET(rift_room->room_flags, ROOM_SAFE)) { continue; } if (IS_SET(rift_room->room_flags, ROOM_IS_CASTLE)) { continue; } if (IS_SET(rift_room->room_flags, ROOM_PET_SHOP)) { continue; } if (IS_SET(rift_room->room_flags, ROOM_PRIVATE)) { continue; } if (IS_SET(rift_room->room_flags, ROOM_SOLITARY)) { continue; } if (IS_SET(rift_room->room_flags, ROOM_NO_RECALL)) { continue; } if (rift_room->sector_type == SECT_ETHEREAL) { continue; } if (rift_room->sector_type == SECT_ASTRAL) { continue; } if (IS_SET(rift_room->area->flags, AFLAG_NOTELEPORT)) { continue; } if (IS_SET(rift_room->area->flags, AFLAG_NORECALL)) { continue; } if (IS_SET(rift_room->area->flags, AFLAG_NORIP)) { continue; } if (!IS_IMMORTAL(ch)) { if (ch->level < rift_room->area->low_hard_range) { continue; } if (ch->level > rift_room->area->hi_hard_range) { continue; } } break; } pop_call(); return rift_room; } /* Spell functions. */ DO_SPELL(spell_acid_blast) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_acid_blast(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*3+50, level*5+100); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_armor) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_armor(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; if (!IS_NPC(ch) && ch->pcdata->mclass[CLASS_DRUID] > 0) { af.duration = 48; af.modifier = -15; } else { af.duration = 24; af.modifier = -5; } af.location = APPLY_AC; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n's armor begins to glow softly as it is enhanced by a cantrip.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your armor begins to glow softly as it is enhanced by a cantrip.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_bless) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_bless(%p,%p,%p,%p)",sn,level,ch,vo); if( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = 6+level/2; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.location = APPLY_HITROLL; af.modifier = level/9; affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = 0 - level / 8; affect_to_char( victim, &af ); act( "A powerful blessing is laid upon $n.", victim, NULL, NULL, TO_ROOM ); send_to_char( "A powerful blessing is laid upon you.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_blindness) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_blindness(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_BLIND) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } if (IS_AFFECTED(victim, AFF_TRUESIGHT )) { act( "$N sees through the veil on reality you try to impose.", ch, NULL, victim, TO_CHAR ); act( "You see through the veil on reality $n attempts to impose.", ch, NULL, victim, TO_VICT ); pop_call(); return; } if ( saves_spell( level, ch, victim ) ) { send_to_char( "Nothing happens.\n\r", ch ); pop_call(); return; } af.type = sn; af.location = APPLY_HITROLL; af.modifier = -2*level/5; af.duration = 1+level/5; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_BLIND; affect_to_char( victim, &af ); send_to_char( "You are blinded!\n\r", victim ); if ( ch != victim ) { send_to_char( "Your foe is now blinded.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_burning_hands) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_burning_hands(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range( level+50, level+100 ); if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_call_lightning) { CHAR_DATA *vch, *vch_next; int dam, door, temp_vnum; EXIT_DATA *pexit; push_call("spell_call_lightning(%p,%p,%p,%p)",sn,level,ch,vo); if ( !IS_OUTSIDE(ch) ) { send_to_char( "You must be out of doors.\n\r", ch ); pop_call(); return; } if (NO_WEATHER_SECT(ch->in_room->sector_type)) { send_to_char( "You must be out of doors.\n\r", ch ); pop_call(); return; } if ( ch->in_room->area->weather_info->sky < SKY_RAINING ) { send_to_char( "You need bad weather.\n\r", ch ); pop_call(); return; } send_to_char( "Elemental lightning strikes your foes!\n\r", ch ); act( "$n calls elemental lightning to strike $s foes!", ch, NULL, NULL, TO_ROOM ); for (vch = ch->in_room->last_person ; vch ; vch = vch_next) { vch_next = vch->prev_in_room; if (!can_mass_cast(ch, vch)) { continue; } dam = number_range(level*1, level*4); damage( ch, vch, saves_spell(level, ch, vch) ? dam/2 : dam, sn ); } temp_vnum = ch->in_room->vnum; for (door = 0 ; door < 6 ; door++) { if ((pexit = get_exit(temp_vnum, door)) && pexit->to_room != temp_vnum) { ch->in_room = room_index[pexit->to_room]; act("Lightning flashes in the sky.", ch, NULL, NULL, TO_ROOM ); } } ch->in_room = room_index[temp_vnum]; pop_call(); return; } DO_SPELL(spell_chain_lightning) { CHAR_DATA *vch, *vch_next; ROOM_INDEX_DATA *temp_room = ch->in_room; int dam, targets; push_call("spell_chain_lightning(%p,%p,%p,%p)",sn,level,ch,vo); if (!IS_OUTSIDE(ch) || NO_WEATHER_SECT(ch->in_room->sector_type)) { send_to_char( "You must be out of doors.\n\r", ch ); pop_call(); return; } if (ch->in_room->area->weather_info->sky < SKY_RAINING) { level = level * 2 / 3; } if (ch->in_room->area->weather_info->sky < SKY_LIGHTNING) { level = level * 2 / 3; } act( "You call forth a bolt of chain lightning!", ch, NULL, NULL, TO_CHAR ); act( "$n calls forth a bolt of chain lightning!", ch, NULL, NULL, TO_ROOM ); while (level > 0) { for (targets = 0, vch = ch->in_room->last_person ; vch ; vch = vch_next) { vch_next = vch->prev_in_room; if (!can_mass_cast(ch, vch)) { continue; } dam = saves_spell(level, ch, vch) ? dice(level, 3) : dice(level, 6); level -= 20; targets += 1; switch (number_bits(2)) { case 0: act("The searing bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The searing bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; case 1: act("The sizzling bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The sizzling bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; case 2: act("The crackling bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The crackling bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; case 3: act("The fiery bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The fiery bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; } damage( ch, vch, dam, sn ); if (level <= 0) { break; } } if (level > 0) { if (targets == 1) { vch = ch; dam = saves_spell(level, ch, vch) ? dice(level, 6) : dice(level, 3); level -= 20; switch (number_bits(2)) { case 0: act("The searing bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The searing bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; case 1: act("The sizzling bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The sizzling bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; case 2: act("The crackling bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The crackling bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; case 3: act("The fiery bolt of chain lightning arcs to you.", vch, NULL, NULL, TO_CHAR); act("The fiery bolt of chain lightning arcs to $n.", vch, NULL, NULL, TO_ROOM); break; } damage( ch, vch, dam, sn ); } if (ch->in_room != temp_room) { send_to_room("The bolt of chain lightning loses power and fizzles out.\n\r", temp_room); pop_call(); return; } if (targets == 0) { act("You catch the bolt of lightning and send it back into the sky.", ch, NULL, NULL, TO_CHAR); act("$n catches the bolt of lightning and sends it back into the sky.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } } } switch (number_bits(2)) { case 0: send_to_room("The searing bolt of chain lightning loses power and fizzles out.\n\r", temp_room); break; case 1: send_to_room("The sizzling bolt of chain lightning arcs to the ground and dissipates.\n\r", temp_room); break; case 2: send_to_room("The crackling arc of chain lightning strikes the ground and vanishes.\n\r", temp_room); break; case 3: send_to_room("The fiery bolt of chain lightning loses power before reaching its target.\n\r", temp_room); break; } pop_call(); return; } DO_SPELL(spell_cause_light) { push_call("spell_cause_light(%p,%p,%p,%p)",sn,level,ch,vo); damage( ch, (CHAR_DATA *) vo, dice(1, 15) + level / 2, sn ); pop_call(); return; } DO_SPELL(spell_cause_serious) { push_call("spell_cause_serious(%p,%p,%p,%p)",sn,level,ch,vo); damage( ch, (CHAR_DATA *) vo, dice(1, 25) + level * 2 / 3, sn ); pop_call(); return; } DO_SPELL(spell_cause_critical) { push_call("spell_cause_critical(%p,%p,%p,%p)",sn,level,ch,vo); damage( ch, (CHAR_DATA *) vo, dice(1, 50) + level, sn ); pop_call(); return; } DO_SPELL(spell_change_sex) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_change_sex(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char("You are forbidden from casting that here.\n\r", ch); pop_call(); return; } if ( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/4; af.location = APPLY_SEX; if (victim->sex <= 0) { if (number_bits(1) == 0) { af.modifier = 1; } else { af.modifier = 2; } } else if (victim->sex == 1) { if (number_bits(1) == 0) { af.modifier = 1; } else { af.modifier = -1; } } else if (victim->sex >= 2) { if (number_bits(1) == 0) { af.modifier = -1; } else { af.modifier = -2; } } af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "You writhe in agony as your gender changes.\n\r", victim ); act( "$n writhes in agony as $s gender changes.", victim, NULL, NULL, TO_ROOM); pop_call(); return; } DO_SPELL(spell_charm_person) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_charm_person(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char("You are forbidden from casting that here.\n\r", ch); pop_call(); return; } if (victim == ch) { send_to_char( "You like yourself even better!\n\r", ch ); pop_call(); return; } if (!IS_NPC(victim) || !can_mass_cast(ch, victim)) { send_to_char( "They seem to be unaffected by your magic.\n\r", ch ); pop_call(); return; } if (IS_AFFECTED(victim, AFF_CHARM)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } if (level/3 < victim->level || saves_spell(level, ch, victim) || get_pets(ch) >= 2) { do_say(victim, "I don't want to be charmed!"); act( "$n suddenly looks VERY angry!",victim,NULL,NULL,TO_ROOM); if (victim->fighting == NULL) { make_char_fight_char( ch, victim ); multi_hit(victim, ch, TYPE_UNDEFINED); } pop_call(); return; } if ( victim->master ) { stop_follower( victim ); } add_follower( victim, ch ); af.type = sn; af.duration = number_fuzzy( level / 4 ); af.location = 0; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_CHARM; affect_to_char( victim, &af ); act( "Isn't $n just so nice?", ch, NULL, victim, TO_VICT ); act( "$N looks at you with adoring eyes.", ch, NULL, victim, TO_CHAR ); act( "$N looks at $n with adoring eyes.", ch, NULL, victim, TO_NOTVICT ); pop_call(); return; } DO_SPELL(spell_chill_touch) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_chill_touch(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level+10, level+130); if (saves_spell(level, ch, victim)) { dam /= 2; } else if (number_bits(1) == 0) { AFFECT_DATA af; af.type = sn; af.duration = 1; if (!IS_NPC(victim)) { af.location = APPLY_STR; } else { af.location = APPLY_DAMROLL; } af.modifier = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_join( victim, &af ); } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_stone_fist) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; int body_part = 0; push_call("spell_stone_fist(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; if (which_god(victim) == GOD_GAIA) { af.duration = 24; } else { af.duration = 8; } af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); if (IS_NPC(victim) && IS_SET(victim->act, ACT_BODY)) { body_part = victim->pIndexData->attack_parts; } else if (!IS_NPC(victim) || IS_SET(victim->act, ACT_RACE)) { body_part = race_table[victim->race].attack_parts; } if (IS_SET(body_part, BODY_TENTACLE)) { act( "$n's tentacles turn to stone.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your tentacles turn to stone.\n\r", victim ); } else if (IS_SET(body_part, BODY_CLAW)) { act( "$n's claws turn to stone.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your claws turn to stone.\n\r", victim ); } else if (IS_SET(body_part, BODY_BRANCH)) { act( "$n's branches turn to stone.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your branches turn to stone.\n\r", victim ); } else { act( "$n's fists turn to stone.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your fists turn to stone.\n\r", victim ); } pop_call(); return; } DO_SPELL(spell_color_spray) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_color_spray)",sn,level,ch,vo); dam = number_range( level*3+30, level*5+40 ); if ( saves_spell( level, ch, victim ) ) { damage( ch, victim, dam/2, sn); } else { /* Added blindness as an extra effect to this spell, 21/10/2000 - Manwe Lets not make it too easy pls, merged the two spells into one 01/04/2002 - Scandum */ damage( ch, victim, dam, sn ); if (ch->in_room == victim->in_room && number_bits(3) == 0 && !IS_AFFECTED(victim, AFF_BLIND)) { AFFECT_DATA af; af.type = gsn_blindness; af.location = APPLY_HITROLL; af.modifier = -1*level/5; af.duration = level/10; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_BLIND; affect_to_char( victim, &af ); send_to_char( "You are blinded by a dazzling ray of light!\n\r", victim ); if (ch != victim) { send_to_char( "A dazzling ray of light blinds your foe.\n\r", ch ); } } } pop_call(); return; } DO_SPELL(spell_continual_light) { OBJ_DATA *light; push_call("spell_continual_light(%p,%p,%p,%p)",sn,level,ch,vo); light = create_object( get_obj_index( OBJ_VNUM_LIGHT_BALL ), 0 ); light->timer = level / 2; light->level = level; act( "Shards of iridescent light collide to form a dazzling ball.", ch, NULL, NULL, TO_CHAR ); act( "Shards of iridescent light collide to form a dazzling ball.", ch, NULL, NULL, TO_ROOM ); obj_to_room( light, ch->in_room->vnum ); pop_call(); return; } DO_SPELL(spell_control_weather) { push_call("spell_control_weather(%p,%p,%p,%p)",sn,level,ch,vo); if (!strcasecmp(target_name, "wet")) { ch->in_room->area->weather_info->change += 1 + level / 33; } else if (!strcasecmp(target_name, "dry")) { ch->in_room->area->weather_info->change -= 1 + level / 33; } else if (!strcasecmp(target_name, "windy")) { ch->in_room->area->weather_info->wind_speed += 1 + level / 33; } else if (!strcasecmp(target_name, "calm")) { ch->in_room->area->weather_info->wind_speed -= 1 + level / 33; } else { send_to_char ("Do you want the weather calm, windy, wet, or dry?\n\r", ch ); pop_call(); return; } send_to_char( "Ok.\n\r", ch ); pop_call(); return; } DO_SPELL(spell_feast) { CHAR_DATA *fch; push_call("spell_feast(%p,%p,%p,%p)",sn,level,ch,vo); /* Added blood feast for undead and vampiric races - Scandum 01/04/2002 */ if (rspec_req(ch, RSPEC_VAMPIRIC) || rspec_req(ch, RSPEC_UNDEAD)) { act( "$n spreads $s arms and blood spurts forth from $s opened hands.", ch, NULL, NULL, TO_ROOM ); act( "You spread your arms and blood spurts forth from your opened hands.", ch, NULL, NULL, TO_CHAR ); act( "Everyone in the room joins you as you drink your fill.", ch, NULL, NULL, TO_CHAR ); gain_condition( ch, COND_FULL, 50 ); gain_condition( ch, COND_THIRST, 50 ); for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (!IS_NPC(fch) && fch->position >= POS_RESTING && fch != ch) { if (!rspec_req(fch,RSPEC_VAMPIRIC) && !rspec_req(fch,RSPEC_UNDEAD)) { send_to_char( "You turn away your head in dismay as the undeads drink.\n\r", fch ); } else { gain_condition( fch, COND_FULL, 50 ); gain_condition( fch, COND_THIRST, 50 ); send_to_char( "You join in the blood feast and drink your fill.\n\r", fch ); } } } } else { act( "$n creates a large selection of food and drinks.", ch, NULL, NULL, TO_ROOM ); act( "You create a large selection of food and drinks.", ch, NULL, NULL, TO_CHAR ); act( "Everyone in the room joins you as you eat your fill.", ch, NULL, NULL, TO_CHAR ); gain_condition( ch, COND_FULL, 50 ); gain_condition( ch, COND_THIRST, 50 ); for (fch = ch->in_room->first_person ; fch ; fch = fch->next_in_room) { if (!IS_NPC(fch) && fch->position >= POS_RESTING && fch != ch) { if (!rspec_req(fch,RSPEC_VAMPIRIC) && !rspec_req(fch,RSPEC_UNDEAD)) { gain_condition( fch, COND_FULL, 50 ); gain_condition( fch, COND_THIRST, 50 ); send_to_char( "You join in the feast and eat your fill.\n\r", fch ); } else { send_to_char( "You turn away your head in dismay as the mortals eat.\n\r", fch ); } } } } pop_call(); return; } DO_SPELL(spell_restore) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal, scale_top, scale_bot; char buf[MAX_INPUT_LENGTH]; push_call("spell_restore(%p,%p,%p,%p)",sn,level,ch,vo); scale_top = 10; /* The fraction for the hp/mana ratio */ scale_bot = 7; if (value == -1 || value > ch->mana ) { value = ch->mana; } heal = value * scale_top / scale_bot ; if (victim->hit + heal > victim->max_hit) { heal = victim->max_hit - victim->hit ; } value = heal * scale_bot / scale_top; sprintf( buf, "Restoring %d hitpoints for %d mana.\n\r", heal, value + get_mana(ch,sn)); send_to_char( buf, ch); victim->hit += heal; ch->mana -= value; update_pos( victim ); send_to_char( "You are filled with an overwhelming feeling of warmth.\n\r", victim ); affect_strip(victim, gsn_critical_hit); if ( ch != victim ) { send_to_char( "You restore them.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_energy_shift) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal, scale_top, scale_bot; char buf[MAX_INPUT_LENGTH]; push_call("spell_energy_shift(%p,%p,%p,%p)",sn,level,ch,vo); scale_top = 65; /* The fraction for the mana_to/mana_from ratio */ scale_bot = 100; if( value == -1 || value > ch->mana ) { value = ch->mana; } heal = value * scale_top / scale_bot ; if( victim->mana + heal > victim->max_mana ) { heal = victim->max_mana - victim->mana ; } value = ( heal * scale_bot / scale_top ); sprintf( buf, "Shifting %d mana for %d mana.\n\r", heal, value + get_mana(ch,sn)); send_to_char( buf, ch); victim->mana += heal; ch->mana -= value; update_pos( victim ); send_to_char( "You feel a surge of power.\n\r", victim ); if ( ch != victim ) { send_to_char( "You transfer energy to them.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_induction) { int heal, scale_top, scale_bot; char buf[MAX_INPUT_LENGTH]; push_call("spell_induction(%p,%p,%p,%p)",sn,level,ch,vo); scale_top = 7; /* The fraction for the mana_to/hp_from ratio */ scale_bot = 10; if (value < 0 || value > ch->hit - 10 ) { value = ch->hit-10; } heal = value * scale_top / scale_bot; if (ch->mana + heal > ch->max_mana) { heal = ch->max_mana - ch->mana ; } if (heal < 0) { heal = 0; } value = heal * scale_bot / scale_top; sprintf( buf, "Inducing %d mana points for %d hitpoints.\n\r", heal, value ); send_to_char( buf, ch); ch->mana += heal; ch->hit -= value; update_pos( ch ); if (heal > 0) { send_to_char( "You feel a surge of power.\n\r", ch ); act( "$n drains $s strength to further $s magic.", ch, NULL, NULL, TO_ROOM); } pop_call(); return; } DO_SPELL(spell_create_food) { OBJ_DATA *mushroom; push_call("spell_create_food(%p,%p,%p,%p)",sn,level,ch,vo); mushroom = create_object( get_obj_index( OBJ_VNUM_MUSHROOM ), 0 ); mushroom->value[0] = 5 + level; act( "$p suddenly appears.", ch, mushroom, NULL, TO_ROOM ); act( "$p suddenly appears.", ch, mushroom, NULL, TO_CHAR ); obj_to_room( mushroom, ch->in_room->vnum ); pop_call(); return; } DO_SPELL(spell_create_spring) { OBJ_DATA *spring; push_call("spell_create_spring(%p,%p,%p,%p)",sn,level,ch,vo); spring = create_object( get_obj_index( OBJ_VNUM_SPRING ), 0 ); spring->timer = level; act( "Tracing a ring before you, the graceful flow of a mystical spring emerges.", ch, spring, NULL, TO_CHAR ); act( "As $n traces a ring through the air, the graceful flow of a mystical spring emerges.", ch, spring, NULL, TO_ROOM ); obj_to_room( spring, ch->in_room->vnum ); pop_call(); return; } DO_SPELL(spell_ice_arrow) { OBJ_DATA *arrow; int type; push_call("spell_ice_arrow(%p,%p,%p,%p)",sn,level,ch,vo); if ((type = get_flag(target_name, bow_types)) == -1) { ch_printf(ch, "Create what kind of arrow, %s?\n\r", give_flags(bow_types)); pop_call(); return; } arrow = create_object(get_obj_index(OBJ_VNUM_ICE_ARROW), 0); arrow->value[0] = type; arrow->value[1] = level; arrow->value[2] = URANGE(10, level/4, 20); arrow->value[3] = 5; arrow->level = level / 2; SET_BIT(arrow->extra_flags, ITEM_MODIFIED); act("$p of frigid, dangerous beauty takes shape in your hand.", ch, arrow, NULL, TO_CHAR); act("$p of frigid, dangerous beauty takes shape in $n's hand.", ch, arrow, NULL, TO_ROOM); if (ch->carry_number < can_carry_n(ch) && ch->carry_weight < can_carry_w(ch)) { obj_to_char(arrow, ch); } else { obj_to_room(arrow, ch->in_room->vnum); } pop_call(); return; } DO_SPELL(spell_cure_blindness) { CHAR_DATA *victim = (CHAR_DATA *) vo; push_call("spell_cure_blindness(%p,%p,%p,%p)",sn,level,ch,vo); if (!is_affected(victim, gsn_blindness)) { if (!is_affected(victim, gsn_gouge)) { if (!is_affected(victim, gsn_flash_powder)) { send_to_char( "They aren't blinded.\n\r", ch ); pop_call(); return; } } } affect_strip( victim, gsn_blindness ); affect_strip( victim, gsn_gouge ); affect_strip( victim, gsn_flash_powder ); send_to_char( "Your vision returns!\n\r", victim ); if (ch != victim) { send_to_char( "They are no longer blinded.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_cure_light) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; push_call("spell_cure_light(%p,%p,%p,%p)",sn,level,ch,vo); heal = dice(1, 15) + level / 2; victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); send_to_char( "Your light wounds mend and your pain ebbs slightly.\n\r", victim ); if (ch != victim) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_cure_serious) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; push_call("spell_cure_serious(%p,%p,%p,%p)",sn,level,ch,vo); heal = dice(1, 25) + level * 2 / 3 ; victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); send_to_char( "Your serious wounds mend and your pain ebbs away.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_cure_critical) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; push_call("spell_cure_critical(%p,%p,%p,%p)",sn,level,ch,vo); heal = dice(1, 50) + level; victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); send_to_char( "Your critical wounds close and your pain ebbs away.\n\r", victim ); affect_strip(victim,gsn_critical_hit); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_cure_poison) { CHAR_DATA *victim = (CHAR_DATA *) vo; bool cured = FALSE; push_call("spell_cure_poison(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, gsn_poison ) ) { affect_strip( victim, gsn_poison ); cured = TRUE; } if (victim->poison != NULL) { POISON_DATA *npd, *pd; cured = TRUE; pd = victim->poison; victim->poison = NULL; while (pd != NULL) { npd = pd->next; FREEMEM( pd ); pd = npd; } } if ( cured ) { act( "$N looks better.", ch, NULL, victim, TO_CHAR ); act( "$N looks better.", ch, NULL, victim, TO_ROOM ); send_to_char( "A warm feeling runs through your body.\n\r", victim ); } else { act( "$N does not seem to be poisoned.", ch, NULL, victim, TO_CHAR ); } pop_call(); return; } DO_SPELL(spell_curse) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_curse(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_CURSE) ) { send_to_char( "They are already cursed.\n\r", ch ); pop_call(); return; } if ( saves_spell( level, ch, victim ) ) { send_to_char( "Your curse did not strike them.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/15; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_CURSE; af.location = APPLY_SAVING_SPELL; af.modifier = UMAX(level/20, 3); affect_to_char( victim, &af ); af.location = APPLY_HITROLL; af.modifier = UMIN(level/-10, -6); affect_to_char( victim, &af ); send_to_char( "You feel unclean.\n\r", victim ); if ( ch != victim ) { send_to_char( "Your foe is now cursed.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_detect_evil) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_detect_evil(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "Traces of red outline all evil in plain sight.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_detect_hidden) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_detect_hidden(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF_DETECT_HIDDEN) || IS_AFFECTED(victim, AFF_TRUESIGHT)) { send_to_char( "You are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_DETECT_HIDDEN; affect_to_char( victim, &af ); send_to_char( "Your senses are heightened to those of an animal.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_detect_invis) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_detect_invis(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF_DETECT_INVIS) || IS_AFFECTED(victim, AFF_TRUESIGHT)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_DETECT_INVIS; affect_to_char( victim, &af ); send_to_char( "Your eyes fixate as they gain the ability to see the unseen.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_detect_poison) { OBJ_DATA *obj = (OBJ_DATA *) vo; push_call("spell_detect_poison(%p,%p,%p,%p)",sn,level,ch,vo); if ( obj->item_type == ITEM_DRINK_CON || obj->item_type == ITEM_FOOD ) { if ( obj->value[3] != 0 ) { send_to_char( "You smell poisonous fumes.\n\r", ch ); } else { send_to_char( "It looks very delicious.\n\r", ch ); } } else { send_to_char( "It doesn't look poisoned.\n\r", ch ); } pop_call(); return; } /* Changed dispel spells slightly, you now damage the victim and make it gain or lose alignment, when the victim hits neutral alignment their gear will be checked for zappers - Scandum 01/04/2002 */ DO_SPELL(spell_dispel_evil) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_dispel_evil(%p,%p,%p,%p)",sn,level,ch,vo); if (!IS_NPC(ch) && IS_EVIL(ch)) { victim = ch; } if (!IS_EVIL(victim)) { act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } dam = number_range(level, level * 5); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } damage( ch, victim, dam, sn ); victim->alignment += 5; if (IS_NEUTRAL(victim)) { check_zap(victim, TRUE); } pop_call(); return; } DO_SPELL(spell_dispel_good) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_dispel_good(%p,%p,%p,%p)",sn,level,ch,vo); if (!IS_NPC(ch) && IS_GOOD(ch)) { victim = ch; } if (!IS_GOOD(victim)) { act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } dam = number_range (level, level * 5); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } damage( ch, victim, dam, sn ); victim->alignment -= 5; if (IS_NEUTRAL(victim)) { check_zap(victim, TRUE); } pop_call(); return; } DO_SPELL(spell_dispel_undead) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_dispel_undead(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_NPC(victim) && !IS_SET(victim->act , ACT_UNDEAD)) { if (!rspec_req(victim, RSPEC_UNDEAD)) { act( "$N is not affected.", ch, NULL, victim, TO_CHAR); pop_call(); return; } } dam = number_range(level*3, level*9); if ( saves_spell( level/2, ch, victim ) ) { dam /= 3; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_dispel_magic) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf, *paf_prev; int paf_type; push_call("spell_dispel_magic(%p,%p,%p,%p)",sn,level,ch,vo); if (target == TAR_CHAR_DEFENSIVE) { if (saves_spell(level, ch, victim)) { send_to_char( "You failed.\n\r", ch ); pop_call(); return; } for (paf_type = 0, paf = victim->last_affect ; paf ; paf = paf_prev) { paf_prev = paf->prev; if (!is_spell(paf->type)) { continue; } switch (paf->bitvector) { case AFF2_POSSESS: case AFF_CHARM: continue; } if (paf_type && paf->type != paf_type) { continue; } if (paf_type == 0 && paf->duration >= 0) { if (skill_table[paf->type].msg_off) { act(skill_table[paf->type].msg_off, victim, NULL, NULL, TO_CHAR); } } paf_type = paf->type; affect_from_char(victim, paf); } if (paf_type == 0) { send_to_char( "Nothing appears to happen.\n\r", ch ); } else if (victim != ch) { send_to_char( "Their magic spells seem to vanish slowly.\n\r", ch ); } } else { for (paf_type = 0, paf = obj->last_affect ; paf ; paf = paf_prev) { paf_prev = paf->prev; if (!is_spell(paf->type)) { continue; } if (paf_type && paf->type != paf_type) { continue; } if (paf_type == 0 && paf->duration >= 0) { if (skill_table[paf->type].msg_obj_off) { act(skill_table[paf->type].msg_obj_off, ch, obj, NULL, TO_CHAR); } } paf_type = paf->type; affect_from_obj(obj, paf); } if (paf_type == 0) { send_to_char( "Nothing appears to happen.\n\r", ch ); } } pop_call(); return; } DO_SPELL(spell_earthquake) { CHAR_DATA *vch; CHAR_DATA *vch_next; EXIT_DATA *pexit; int door, temp_vnum; push_call("spell_earthquake(%p,%p,%p,%p)",sn,level,ch,vo); /* no earthquakes in the air */ if (ch->in_room->sector_type == SECT_AIR) { send_to_char("The earth trembles far beneath you.\n\r",ch); pop_call(); return; } send_to_char( "The earth trembles beneath your feet!\n\r", ch ); act( "$n makes the earth tremble and shiver.", ch, NULL, NULL, TO_ROOM ); temp_vnum = ch->in_room->vnum; for (door = 0 ; door <= 5 ; door++) { if ((pexit = get_exit(temp_vnum, door)) && pexit->to_room != temp_vnum) { ch->in_room = room_index[pexit->to_room]; act("The earth trembles and shivers.", ch, NULL, NULL, TO_ROOM ); } } ch->in_room = room_index[temp_vnum]; for (vch = ch->in_room->last_person ; vch ; vch = vch_next) { vch_next = vch->prev_in_room; if (CAN_FLY(vch)) { continue; } if (!can_mass_cast(ch, vch)) { continue; } damage( ch, vch, level + dice(2, 8), sn ); } pop_call(); return; } DO_SPELL(spell_tremor) { CHAR_DATA *vch; CHAR_DATA *vch_next; EXIT_DATA *pexit; int door, temp_vnum; push_call("spell_tremor(%p,%p,%p,%p)",sn,level,ch,vo); if (ch->in_room->sector_type == SECT_AIR) { send_to_char("The earth tremors far beneath you.\n\r",ch); pop_call(); return; } temp_vnum = ch->in_room->vnum; for (door = 0 ; door <= 5 ; door++) { if ((pexit = get_exit(temp_vnum, door)) && pexit->to_room != temp_vnum) { ch->in_room = room_index[pexit->to_room]; act("You hear a loud wrenching noise from the ground.", ch, NULL, NULL, TO_ROOM ); } } ch->in_room = room_index[temp_vnum]; send_to_char( "The earth tremors beneath your feet!\n\r", ch ); act( "$n makes the earth shake.", ch, NULL, NULL, TO_ROOM ); for (vch = ch->in_room->last_person ; vch ; vch = vch_next) { vch_next = vch->prev_in_room; if (CAN_FLY(vch)) { continue; } if (!can_mass_cast(ch, vch)) { continue; } if (number_bits(3) == 0) { vch->position = POS_RESTING; } damage(ch, vch, number_range(level * 2, level * 3) + dice(5, 20), sn); } pop_call(); return; } DO_SPELL(spell_enchant_weapon) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA af; push_call("spell_enchant_weapon(%p,%p,%p,%p)",sn,level,ch,vo); if (!IS_NPC(ch) && multi(ch, sn) == -1) { send_to_char( "You can't do that!\n\r", ch); pop_call(); return; } if (obj->item_type != ITEM_WEAPON || IS_OBJ_STAT(obj, ITEM_MAGIC) || obj->first_affect != NULL) { send_to_char( "That object cannot be enchanted.\n\r", ch); pop_call(); return; } SET_BIT(obj->extra_flags, ITEM_MODIFIED); SET_BIT(obj->extra_flags, ITEM_MAGIC); af.type = sn; af.duration = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.location = APPLY_HITROLL; af.modifier = level / 5; affect_to_obj(obj, &af); af.location = APPLY_DAMROLL; af.modifier = level / 10; affect_to_obj(obj, &af); obj->level += level/3; if (IS_GOOD(ch)) { SET_BIT(obj->extra_flags, ITEM_ANTI_EVIL); act("$p glows yellow.", ch, obj, NULL, TO_ROOM); } else if (IS_EVIL(ch)) { SET_BIT(obj->extra_flags, ITEM_ANTI_GOOD); act("$p glows red.", ch, obj, NULL, TO_ROOM); } else { SET_BIT(obj->extra_flags, ITEM_ANTI_EVIL); SET_BIT(obj->extra_flags, ITEM_ANTI_GOOD); act("$p glows blue.", ch, obj, NULL, TO_ROOM); } act("$p has been enchanted.", ch, obj, NULL, TO_CHAR); pop_call(); return; } DO_SPELL(spell_energy_bolt) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_energy_bolt(%p,%p,%p,%p)",sn,level,ch,vo); dam = 10 + number_range(level, level*2); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_energy_drain) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_energy_drain(%p,%p,%p,%p)",sn,level,ch,vo); if (saves_spell(5 * level / 4, ch, victim)) { switch(number_range(1,3)) { case 1: act( "$N shrugs off your deathly embrace!", ch, NULL, victim, TO_CHAR); break; case 2: act( "$N flinches but is unharmed.", ch, NULL, victim, TO_CHAR); break; case 3: act( "$N moans softly from your spine chilling spell, but is otherwise unharmed.", ch, NULL, victim, TO_CHAR); break; } pop_call(); return; } if (!IS_NPC(victim)) { gain_exp(victim, 0 - dice(level, 5)); } dam = number_range(level * 2, level * 4) + 50; ch->hit = UMIN(ch->hit + dam / 6, ch->max_hit); victim->move = UMAX(0, victim->move - number_fuzzy(dam) / 3); victim->mana = UMAX(0, victim->mana - number_fuzzy(dam) / 3); damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_fireball) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_fireball(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range( level*3 , level*5); if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_flamestrike) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_flamestrike(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level, level+150); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_faerie_fire) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_faerie_fire(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, gsn_faerie_fire)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level; af.location = APPLY_AC; af.modifier = 2 * level; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "You are surrounded by a pink outline.\n\r", victim ); act( "$n is surrounded by a pink outline.", victim, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_faerie_fog) { CHAR_DATA *ich; push_call("spell_faerie_fog(%p,%p,%p,%p)",sn,level,ch,vo); act( "$n conjures a cloud of purple smoke.", ch, NULL, NULL, TO_ROOM ); send_to_char( "You conjure a cloud of purple smoke.\n\r", ch ); for ( ich = ch->in_room->first_person; ich != NULL; ich = ich->next_in_room ) { if ( !IS_NPC(ich) && IS_SET(ich->act, PLR_WIZINVIS) ) continue; if ( !IS_NPC(ich) && IS_SET(ich->act, PLR_WIZCLOAK) ) continue; if( IS_NPC(ich) && IS_AFFECTED(ich, AFF_ETHEREAL) ) continue; if ( ich == ch || saves_spell( level, ch, ich ) ) continue; affect_strip ( ich, gsn_invis ); affect_strip ( ich, gsn_sneak ); affect_strip ( ich, gsn_stealth ); REMOVE_BIT ( ich->affected_by, AFF_HIDE ); REMOVE_BIT ( ich->affected_by, AFF_INVISIBLE ); REMOVE_BIT ( ich->affected_by, AFF_SNEAK ); REMOVE_BIT ( ich->affected_by, AFF_STEALTH ); REMOVE_BIT ( ich->affected_by, AFF_IMP_INVISIBLE); act( "$n is revealed!", ich, NULL, NULL, TO_ROOM ); send_to_char( "You are revealed!\n\r", ich ); } pop_call(); return; } DO_SPELL(spell_fly) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_fly(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF2_EARTHBIND)) { send_to_char("They are bound to the earth.\n\r", ch); pop_call(); return; } if (CAN_FLY(victim)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level + 3; af.location = 0; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_FLYING; affect_to_char( victim, &af ); send_to_char( "Your feet rise off the ground.\n\r", victim ); act( "$n's feet rise off the ground.", victim, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_gate) { CHAR_DATA *victim; OBJ_DATA *gate; push_call("spell_gate(%p,%p,%p,%p)",sn,level,ch,vo); if (target_name[0] == '\0') { send_to_char("Whom would you want to gate to?\n\r", ch); pop_call(); return; } if ((victim = get_char_area(ch, target_name)) == NULL) { send_to_char("There is none named like that.\n\r", ch); pop_call(); return; } if (IS_SET(ch->in_room->room_flags, ROOM_IS_CASTLE) || (IS_NPC(victim) && level / 3 < victim->level) || (!IS_NPC(victim) && level - 3 < victim->level)) { send_to_char( "They are protected from your power.\n\r", ch); pop_call(); return; } if (!IS_NPC(victim) && is_affected(victim, gsn_anti_magic_shell)) { act("The flows of magic shatter against a shell surrounding $N.", ch, NULL, victim, TO_CHAR); pop_call(); return; } if (victim == ch || victim->in_room == NULL || IS_SET(victim->in_room->room_flags, ROOM_SAFE) || IS_SET(victim->in_room->room_flags, ROOM_PRIVATE) || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) || IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || victim->in_room->sector_type == SECT_ETHEREAL || victim->in_room->sector_type == SECT_ASTRAL || ch->in_room->sector_type == SECT_ETHEREAL || ch->in_room->sector_type == SECT_ASTRAL || IS_SET(ch->in_room->area->flags, AFLAG_NORECALL) || IS_SET(ch->in_room->area->flags, AFLAG_NOSUMMON) || victim->level > UMIN(ch->level-3, level - 3) || find_keeper(victim) != NULL) { send_to_char( "You failed.\n\r", ch ); pop_call(); return; } if (ch->in_room == victim->in_room) { send_to_char("You are already there.\n\r",ch); pop_call(); return; } if (saves_spell(level,ch,victim)) { send_to_char("You failed to envision your victim.\n\r", ch); pop_call(); return; } gate = create_object(get_obj_index(OBJ_VNUM_GATE), 0); if (!gate) { ch_printf(ch,"You try to create a gate, but it does not seem possible somehow.\n\r"); pop_call(); return; } gate->value[3] = victim->in_room->vnum; obj_to_room(gate, ch->in_room->vnum); act( "$p opens before you.", ch, gate, NULL, TO_CHAR); act( "$p opens before $n.", ch, gate, NULL, TO_ROOM); do_enter(ch, "i23"); obj_from_room(gate); junk_obj(gate); pop_call(); return; } /* * Spell for mega1.are from Glop/Erkenbrand. */ DO_SPELL(spell_general_purpose) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_general_purpose(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range( 25, 100 ); if ( saves_spell( level, ch, victim ) ) dam /= 2; damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_giant_strength) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_giant_strength(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level; af.location = APPLY_STR; af.modifier = 1 + (level >= 18) + (level >= 25); af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "You feel the strength of a giant.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_harm) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_harm(%p,%p,%p,%p)",sn,level,ch,vo); dam = 100 + number_range(0, 4) * 50; if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, number_fuzzy(dam), sn ); pop_call(); return; } DO_SPELL(spell_heal) { CHAR_DATA *victim = (CHAR_DATA *) vo; push_call("spell_heal(%p,%p,%p,%p)",sn,level,ch,vo); victim->hit = UMIN( victim->hit + 100, victim->max_hit ); update_pos( victim ); send_to_char( "A warm feeling fills your body.\n\r", victim ); affect_strip(victim,gsn_critical_hit); affect_strip(victim,631); /* HALLUCINATE */ if ( ch != victim ) { send_to_char( "Healing powers at work.\n\r", ch ); } pop_call(); return; } /* * Spell for mega1.are from Glop/Erkenbrand. */ DO_SPELL(spell_high_explosive) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_high_explosive(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range( 30, 120 ); if ( saves_spell( level, ch, victim ) ) dam /= 2; damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_identify) { OBJ_DATA *obj = (OBJ_DATA *) vo; char buf[MAX_STRING_LENGTH]; AFFECT_DATA *paf; push_call("spell_identify(%p,%p,%p,%p)",sn,level,ch,vo); ch_printf(ch, "%s is type %s, extra flags %s.\n\rWeight is %d, value is %d, level is %d.\n\r", capitalize(obj->short_descr), item_type_name(obj), flag_string(obj->extra_flags, o_flags), get_obj_weight(obj), obj->cost, obj->level); switch ( obj->item_type ) { case ITEM_SCROLL: case ITEM_POTION: case ITEM_PILL: sprintf(buf, "Level %d spells of:", obj->value[0]); if (obj->value[1] > 0 && obj->value[1] < MAX_SKILL) { cat_sprintf(buf, " '%s'", skill_table[obj->value[1]].name); } if (obj->value[2] > 0 && obj->value[2] < MAX_SKILL) { cat_sprintf(buf, " '%s'", skill_table[obj->value[2]].name); } if (obj->value[3] > 0 && obj->value[3] < MAX_SKILL) { cat_sprintf(buf, " '%s'", skill_table[obj->value[3]].name); } ch_printf(ch, "%s\n\r", buf); break; case ITEM_WAND: case ITEM_STAFF: sprintf(buf, "Has %d/%d charges of level %d", obj->value[2], obj->value[1], obj->value[0]); if (obj->value[3] >= 0 && obj->value[3] < MAX_SKILL) { cat_sprintf(buf, " '%s'", skill_table[obj->value[3]].name); } ch_printf(ch, "%s\n\r", buf); break; case ITEM_WEAPON: switch (obj->value[0]) { case WEAPON_TYPE_WEAPON: ch_printf(ch, "Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_SWORD: ch_printf(ch, "This weapon is a sword. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_DAGGER: ch_printf(ch, "This weapon is a dagger. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_AXE: ch_printf(ch, "This weapon is an axe. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_MACE: ch_printf(ch, "This weapon is a mace. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_STAFF: ch_printf(ch, "This weapon is a staff. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_WHIP: ch_printf(ch, "This weapon is a whip. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_FLAIL: ch_printf(ch, "This weapon is a flail. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_SPEAR: ch_printf(ch, "This weapon is a spear. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_CLAW: ch_printf(ch, "This weapon is a claw. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_SHORTBOW: ch_printf(ch, "This weapon is a short bow. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_LONGBOW: ch_printf(ch, "This weapon is a long bow. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_CROSSBOW: ch_printf(ch, "This weapon is a cross bow. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; case WEAPON_TYPE_BLOWPIPE: ch_printf(ch, "This weapon is a blow pipe. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; default: ch_printf(ch, "This weapon is faulty. Talk to Demise. Damage is %dd%d.\n\r", obj->value[1], obj->value[2]); break; } break; case ITEM_ARMOR: ch_printf(ch, "Armor class is %d.\n\r", obj->value[0] ); break; case ITEM_AMMO: switch (obj->value[0]) { case WEAPON_TYPE_SHORTBOW: ch_printf(ch, "Ammo type for short bows, Damage is %d, Speed is %d, Range is %d.\n\r", obj->value[1], obj->value[2], obj->value[3]); break; case WEAPON_TYPE_LONGBOW: ch_printf(ch, "Ammo type for long bows, Damage is %d, Speed is %d, Range is %d.\n\r", obj->value[1], obj->value[2], obj->value[3]); break; case WEAPON_TYPE_CROSSBOW: ch_printf(ch, "Ammo type for cross bows, Damage is %d, Speed is %d, Range is %d.\n\r", obj->value[1], obj->value[2], obj->value[3]); break; case WEAPON_TYPE_BLOWPIPE: ch_printf(ch, "Ammo type for blow pipes, Damage is %d, Speed is %d, Range is %d.\n\r", obj->value[1], obj->value[2], obj->value[3]); break; default: ch_printf(ch, "Ammo type is faulty. Talk to Demise. Damage is %d, Speed is %d, Range is %d.\n\r", obj->value[1], obj->value[2], obj->value[3]); break; } break; case ITEM_CONTAINER: ch_printf(ch, "Capacity is %d weight and %d items.\n\r", obj->value[0], obj->value[3] ? obj->value[3] : MAX_OBJECTS_IN_CONTAINER); break; } for (paf = obj->pIndexData->first_affect ; paf ; paf = paf->next) { switch (paf->location) { case APPLY_NONE: break; default: ch_printf(ch, "Affects %s by %d.\n\r", affect_loc_name(paf->location), paf->modifier); break; } switch (paf->bittype) { case AFFECT_TO_NONE: break; case AFFECT_TO_CHAR: ch_printf(ch, "Affects wearer with %s.\n\r", affect_bit_name(paf->bitvector)); break; case AFFECT_TO_OBJ: ch_printf(ch, "Affects object with %s.\n\r", flag_string(paf->bitvector, o_flags)); break; } } for (paf = obj->first_affect ; paf != NULL ; paf = paf->next) { switch (paf->location) { case APPLY_NONE: break; default: ch_printf(ch, "Affects %s by %d.\n\r", affect_loc_name(paf->location), paf->modifier); break; } switch (paf->bittype) { case AFFECT_TO_NONE: break; case AFFECT_TO_CHAR: ch_printf(ch, "Affects wearer with %s.\n\r", affect_bit_name(paf->bitvector)); break; case AFFECT_TO_OBJ: ch_printf(ch, "Affects object with %s.\n\r", flag_string(paf->bitvector, o_flags)); break; } } sprintf(buf, "Wear locations:"); if (!IS_SET(obj->wear_flags, ITEM_TAKE)) { strcat( buf, " Cannot take"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_FINGER)) { strcat( buf, " Fingers"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_NECK)) { strcat( buf, " Neck"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_BODY)) { strcat( buf, " Body"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_HEAD)) { strcat( buf, " Head"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_LEGS)) { strcat( buf, " Legs"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_FEET)) { strcat( buf, " Feet"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_HANDS)) { strcat( buf, " Hands"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_ARMS)) { strcat( buf, " Arms"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_SHIELD)) { strcat( buf, " Shield"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_ABOUT)) { strcat( buf, " About"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_WAIST)) { strcat( buf, " Waist"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_WRIST)) { strcat( buf, " Wrist"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_WIELD)) { strcat( buf, " Wield"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_HOLD)) { strcat( buf, " Hold"); } if (IS_SET(obj->wear_flags, ITEM_WEAR_HEART)) { strcat( buf, " Heart"); } if (strlen(buf) < 17) { strcat( buf, " Carry only"); } ch_printf(ch, "%s.\n\r", buf); pop_call(); return; } DO_SPELL(spell_infravision) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_infravision(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_INFRARED) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } act( "$n's eyes glow red.", ch, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = 2 * level; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_INFRARED; affect_to_char( victim, &af ); send_to_char( "Your eyes glow red.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_enhanced_heal) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_enhanced_heal(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF2_ENHANCED_HEAL) ) { send_to_char("They are already healing easily.\n\r", ch); pop_call(); return; } act( "$n heals easily.", victim, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_ENHANCED_HEAL; affect_to_char( victim, &af ); send_to_char( "You heal easily.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_enhanced_revive) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_enhanced_revive(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF2_ENHANCED_REVIVE) ) { send_to_char("They are already reviving easily.\n\r", ch); pop_call(); return; } act( "$n revives easily.", victim, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_ENHANCED_REVIVE; affect_to_char( victim, &af ); send_to_char( "You revive easily.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_enhanced_rest) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_enhanced_rest(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF2_ENHANCED_REST) ) { send_to_char("They are already resting easily.\n\r", ch); pop_call(); return; } act( "$n rests easily.", victim, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_ENHANCED_REST; affect_to_char( victim, &af ); send_to_char( "You rest easily.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_remove_fear) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_remove_fear(%p,%p,%p,%p)",sn,level,ch,vo); if (saves_spell(level, ch, victim)) { send_to_char( "They are not made fearless.\n\r", ch ); pop_call(); return; } if (!IS_NPC(victim)) { if (is_affected(victim, sn)) { send_to_char("They are already fearless.\n\r", ch); pop_call(); return; } af.type = sn; af.duration = level / 3; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.location = APPLY_NONE; af.modifier = 0; affect_to_char(victim, &af); affect_strip(victim, gsn_fear); victim->pcdata->wimpy = 0; } else { if (!IS_SET(victim->act, ACT_WIMPY)) { send_to_char( "They are already fearless.\n\r", ch ); pop_call(); return; } REMOVE_BIT(victim->act, ACT_WIMPY); } act("You become fearless!", victim, NULL, NULL, TO_CHAR ); act("$n becomes fearless!", victim, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_fear) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_fear(%p,%p,%p,%p)",sn,level,ch,vo); if (saves_spell(level, ch, victim)) { send_to_char( "They are not made frightened.\n\r", ch ); pop_call(); return; } if (!IS_NPC(victim)) { if (is_affected(victim, sn)) { send_to_char("They are already frightened.\n\r", ch); pop_call(); return; } af.type = sn; af.duration = level / 3; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.location = APPLY_NONE; af.modifier = 0; affect_to_char(victim, &af); affect_strip(victim, gsn_remove_fear); victim->pcdata->wimpy = victim->max_hit / 2; } else { if (IS_SET(victim->act, ACT_WIMPY)) { send_to_char( "They are already frightened.\n\r", ch ); pop_call(); return; } SET_BIT(victim->act, ACT_WIMPY); } act("You become filled with fear!", victim, NULL, NULL, TO_CHAR ); act("$n becomes filled with fear!", victim, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_haste) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_haste(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF_HASTE)) { send_to_char("They are already fast.\n\r", ch); pop_call(); return; } af.type = sn; af.location = APPLY_DEX; if (which_god(victim) != GOD_MANWE) { af.duration = URANGE(6, level / 8, 24); af.modifier = 1 + (level > 49) + (level > 99); } else { af.duration = URANGE(12, level / 4, 48); af.modifier = 1 + (level > 24) + (level > 49) + (level > 74) + (level > 99) + (level > 124); } af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_HASTE; affect_to_char(victim, &af); send_to_char("You speed up.\n\r", victim); act("$n speeds up.", victim, NULL, NULL, TO_ROOM); pop_call(); return; } DO_SPELL(spell_invis) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA af; push_call("spell_invis(%p,%p,%p,%p)",sn,level,ch,vo); if (target == TAR_CHAR_DEFENSIVE) { if (IS_AFFECTED(victim, AFF_INVISIBLE) || IS_AFFECTED(victim, AFF_IMP_INVISIBLE)) { send_to_char("They are already invisible.\n\r", ch); pop_call(); return; } act("You fade out of existence.", victim, NULL, NULL, TO_CHAR); act("$n fades out of existence.", victim, NULL, NULL, TO_ROOM); af.type = sn; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_INVISIBLE; affect_to_char( victim, &af ); } else if (target == TAR_OBJ_INV) { if (IS_SET(obj->extra_flags, ITEM_INVIS)) { act("$p is already invisible.", ch, obj, NULL, TO_CHAR); pop_call(); return; } af.type = sn; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_OBJ; af.bitvector = ITEM_INVIS; affect_to_obj(obj, &af ); SET_BIT(obj->extra_flags, ITEM_MODIFIED); act("$p fades out of existance.", ch, obj, NULL, TO_CHAR); } pop_call(); return; } DO_SPELL(spell_invis_obj) { OBJ_DATA *obj = (OBJ_DATA *) vo; push_call("spell_invis_obj(%p,%p,%p,%p)",sn,level,ch,vo); if (number_fuzzy(obj->level) > level) { send_to_char( "You failed.\n\r", ch); pop_call(); return; } if (IS_SET(obj->extra_flags, ITEM_INVIS)) { send_to_char( "It is already invisible.\n\r", ch); pop_call(); return; } SET_BIT(obj->extra_flags, ITEM_INVIS); SET_BIT(obj->extra_flags, ITEM_MODIFIED); send_to_char( "Ok.\n\r", ch ); pop_call(); return; } DO_SPELL(spell_tongues) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_tongues(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_TONGUES)) { send_to_char( "That person is already speaking in tongues.\n\r", ch); pop_call(); return; } act( "$n starts speaking in tongues.", victim, NULL, NULL, TO_ROOM); af.type = sn; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_TONGUES; affect_to_char( victim, &af); send_to_char( "You start speaking in tongues.\n\r", victim); if(ch!=victim) { send_to_char( "Ok.\n\r", ch); } pop_call(); return; } DO_SPELL(spell_understand) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_understand(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF_UNDERSTAND)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } act( "$n starts understanding everyone.", victim, NULL, NULL, TO_ROOM); af.type = sn; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_UNDERSTAND; affect_to_char( victim, &af); send_to_char( "You start understanding everyone.\n\r", victim); if(ch!=victim) { send_to_char( "Ok.\n\r", ch); } pop_call(); return; } DO_SPELL(spell_petrifying_touch) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_petrifying_touch(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level+30, level+110); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } else if (number_bits(1) == 0) { AFFECT_DATA af; af.type = sn; af.duration = 1; if (!IS_NPC(victim)) { af.location = APPLY_DEX; af.modifier = -1; } else { af.location = APPLY_AC; af.modifier = 2; } af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_join( victim, &af ); } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_locate_object) { OBJ_DATA *obj; OBJ_DATA *in_obj; int count; push_call("spell_locate_object(%p,%p,%p,%p)",sn,level,ch,vo); if (*target_name == '\0') { send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch ); pop_call(); return; } if (strlen(target_name) > 20) { target_name[20] = '\0'; } count = 0; for (obj = mud->f_obj ; obj ; obj = obj->next) { if (obj->level > level || !is_multi_name_list_short(target_name, short_to_name(obj->short_descr, 1)) || !can_see_obj(ch, obj) ) { continue; } for (in_obj = obj ; in_obj->in_obj ; in_obj = in_obj->in_obj); if (in_obj->carried_by && !can_see_world(ch, in_obj->carried_by)) { continue; } count++; if (in_obj->carried_by != NULL) { ch_printf(ch, "%s%s is carried by %s.\n\r", get_color_string(ch, COLOR_TEXT, VT102_DIM), capitalize(obj->short_descr), PERS(in_obj->carried_by, ch)); } else { ch_printf(ch, "%s%s is in %s.\n\r", get_color_string(ch, COLOR_TEXT, VT102_DIM), capitalize(obj->short_descr), in_obj->in_room == NULL ? "somewhere" : in_obj->in_room->name); } if (count > UMAX(20, 10 + level / 10)) { break; } } if (count == 0) { send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_magic_missile) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_magic_missile(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level / 2 + 40, level / 2 + 60); if (!IS_AFFECTED(ch, AFF2_QUICKEN)) { switch (level / 25) { case 0: wait_state(ch, 1 + skill_table[sn].beats * 3); break; case 1: wait_state(ch, 1 + skill_table[sn].beats * 2); break; default: wait_state(ch, 1 + skill_table[sn].beats * 1); break; } } if ( saves_spell( level, ch, victim ) ) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_mass_invis) { AFFECT_DATA af; CHAR_DATA *gch; push_call("spell_mass_invis(%p,%p,%p,%p)",sn,level,ch,vo); for (gch = ch->in_room->first_person ; gch ; gch = gch->next_in_room) { if (!is_same_group(gch, ch)) { continue; } if (IS_AFFECTED(gch, AFF_INVISIBLE) || IS_AFFECTED(gch, AFF_IMP_INVISIBLE)) { continue; } act("$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM); act("You slowly fade out of existence.", gch, NULL, NULL, TO_CHAR); af.type = gsn_invis; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_INVISIBLE; affect_to_char( gch, &af ); } send_to_char( "Ok.\n\r", ch ); pop_call(); return; } DO_SPELL(spell_null) { push_call("spell_null(%p,%p,%p,%p)",sn,level,ch,vo); send_to_char( "That's not a spell!\n\r", ch ); pop_call(); return; } DO_SPELL(spell_pass_door) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_pass_door(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_PASS_DOOR) || rspec_req(victim,RSPEC_PASS_DOOR)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = number_fuzzy( level / 4 ); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_PASS_DOOR; affect_to_char( victim, &af ); act( "$n turns translucent.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You turn translucent.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_poison) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_poison(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_POISON) ) { send_to_char( "They are already poisoned.\n\r", ch ); pop_call(); return; } if ( saves_spell( level, ch, victim ) ) { send_to_char( "They turn slightly green but it passes.\n\r", ch ); pop_call(); return; } if (IS_NPC(victim)) { af.type = sn; af.duration = level; af.location = APPLY_AC; af.modifier = level; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_POISON; } else { af.type = sn; af.duration = level/4; af.location = APPLY_STR; af.modifier = -2; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_POISON; } affect_to_char(victim, &af ); send_to_char( "You feel poison coursing through your vains.\n\r", victim ); if ( ch != victim ) { send_to_char( "They now feel your poison.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_mage_blast) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_mage_blast(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, gsn_mage_blast)) { send_to_char( "Your blast was ineffective.\n\r", ch ); pop_call(); return; } if (saves_spell(level, ch, victim)) { af.type = sn; af.duration = 1; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "Your blast was repelled.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/20; af.location = APPLY_SAVING_SPELL; af.modifier = level/8; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "Your magic aura has been weakened.\n\r", victim ); if ( ch != victim ) { send_to_char( "You blast through their magical defenses.\n\r", ch ); } pop_call(); return; } /* Checked spells till here - Scandum */ DO_SPELL(spell_protection_fe) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_protection_fe(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_PROTECT_EVIL) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/4; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_PROTECT_EVIL; affect_to_char( victim, &af ); send_to_char( "You feel protected from evil.\n\r", victim ); if ( ch != victim ) { send_to_char( "Protection has been applied from evil.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_protection_fg) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_protection_fg(%p,%p,%p,%p)",sn,level,ch,vo); if ( IS_AFFECTED(victim, AFF_PROTECT_GOOD) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/5; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_PROTECT_GOOD; affect_to_char( victim, &af ); send_to_char( "You feel protected from good.\n\r", victim ); if ( ch != victim ) { send_to_char( "Protection from good is now working.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_refresh) { CHAR_DATA *victim = (CHAR_DATA *) vo; push_call("spell_refresh(%p,%p,%p,%p)",sn,level,ch,vo); victim->move = UMIN( victim->move + level, victim->max_move ); send_to_char( "You feel less tired.\n\r", victim ); if ( ch != victim ) { send_to_char( "Movement is now restoring.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_remove_curse) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj; char buf[MAX_STRING_LENGTH]; push_call("spell_remove_curse(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, gsn_curse)) { affect_strip( victim, gsn_curse ); send_to_char( "You feel better.\n\r", victim ); if (ch != victim) { send_to_char( "Your spell has taken the curse away.\n\r", ch ); } pop_call(); return; } for(obj=victim->first_carrying; obj!=NULL ; obj=obj->next_content) if((!IS_SET(obj->extra_flags, ITEM_INVENTORY)) && (IS_SET(obj->extra_flags, ITEM_NODROP) || IS_SET(obj->extra_flags, ITEM_NOREMOVE))) { REMOVE_BIT( obj->extra_flags, ITEM_NOREMOVE); REMOVE_BIT( obj->extra_flags, ITEM_NODROP); if( victim!=ch) send_to_char( "Ok.\n\r", ch); sprintf( buf, "%s is no longer cursed.\n\r", obj->short_descr); if( buf[0]>='a' && buf[0]<='z') buf[0]-=('a'-'A'); send_to_char( buf, victim); pop_call(); return; } send_to_char( "That had no effect.\n\r", ch); pop_call(); return; } DO_SPELL(spell_ethereal) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA *paf, *paf_next; AFFECT_DATA af; push_call("spell_ethereal(%p,%p,%p,%p)",sn,level,ch,vo); if( IS_NPC( victim ) ) { send_to_char( "You may only cast that on players.\n\r", ch ); pop_call(); return; } if ( IS_AFFECTED(victim, AFF2_ETHEREAL) ) { for ( paf = victim->first_affect; paf != NULL; paf = paf_next ) { paf_next = paf->next; if( paf->bitvector==AFF2_ETHEREAL ) { paf->duration = number_fuzzy( level / 2 ); send_to_char( "You faze out a bit more.\n\r", victim ); if( victim != ch ) send_to_char( "Ok.\n\r", ch ); pop_call(); return; } } } af.type = sn; af.duration = number_fuzzy( level / 2 ); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_ETHEREAL; affect_to_char( victim, &af ); act( "$n partially fades out.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You partially fade out.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_astral) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af, *paf, *paf_next; push_call("spell_astral(%p,%p,%p,%p)",sn,level,ch,vo); if( IS_NPC( victim ) ) { send_to_char( "You may only cast that on players.\n\r", ch ); pop_call(); return; } if ( IS_AFFECTED(victim, AFF2_ASTRAL) ) { for ( paf = victim->first_affect; paf != NULL; paf = paf_next ) { paf_next = paf->next; if (paf->bitvector == AFF2_ASTRAL) { paf->duration = number_fuzzy( level / 3 ); send_to_char( "You no longer have the urge to return to your body.\n\r", victim ); if (ch != victim) { act( "$N no longer has the urge to return to $S body.", ch, NULL, victim, TO_CHAR ); } pop_call(); return; } } } af.type = sn; af.duration = number_fuzzy( level / 3 ); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_ASTRAL; affect_to_char( victim, &af ); act( "$n steps outside of $s body.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You step outside your body.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_breath_water) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af, *paf, *paf_next; push_call("spell_breath_water(%p,%p,%p,%p)",sn,level,ch,vo); if( IS_NPC( victim ) ) { send_to_char( "You may only cast that on players.\n\r", ch ); pop_call(); return; } if ( IS_AFFECTED(victim, AFF2_BREATH_WATER) ) { for ( paf = victim->first_affect; paf != NULL; paf = paf_next ) { paf_next = paf->next; if( paf->bitvector == AFF2_BREATH_WATER ) { paf->duration = number_fuzzy( level / 3 ); act( "$n takes another deep breath.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You take another deep breath.\n\r", victim ); /*if( victim != ch ) send_to_char( "Gills appear so water can be breathed.\n\r", victim );*/ pop_call(); return; } } } af.type = sn; af.duration = number_fuzzy( level / 3 ); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_BREATH_WATER; affect_to_char( victim, &af ); act( "$n takes a deep breath.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You take a deep breath.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_sanctuary) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_sanctuary(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF_SANCTUARY)) { send_to_char( "That person already has Sanctuary.\n\r", ch); pop_call(); return; } af.type = sn; af.duration = number_fuzzy( level / 4 ); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_SANCTUARY; affect_to_char( victim, &af ); act( "$n is surrounded by a white aura.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are surrounded by a white aura.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_shield) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_shield(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "That person is already Shielded.\n\r", ch); pop_call(); return; } af.type = sn; af.duration = 8 + level/2; af.location = APPLY_AC; af.modifier = -20; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n is surrounded by a force shield.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are surrounded by a force shield.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_shocking_grasp) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_shocking_grasp(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level+60, level+90); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_paralyzing_embrace) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_paralyzing_embrace(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level+20, level+120); if ( saves_spell( level, ch, victim ) ) { dam /= 2; } else if (number_bits(1) == 0) { AFFECT_DATA af; af.type = sn; af.duration = 1; if (!IS_NPC(victim)) { if (number_bits(1) == 0) { af.location = APPLY_INT; af.modifier = -1; } else { af.location = APPLY_WIS; af.modifier = -1; } } else { af.location = APPLY_SAVING_SPELL; af.modifier = 1; } af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_join( victim, &af ); } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_sleep) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_sleep(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char("You are forbidden from casting that here.\n\r", ch); pop_call(); return; } if (!IS_NPC(ch) && !IS_NPC(victim)) { if (!can_attack(ch, victim)) { send_to_char("You cannot cast sleep on that person.\n\r", ch); pop_call(); return; } } if ( IS_AFFECTED(victim, AFF_SLEEP) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } if (level < victim->level) { send_to_char( "They are too high of a level.\n\r", ch ); pop_call(); return; } if (saves_spell(level, ch, victim)) { send_to_char( "Nothing happens.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level / 5; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_SLEEP; affect_to_char( victim, &af ); if ( IS_AWAKE(victim) ) { send_to_char( "You feel very sleepy ..... zzzzzz.\n\r", victim ); act( "$n goes to sleep.", victim, NULL, NULL, TO_ROOM ); victim->position = POS_SLEEPING; } pop_call(); return; } DO_SPELL(spell_stone_skin) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_stone_skin(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/2; af.location = APPLY_AC; af.modifier = -40; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n's skin turns to stone.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your skin turns to stone.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_demon) { MOB_INDEX_DATA *pMob; CHAR_DATA *mh; push_call("spell_demon(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char("You are forbidden from casting that here.\n\r", ch); pop_call(); return; } if (get_pets(ch) > 0) { send_to_char("You have too many pets.\n\r", ch); pop_call(); return; } if (ch->position == POS_FIGHTING) { send_to_char( "You cannot cast this during combat.\n\r", ch); pop_call(); return; } pMob = get_mob_index( 9901 ); /* Hard coded in emud.are */ mh = create_mobile( pMob ); char_to_room( mh, ch->in_room->vnum ); mh->level = level * 3 / 4; mh->npcdata->damnodice = mh->level; mh->npcdata->damsizedice = 4; mh->npcdata->damplus = 3; mh->max_hit = 80 + mh->level * 4; mh->hit = mh->max_hit; if (number_percent() < 66) { SET_BIT( mh->affected_by , AFF_CHARM ); send_to_char( "A demon appears out of a rip in space.\n\r", ch); act("A demon appears out of a rip in space.", ch, NULL, NULL, TO_ROOM); add_follower( mh , ch ); pop_call(); return; } mh->level = level; mh->max_hit = 30 + mh->level * 10; send_to_char( "A demon appears out of a rip in space.\n\rHe seems angry.\n\r", ch); multi_hit(mh, ch, TYPE_UNDEFINED); pop_call(); return; } DO_SPELL(spell_animate_dead) { CHAR_DATA *mh; OBJ_DATA *obj; push_call("spell_animate_dead(%p,%p,%p,%p)",sn,level,ch,vo); if (get_pets(ch) > 0) { send_to_char( "You have too many pets.\n\r", ch); pop_call(); return; } if (ch->position == POS_FIGHTING) { send_to_char( "You cannot cast this during combat.\n\r", ch); pop_call(); return; } for (obj = ch->in_room->first_content ; obj ; obj = obj->next_content) { if (obj->item_type == ITEM_CORPSE_NPC && obj->level <= level) { break; } } if (obj == NULL) { send_to_char( "You find no suitable corpse.\n\r", ch); pop_call(); return; } mh = create_mobile(mob_index[9903]); char_to_room( mh, ch->in_room->vnum ); mh->level = obj->level; mh->hitroll = 0; mh->npcdata->damnodice = mh->level; mh->npcdata->damsizedice = 3; mh->npcdata->damplus = 2; mh->max_hit = 50 + mh->level * 5; mh->hit = mh->max_hit; SET_BIT( mh->affected_by , AFF_CHARM ); SET_BIT( mh->act, ACT_UNDEAD ); if (IS_SET(obj->extra_flags, ITEM_MOUNT)) { SET_BIT( mh->act, ACT_MOUNT ); } act("$n raises $p from death.", ch, obj, NULL, TO_ROOM ); RESTRING(mh->name, obj->name); RESTRING(mh->short_descr, obj->short_descr); RESTRING(mh->long_descr, ""); RESTRING(mh->description, ""); while (obj->first_content) { if (number_bits(1)) { obj_to_char(obj->first_content, mh); } else { junk_obj(obj->first_content); } } junk_obj(obj); do_wear(mh, "all"); add_follower( mh , ch ); pop_call(); return; } DO_SPELL(spell_beast) { MOB_INDEX_DATA *pMob; CHAR_DATA *mh; push_call("spell_beast(%p,%p,%p,%p)",sn,level,ch,vo); if (get_pets(ch) > 0) { send_to_char( "You have too many pets.\n\r", ch); pop_call(); return; } if (ch->position == POS_FIGHTING) { send_to_char( "You cannot cast this during combat.\n\r", ch); pop_call(); return; } pMob = get_mob_index( 9902 ); /* Hard coded in emud.are */ mh = create_mobile( pMob ); char_to_room( mh, ch->in_room->vnum ); mh->level = level * 3 / 4; mh->npcdata->damnodice = mh->level; mh->npcdata->damsizedice = 2; mh->npcdata->damplus = 5; mh->max_hit = 30 + level * 4; mh->hit = 30 + level * 4; SET_BIT(mh->affected_by, AFF_CHARM); send_to_char( "A shadow beast appears out of a ripple in the wall.\n\r", ch); add_follower( mh , ch ); if (ch->fighting != NULL) { multi_hit( mh, ch->fighting->who, TYPE_UNDEFINED); } pop_call(); return; } DO_SPELL(spell_shade) { MOB_INDEX_DATA *pMob; CHAR_DATA *mh; push_call("spell_shade(%p,%p,%p,%p)",sn,level,ch,vo); if (get_pets(ch) > 0) { send_to_char("You have too many pets.\n\r", ch); pop_call(); return; } pMob = get_mob_index( 9903 ); /* Hard coded in emud.are */ mh = create_mobile( pMob ); char_to_room( mh, ch->in_room->vnum ); mh->level = level * 2 / 3; mh->npcdata->damnodice = mh->level / 2; mh->npcdata->damsizedice = 2; mh->npcdata->damplus = 5; mh->max_hit = 30 + level * 3; mh->hit = 30 + level * 3; SET_BIT(mh->affected_by , AFF_CHARM); act("A Shade appears out of a ripple in the floor.", ch, NULL, NULL, TO_CHAR); act("A Shade appears out of a ripple in the floor.", ch, NULL, NULL, TO_ROOM); add_follower( mh , ch ); pop_call(); return; } DO_SPELL(spell_phantasm) { MOB_INDEX_DATA *pMob; CHAR_DATA *mh; push_call("spell_phantasm(%p,%p,%p,%p)",sn,level,ch,vo); if (get_pets(ch) > 0) { send_to_char( "You have too many pets.\n\r", ch); pop_call(); return; } pMob = get_mob_index( 9904 ); /* Hard coded in emud.are */ mh = create_mobile( pMob ); char_to_room( mh, ch->in_room->vnum ); mh->level = level * 1 / 2; mh->npcdata->damnodice = mh->level; mh->npcdata->damsizedice = 5; mh->npcdata->damplus = 50; mh->max_hit = 50 + mh->level * 6; mh->hit = 50 + mh->level * 6; SET_BIT( mh->affected_by , AFF_CHARM ); send_to_char( "A phantasmal killer appears out of the palm of your hand.\n\r", ch); add_follower( mh , ch ); if (ch->fighting != NULL) { multi_hit(mh, ch->fighting->who, TYPE_UNDEFINED ); } pop_call(); return; } DO_SPELL(spell_summon) { CHAR_DATA *victim; push_call("spell_summon(%p,%p,%p,%p)",sn,level,ch,vo); if (target_name[0] == '\0') { send_to_char("Whom would you like to summon?\n\r", ch); pop_call(); return; } if ((victim = get_char_area(ch, target_name)) == NULL) { send_to_char( "There is nothing named like that.\n\r", ch); pop_call(); return; } if (IS_NPC(victim) && level / 3 < victim->level) { send_to_char( "You cannot summon those that do not wish to leave.\n\r", ch); pop_call(); return; } if (!IS_NPC(victim) && is_affected(victim, gsn_anti_magic_shell)) { act("The flows of magic shatter against a shell surrounding $N.", ch, NULL, victim, TO_CHAR); act("Flows of magic shatter against your anti magic shell.", ch, NULL, victim, TO_VICT); pop_call(); return; } if (victim == ch || victim->in_room == NULL || IS_SET(victim->in_room->room_flags, ROOM_SAFE) || IS_SET(ch->in_room->room_flags, ROOM_SAFE) || IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL) || victim->in_room->sector_type == SECT_ETHEREAL || victim->in_room->sector_type == SECT_ASTRAL || ch->in_room->sector_type == SECT_ETHEREAL || ch->in_room->sector_type == SECT_ASTRAL || IS_SET(ch->in_room->area->flags, AFLAG_NORECALL) || IS_SET(ch->in_room->area->flags, AFLAG_NOSUMMON) || victim->level > level - 3 || victim->fighting != NULL || find_keeper(victim) != NULL) { send_to_char( "You failed.\n\r", ch ); pop_call(); return; } if (IS_AFFECTED(victim, AFF_STABILITY) || saves_spell(level / 2, ch, victim)) { send_to_char( "They resist your summoning spell.\n\r", ch); act("You feel a strange magical force pulling at you.", ch, NULL, victim, TO_VICT); pop_call(); return; } act( "$n disappears suddenly.", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, ch->in_room->vnum ); act( "$n arrives suddenly.", victim, NULL, NULL, TO_ROOM ); ch_printf(victim, "%s has summoned you!\n\r", get_name(ch)); do_look( victim, "auto" ); pop_call(); return; } DO_SPELL(spell_banish) { CHAR_DATA *victim = (CHAR_DATA *) vo; CHAR_DATA *rch; ROOM_INDEX_DATA *pRoomIndex; int cnt = 0; push_call("spell_banish(%p,%p,%p,%p)",sn,level,ch,vo); if (victim->in_room == NULL || victim == ch || IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(ch->in_room->area->flags, AFLAG_NORECALL) || IS_SET(ch->in_room->room_flags, AFLAG_NOSUMMON) || saves_spell(level, ch, victim)) { send_to_char( "You failed.\n\r", ch ); pop_call(); return; } if (saves_spell(level, ch, victim)) { victim = ch; } for ( ; ; ) { /* Better safe than freezing, added cnt - Scandum 01-04-2002 */ if (cnt++ > 10000) { send_to_char("Nothing happens", ch); pop_call(); return; } pRoomIndex = get_room_index(number_range(victim->in_room->area->low_r_vnum, victim->in_room->area->hi_r_vnum)); if ( pRoomIndex != NULL ) { if (IS_SET(pRoomIndex->room_flags, ROOM_PRIVATE) || IS_SET(pRoomIndex->room_flags, ROOM_SOLITARY) || IS_SET(pRoomIndex->room_flags, ROOM_SAFE) || pRoomIndex == victim->in_room) { continue; } for (rch = pRoomIndex->first_person ; rch ; rch = rch->next_in_room) { if (IS_NPC(rch) && rch->pIndexData->pShop != NULL) { break; } } if (rch) { continue; } break; } } act( "$n is banished from existence.", victim, NULL, NULL, TO_ROOM ); if (victim->position == POS_FIGHTING) { stop_fighting(victim, TRUE); } char_from_room( victim ); char_to_room( victim, pRoomIndex->vnum ); if (victim == ch) { send_to_char("You failed and banished yourself from existance.\n\r", victim); } else { send_to_char("You've been banished from existence.\n\r", victim); } do_look( victim, "auto" ); pop_call(); return; } DO_SPELL(spell_teleport) { CHAR_DATA *victim = (CHAR_DATA *) vo; ROOM_INDEX_DATA *pRoomIndex; int attempts; push_call("spell_teleport(%p,%p,%p,%p)",sn,level,ch,vo); victim = ch; if (victim->in_room == NULL || IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(victim->in_room->area->flags, AFLAG_NORECALL) || (!IS_NPC(ch) && victim->fighting != NULL) || (IS_NPC(ch) && saves_spell(level, ch, victim))) { send_to_char( "You failed.\n\r", ch ); pop_call(); return; } for (attempts = 0 ; attempts < 1000 ; attempts++) { pRoomIndex = get_room_index( number_range(1, MAX_VNUM-1)); if(pRoomIndex != NULL) { if(!IS_SET(pRoomIndex->room_flags, ROOM_PRIVATE) && !IS_SET(pRoomIndex->room_flags, ROOM_SOLITARY) && !IS_SET(pRoomIndex->room_flags, ROOM_IS_CASTLE) && !IS_SET(pRoomIndex->room_flags, ROOM_PET_SHOP) && !IS_SET(pRoomIndex->room_flags, ROOM_RIP) && !IS_SET(pRoomIndex->room_flags, ROOM_NO_RECALL) && !IS_SET(pRoomIndex->area->flags, AFLAG_NOTELEPORT) && !IS_SET(pRoomIndex->area->flags, AFLAG_NORECALL) && pRoomIndex->area->average_level*2 < victim->level+15 && pRoomIndex->sector_type != SECT_ETHEREAL && pRoomIndex->sector_type != SECT_ASTRAL && !((!IS_IMMORTAL(victim)) && (victim->level<pRoomIndex->area->low_hard_range || victim->level>pRoomIndex->area->hi_hard_range))) { break; } } } if (attempts >= 1000) { send_to_char("The earth decides you should remain where you are.\n\r", ch); pop_call(); return; } act("$n slowly fades out of existence.", victim, NULL, NULL, TO_ROOM); if (victim->position == POS_FIGHTING && !IS_NPC(ch)) { stop_fighting(victim, TRUE); } char_from_room(victim); char_to_room(victim, pRoomIndex->vnum); act("$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM); do_look(victim, "auto"); pop_call(); return; } DO_SPELL(spell_ventriloquate) { char buf1[MAX_STRING_LENGTH]; char speaker[MAX_INPUT_LENGTH]; CHAR_DATA *vch; push_call("spell_ventriloquate(%p,%p,%p,%p)",sn,level,ch,vo); if( ch->in_room == NULL ) { pop_call(); return; } for( vch = ch->in_room->first_person; vch != NULL; vch=vch->next_in_room ) { if( !IS_NPC( vch ) && vch->level >= 99 ) { sprintf( buf1, "You may not cast that with %s in the room.\n\r", capitalize( vch->name ) ); send_to_char( buf1, ch ); pop_call(); return; } } target_name = one_argument( target_name, speaker ); for ( vch = ch->in_room->first_person; vch != NULL; vch = vch->next_in_room ) { if( vch->position >= POS_RESTING ) { if ( !is_name_short( speaker, vch->name ) ) { if( !saves_spell( level, ch, vch ) ) sprintf( buf1, "%s%s says '%s'\n\r", get_color_string(vch,COLOR_SPEACH,VT102_DIM), capitalize( speaker ), target_name ); else sprintf( buf1, "%sSomeone makes %s say '%s'\n\r", get_color_string(vch,COLOR_SPEACH,VT102_DIM), capitalize(speaker), target_name ); send_to_char( buf1, vch ); } } } pop_call(); return; } DO_SPELL(spell_weaken) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_weaken(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn )) { send_to_char( "They are already weakened.\n\r", ch ); pop_call(); return; } if( saves_spell( level, ch, victim ) ) { send_to_char( "Nothing happens.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level / 10; if(IS_NPC(victim)) { af.location = APPLY_DAMROLL; af.modifier = 0-(level/10)-2; } else { af.location = APPLY_STR; af.modifier = 0-(level/45)-2; } af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "Your strength flows out of your body.\n\r", victim ); if ( ch != victim ) { send_to_char( "They now lost the strength to fight.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_word_of_recall) { push_call("spell_word_of_recall(%p,%p,%p,%p)",sn,level,ch,vo); do_recall( (CHAR_DATA *) vo, NULL ); pop_call(); return; } /* Breath Spells */ DO_SPELL(spell_acid_breath) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_acid_breath(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*3+50, level*6+100); if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_fire_breath) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; int dam; push_call("spell_fire_breath(%p,%p,%p,%p)",sn,level,ch,vo); if (number_percent() < level / 2 && !saves_spell(level, ch, victim)) { for (obj_lose = victim->first_carrying ; obj_lose ; obj_lose = obj_next) { obj_next = obj_lose->next_content; if (number_bits(2) != 0 || obj_lose->first_content) { continue; } switch (obj_lose->item_type) { default: continue; case ITEM_POTION: act("$p bubbles and boils!", victim, obj_lose, NULL, TO_CHAR); break; case ITEM_SCROLL: act("$p crackles and burns!", victim, obj_lose, NULL, TO_CHAR); break; case ITEM_STAFF: act("$p smokes and chars!", victim, obj_lose, NULL, TO_CHAR); break; case ITEM_WAND: act("$p sparks and sputters!", victim, obj_lose, NULL, TO_CHAR); break; case ITEM_FOOD: act("$p blackens and crisps!", victim, obj_lose, NULL, TO_CHAR); break; case ITEM_PILL: act("$p melts and drips!", victim, obj_lose, NULL, TO_CHAR); break; } junk_obj( obj_lose ); } } dam = number_range(level*10, level*12); if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_frost_breath) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; int dam; push_call("spell_frost_breath(%p,%p,%p,%p)",sn,level,ch,vo); if (number_percent() < level && !saves_spell(level, ch, victim)) { for (obj_lose = victim->first_carrying ; obj_lose ; obj_lose = obj_next) { obj_next = obj_lose->next_content; if (number_bits(2) != 0 || obj_lose->first_content) { continue; } switch (obj_lose->item_type) { default: continue; case ITEM_DRINK_CON: case ITEM_POTION: act("$p freezes and shatters!", victim, obj_lose, NULL, TO_CHAR); break; } junk_obj( obj_lose ); } } dam = number_range(level*4, level*18); if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_gas_breath) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_gas_breath(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*8, level*14); if (saves_spell(level, ch, victim)) { dam /= 2; } else { if (number_bits(3) == 0 && !IS_AFFECTED(victim, AFF_POISON)) { AFFECT_DATA af; af.type = gsn_poison; af.location = APPLY_AC; af.modifier = level; af.duration = level/10; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_POISON; affect_to_char( victim, &af ); send_to_char( "You feel poison coursing through your vains.\n\r", victim ); if (ch != victim) { send_to_char( "They now feel your poison.\n\r", ch ); } } } damage(ch, victim, dam, sn); pop_call(); return; } DO_SPELL(spell_lightning_breath) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_lightning_breath(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*6, level*16); if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_psionic_shockwave) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_psionic_shockwave(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*2, level*20); if (saves_spell(level, ch, victim)) { dam /= 2; } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_block_area) { push_call("spell_block_area(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char("You are restricted from blocking this area.\n\r",ch); pop_call(); return; } if (ch->in_room->sector_type < 2 || ch->in_room->sector_type > 4) { send_to_char("The area pulsates with life but no plant life appears.\n\r", ch); pop_call(); return; } if (IS_SET(ch->in_room->room_flags, ROOM_BLOCK)) { send_to_char("The area pulsates with life but nothing new appears.\n\r",ch); pop_call(); return; } SET_BIT(ch->in_room->room_flags, ROOM_BLOCK); if (!del_room_timer(ch->in_room->vnum, ROOM_TIMER_UNBLOCK)) { set_room_timer(ch->in_room->vnum, ROOM_TIMER_BLOCK, level / 2); } act( "All sorts of plant growth sprout up everywhere!", ch, NULL, NULL, TO_ROOM); act( "Your magic fills the area with plant life!", ch, NULL, NULL, TO_CHAR); pop_call(); return; } DO_SPELL(spell_write_spell) { char buf[MAX_INPUT_LENGTH]; char buf2[MAX_INPUT_LENGTH]; OBJ_DATA *scroll; int sn2,i; push_call("spell_write_spell(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_NPC(ch) || multi(ch, sn) == -1) { send_to_char( "You can't do that!\n\r", ch); pop_call(); return; } if ((scroll = get_eq_char(ch, WEAR_HOLD)) == NULL || scroll->item_type != ITEM_SCROLL) { send_to_char("You need to hold the scroll you wish to write upon.\n\r",ch); pop_call(); return; } for (i = 0 ; i < 100 ; i++) { sn2 = number_range(0, MAX_SKILL-1); if (skill_table[sn2].slot <= 0) { continue; } if (!IS_SET(skill_table[sn2].flags, FSKILL_SPELL)) { continue; } if (ch->pcdata->learned[sn2] == 0) { continue; } break; } if (i >= 100) { send_to_char("Your mind goes blank!\n\r", ch); ch->mana = 0; pop_call(); return; } if (level < 21) { sprintf(buf, "a haphazardly written scroll of %s", skill_table[sn2].name); } else if (level < 31) { sprintf(buf, "a decently scribed scroll of %s", skill_table[sn2].name); } else { sprintf(buf, "a skillfully crafted scroll of %s", skill_table[sn2].name); } sprintf(buf2, "scroll %s", skill_table[sn2].name); RESTRING(scroll->name, buf2); RESTRING(scroll->short_descr, buf); RESTRING(scroll->description, buf); scroll->cost = 0; scroll->level = level * 3 / 4; scroll->value[0] = level; scroll->value[1] = sn2; scroll->value[2] = 0; scroll->value[3] = 0; SET_BIT(scroll->extra_flags, ITEM_MODIFIED); act("$n writes what is hoped to be a useful spell.", ch, scroll, NULL, TO_ROOM); act("You enter a trance and.. ..you now hold $p!", ch, scroll, NULL, TO_CHAR); pop_call(); return; } DO_SPELL(spell_homonculous) { MOB_INDEX_DATA *pMob; CHAR_DATA *mh; push_call("spell_homonculous(%p,%p,%p,%p)",sn,level,ch,vo); if (ch->desc == NULL || ch->desc->original != NULL) { send_to_char( "You already are switched into something.\n\r", ch); pop_call(); return; } pMob = get_mob_index( 9900 ); /* Hard coded in emud.are */ mh = create_mobile( pMob ); char_to_room(mh, ch->in_room->vnum); act("A clap of thunder and a small, ugly creature appears!", ch, NULL, NULL, TO_ROOM); act("A clap of thunder and you suddenly feel smaller!", ch, NULL, NULL, TO_CHAR); ch->desc->character = mh; ch->desc->original = ch; mh->desc = ch->desc; ch->desc = NULL; ch->pcdata->switched = TRUE; pop_call(); return; } DO_SPELL(spell_enhance_object) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA af; int stat; push_call("spell_enhance_object(%p,%p,%p,%p)",sn,level,ch,vo); if (obj->owned_by) { send_to_char( "You cannot enhance that object.\n\r", ch); pop_call(); return; } stat = UMIN(1 + (level-1) / 25, 6); switch (obj->item_type) { case ITEM_ARMOR: af.location = APPLY_AC; af.modifier = 0-stat; break; case ITEM_WEAPON: af.location = APPLY_HITROLL; af.modifier = stat; break; default: send_to_char("You cannot enhance that kind of an object.\n\r", ch); pop_call(); return; } obj->owned_by = ch->pcdata->pvnum; SET_BIT(obj->extra_flags, ITEM_MODIFIED); af.type = sn; af.duration = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_obj(obj, &af); char_reset( ch ); act("$p has been enhanced.", ch, obj, NULL, TO_CHAR); pop_call(); return; } DO_SPELL(spell_mage_shield) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_mage_shield(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/3; af.location = APPLY_SAVING_SPELL; af.modifier = -level/5; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n is quickly covered by a shimmering glow.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are quickly covered by a shimmering glow.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_rift) { char buf[MAX_INPUT_LENGTH]; EXIT_DATA *pexit; ROOM_INDEX_DATA *to_room; int door, rip_door; push_call("spell_rift(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_NPC(ch)) { pop_call(); return; } if (!IS_SET(ch->in_room->room_flags, ROOM_RIP)) { send_to_char("You can only create rifts from inside of a rip.\n\r",ch); pop_call(); return; } to_room = get_rift_room(ch, value); /* pick a random exit */ for (rip_door = 0 ; rip_door < 12 ; rip_door++) { door = number_door(); if (ch->in_room->exit[door] && IS_SET(ch->in_room->exit[door]->exit_info, EX_ISDOOR)) { send_to_char("Sorry, only one rift per rip.\n\r", ch); pop_call(); return; } if (to_room->exit[door] == NULL && ch->in_room->exit[rev_dir[door]] == NULL) { rip_door = rev_dir[door]; break; } } if (rip_door == 12) { send_to_char("You failed to open a rift using that wrinkle in this room.\n\r",ch); pop_call(); return; } /* Create 2-way connection */ create_exit(to_room, door); pexit = to_room->exit[door]; RESTRING(pexit->description, "You see a rift in space and time."); pexit->exit_info = EX_RIP; pexit->pvnum = ch->pcdata->pvnum; pexit->to_room = ch->in_room->vnum; create_exit(ch->in_room, rip_door); pexit = ch->in_room->exit[rip_door]; sprintf(buf, "You see a wrinkle in time and space leading toward %s.", to_room->area->name); RESTRING(pexit->description, buf); pexit->to_room = to_room->vnum; ch->in_room->exit[rip_door] = pexit; act("Space and time appear to warp for a split second!", ch, NULL, NULL, TO_ROOM); switch (rip_door) { case DIR_UP: sprintf(buf, "You cause space and time to warp irreparably above you."); break; case DIR_DOWN: sprintf(buf, "You cause space and time to warp irreparably below you."); break; default: sprintf(buf, "You cause space and time to warp irreparably to the %s.", dir_name[rip_door]); break; } act (buf, ch, NULL, NULL, TO_CHAR ); pop_call(); return; } DO_SPELL(spell_rip) { char buf[MAX_INPUT_LENGTH]; EXIT_DATA *pexit; ROOM_INDEX_DATA *pRoomIndex; int door, rip_door, vnum, range; push_call("spell_rip(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_NPC(ch)) { pop_call(); return; } if (!IS_SET(ch->in_room->room_flags, ROOM_RIP)) { if (IS_SET(ch->in_room->room_flags, ROOM_SAFE) || IS_SET(ch->in_room->room_flags, ROOM_NO_RIP) || IS_SET(ch->in_room->area->flags, AFLAG_NORIP) || IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(ch->in_room->area->flags, AFLAG_NORECALL)) { send_to_char("You are prevented from ripping space here!\n\r",ch); pop_call(); return; } } for (door = range = 0 ; door < 6 ; door++) { if (ch->in_room->exit[door] == NULL) { range++; } } if (range == 0) { send_to_char("You failed to find space to create a rip here.\n\r", ch); pop_call(); return; } vnum = number_range(1, range); rip_door = 0; for (door = 0 ; door < 6 ; door++) { if (ch->in_room->exit[door] == NULL) { if (--vnum == 0) { rip_door = door; break; } } } /* find valid vnum */ for (vnum = ROOM_VNUM_RIFT ; vnum < MAX_VNUM && get_room_index(vnum) != NULL ; vnum++); if (vnum >= MAX_VNUM) { send_to_char("You are prevented from ripping up the Realm!\n\r",ch); pop_call(); return; } create_room(vnum); pRoomIndex = room_index[vnum]; sprintf(buf, "Haven a la %s.", ch->name); pRoomIndex->name = STRALLOC(buf); pRoomIndex->area = room_index[ROOM_VNUM_LIMBO]->area; pRoomIndex->vnum = vnum; pRoomIndex->description = STRALLOC("You see an area that defies all description."); pRoomIndex->room_flags = ROOM_RIP|ROOM_NO_MOB|ROOM_INDOORS|ROOM_NO_RECALL|ROOM_NO_SAVE|ROOM_SAFE; pRoomIndex->sector_type = SECT_INSIDE; for (door = 0 ; door < MAX_LAST_LEFT ; door++) { pRoomIndex->last_left[door] = STRDUPE(str_empty); } /* new room exit points to old room */ create_exit(pRoomIndex, rev_dir[rip_door]); pexit = pRoomIndex->exit[rev_dir[rip_door]]; RESTRING(pexit->description, "You see an opening exiting the fabric of space and time."); pexit->to_room = ch->in_room->vnum; create_exit(ch->in_room, rip_door); pexit = ch->in_room->exit[rip_door]; RESTRING(pexit->description, "You see an opening in the fabric of space and time."); pexit->exit_info = EX_RIP; pexit->pvnum = ch->pcdata->pvnum; pexit->to_room = pRoomIndex->vnum; act("$n creates a room of haven $twards.", ch, dir_name[rip_door], NULL, TO_ROOM); ch_printf(ch, "You create a room of haven %swards.\n\r", dir_name[rip_door]); pop_call(); return; } DO_SPELL(spell_envision) { ROOM_INDEX_DATA *rift_room, *temp_room; push_call("spell_envision(%p,%p,%p,%p)",sn,level,ch,vo); rift_room = get_rift_room(ch, value); temp_room = ch->in_room; char_from_room(ch); char_to_room(ch, rift_room->vnum); ch_printf(ch, "Time space coordinates echo through your mind.\n\r"); do_look(ch, ""); char_from_room(ch); char_to_room(ch, temp_room->vnum); pop_call(); return; } DO_SPELL(spell_illusion) { CHAR_DATA *mh, *victim; char illusionname[MAX_INPUT_LENGTH]; int i; push_call("spell_illusion(%p,%p,%p,%p)",sn,level,ch,vo); if (get_pets(ch) > 0) { send_to_char("You have too many pets.\n\r", ch); pop_call(); return; } for (i = 0 ; target_name[i] != '\0' ; i++) { if (ispunct(target_name[i]) || isdigit(target_name[i])) { send_to_char("You failed to create such an abstract illusion.\n\r", ch); pop_call(); return; } } mh = create_mobile( get_mob_index( MOB_VNUM_ILLUSION ) ); char_to_room( mh, ch->in_room->vnum ); mh->level = 3*level/4; mh->npcdata->damnodice = mh->level; mh->npcdata->damsizedice = 2; mh->npcdata->damplus = 3; mh->max_hit = 1; mh->hit = mh->max_hit; if (target_name[0] == '\0') { STRFREE (mh->name); STRFREE (mh->short_descr); STRFREE (mh->long_descr); STRFREE (mh->description); sprintf(illusionname, "%s^", ch->name); mh->name = STRALLOC(illusionname); if (IS_NPC(ch)) { mh->short_descr = STRALLOC(ch->short_descr); } else { mh->short_descr = STRALLOC(ch->name); } mh->long_descr = STRALLOC(ch->long_descr); mh->description = STRALLOC(ch->description); mh->race = ch->race; mh->sex = ch->sex; } else if ((victim = get_char_room(ch, target_name)) != NULL && victim != mh) { for (illusionname[0] = '\0', i = 0 ; victim->name[i] != '\0' ; i++) { if (victim->name[i] == ' ') { strcat(illusionname, "^ "); } else { cat_sprintf(illusionname, "%c", victim->name[i]); } } strcat(illusionname, "^"); STRFREE(mh->name); STRFREE(mh->short_descr); STRFREE(mh->long_descr); STRFREE(mh->description); if (IS_NPC(victim)) { mh->short_descr = STRALLOC(victim->short_descr); } else { mh->short_descr = STRALLOC(victim->name); } mh->name = STRALLOC(illusionname); if (IS_NPC(victim)) { if (victim->long_descr[0] != '\0') { sprintf(illusionname, "%s", ansi_strip(ansi_translate(victim->long_descr))); } else { illusionname[0] = '\0'; } } else { strcpy(illusionname, victim->long_descr); } mh->long_descr = STRALLOC(illusionname); mh->description = STRALLOC(victim->description); mh->race = victim->race; mh->sex = victim->sex; } else { for (illusionname[0] = '\0', i = 0 ; target_name[i] != '\0' ; i++) { if (target_name[i] == ' ') { strcat(illusionname, "^ "); } else { cat_sprintf(illusionname, "%c", target_name[i]); } } strcat(illusionname, "^"); STRFREE (mh->name); STRFREE (mh->short_descr); STRFREE (mh->long_descr); STRFREE (mh->description); mh->name = STRALLOC(illusionname); mh->short_descr = STRALLOC(target_name); mh->long_descr = STRALLOC(""); mh->description = STRALLOC(""); mh->race = ch->race; mh->sex = ch->sex; } SET_BIT( mh->affected_by , AFF_CHARM ); act("$N takes shape before your eyes.",ch,NULL,mh,TO_CHAR); act("$N takes shape before your eyes.",ch,NULL,mh,TO_ROOM); add_follower( mh , ch ); pop_call(); return; } DO_SPELL(spell_winged_call) { CHAR_DATA *mob; push_call("spell_winged_call(%p,%p,%p,%p)",sn,level,ch,vo); if (get_pets(ch) > 0) { send_to_char("You have too many pets.\n\r", ch); pop_call(); return; } mob = create_mobile(mob_index[MOB_VNUM_WINGED_CALL]); char_to_room(mob, ch->in_room->vnum); mob->level = level / 2; mob->npcdata->damnodice = level / 2; mob->npcdata->damsizedice = 2; mob->npcdata->damplus = level / 2; mob->max_hit = level * 5; mob->hit = mob->max_hit; SET_BIT(mob->affected_by , AFF_CHARM); act("You summon $N from the high mountains.", ch, NULL, mob, TO_CHAR); act("$n summons $N from the high mountains.", ch, NULL, mob, TO_ROOM); add_follower(mob, ch); pop_call(); return; } DO_SPELL(spell_mirror_image) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_mirror_image(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "Mirror images can't be compounded!\n\r", ch ); pop_call(); return; } af.type = sn; if (!IS_NPC(ch) && ch->pcdata->mclass[CLASS_SORCERER] > 0) { af.duration = (ch == victim) ? 10 : 5; af.modifier = (ch == victim) ? number_fuzzy(level / 8) : number_fuzzy(level / 20); } else { af.duration = 10; af.modifier = 1 + level / 30; } af.location = APPLY_NONE; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_MIRROR_IMAGE; affect_to_char( victim, &af ); send_to_char("Several of you take a step out and away from yourself.\n\r", victim ); if ( ch != victim ) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_hallucinate) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_hallucinate(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "They can't get any worse!\n\r", ch ); pop_call(); return; } if (IS_AFFECTED(victim, AFF_TRUESIGHT)) { act( "$N sees through the veil on reality you try to impose.", ch, NULL, victim, TO_CHAR ); act( "You see through the veil on reality $n attempts to impose.", ch, NULL, victim, TO_VICT ); pop_call(); return; } af.type = sn; af.duration = level/10; /* Used to be level/31 , longer trip for those halu dudes now :) - Scandum */ af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_HALLUCINATE; affect_to_char( victim, &af ); send_to_char("Wow! You see lot's of pretty colors!\n\r", victim ); if(ch!=victim) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_stability) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_stability(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF_STABILITY)) { send_to_char("They already feel the solidity of the earth.\n\r", ch); pop_call(); return; } af.type = sn; af.duration = level/4; af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_STABILITY; affect_to_char( victim, &af ); send_to_char("The weight of the earth begins to creep into your soul.\n\r", victim ); if (ch != victim) { send_to_char( "You fill their soul with the weight of the earth.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_confusion) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_confusion(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF2_CONFUSION) || saves_spell(level, ch, victim)) { send_to_char( "You cast confusion!\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/30+1; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_CONFUSION; affect_to_char( victim, &af ); send_to_char( "Your eyes shimmer.\n\r", victim ); if (ch != victim) { send_to_char( "You cast confusion!\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_sanctify) { ROOM_INDEX_DATA *room; CHAR_DATA *fch; char buf[MAX_INPUT_LENGTH]; push_call("spell_sanctify(%p,%p,%p,%p)",sn,level,ch,vo); if (ch->in_room == NULL) { pop_call(); return; } room = ch->in_room; if (IS_SET(room->room_flags, ROOM_SAFE)) { send_to_char( "This room is already safe enough.\n\r", ch ); pop_call(); return; } for (fch = room->first_person ; fch ; fch = fch->next_in_room) { if (fch->position == POS_FIGHTING || fch->fighting != NULL) { send_to_char( "There is too much violence in the room to cast sanctify.\n\r", ch ); pop_call(); return; } } /* Can't sanctify the arena. Presto 8-1-98 */ if (ch->in_room->area->low_r_vnum == ROOM_VNUM_ARENA) { send_to_char("The arena may not be sanctified.\n\r", ch); pop_call(); return; } set_room_timer(room->vnum, ROOM_TIMER_SANCTIFY, 1 + level / 5); room->sanctify_char = ch; SET_BIT(room->room_flags, ROOM_SAFE); send_to_char( "The room becomes sanctified, and is a sanctuary for all.\n\r", ch); sprintf(buf, "$n prays to %s and makes this small area a sanctuary to all.", get_god_name(which_god(ch))); act(buf, ch, NULL, NULL, TO_ROOM); pop_call(); return; } DO_SPELL(spell_globe_of_darkness) { push_call("spell_globe_of_darkness(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_GLOBE)) { send_to_char("This room is already shrouded in darkness.\n\r", ch ); pop_call(); return; } if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char( "The darkness dissipates immediately.\n\r", ch ); pop_call(); return; } SET_BIT(ch->in_room->room_flags, ROOM_GLOBE); set_room_timer(ch->in_room->vnum, ROOM_TIMER_GLOBE, 1 + level/20); act("The light around you dissolves into darkness.", ch, NULL, NULL, TO_CHAR); act("The light around you dissolves into darkness.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } DO_SPELL(spell_ice_layer) { push_call("spell_ice_layer(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_ICE)) { send_to_char("This room is already covered by ice.\n\r", ch ); pop_call(); return; } if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char( "The ice melts immediately.\n\r", ch ); pop_call(); return; } switch (ch->in_room->sector_type) { case SECT_ETHEREAL: case SECT_ASTRAL: send_to_char("The ice slowly drifts away into the unknown.\n\r", ch); pop_call(); return; case SECT_UNDER_WATER: send_to_char("The ice slowly floats up toward the surface.\n\r", ch); pop_call(); return; } /* Possible to add duration based on temperature, farenheit to celcius is: -32 times 5 div by 9 */ SET_BIT(ch->in_room->room_flags, ROOM_ICE); set_room_timer(ch->in_room->vnum, ROOM_TIMER_ICE, 1 + level/30); act("Water emerges at your command, freezing into sheets of ice.", ch, NULL, NULL, TO_CHAR); act("Water emerges at $n's command, freezing into sheets of ice.", ch, NULL, NULL, TO_ROOM); pop_call(); return; } DO_SPELL(spell_benediction) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_benediction(%p,%p,%p,%p)",sn,level,ch,vo); if (victim->position == POS_FIGHTING) { send_to_char( "They are fighting.\n\r", ch ); pop_call(); return; } if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } if (ch->level < victim->level*3/4 || ch->level > victim->level*4/3) { ch_printf(ch, "Your god feels that %s is unworthy of your benediction.\n\r", get_name(victim) ); pop_call(); return; } af.type = sn; af.location = APPLY_HIT; af.modifier = level * 4; if (victim != ch) { af.modifier /= 2; } af.duration = level / 8; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); if (victim != ch) { act("You make a sign of benediction over $N's head.", ch, NULL, victim, TO_CHAR); act("$n makes a sign of benediction over your head.", ch, NULL, victim, TO_VICT); } else { act("You make the sign of benediction over your head.", ch, NULL, NULL, TO_CHAR); act("$n makes the sign of benediction over $s head.", ch, NULL, NULL, TO_ROOM); } pop_call(); return; } DO_SPELL(spell_righteous_fury) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_righteous_fury(%p,%p,%p,%p)",sn,level,ch,vo); if ( victim->position == POS_FIGHTING ) { send_to_char( "They are fighting.\n\r", ch ); pop_call(); return; } if( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = number_fuzzy (level /10); af.location = APPLY_HITROLL; af.modifier = number_fuzzy (level / 7); if (victim != ch) { af.modifier /= 2; } af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_DAMROLL; af.modifier = number_fuzzy (level / 8); if (victim != ch) { af.modifier /= 2; } affect_to_char( victim, &af ); if (ch != victim) { act("You invoke the wrath of your god, filling $N with righteous fury.", ch, NULL, victim, TO_CHAR); act("$n invokes the wrath of $s god, filling you with righteous fury.", ch, NULL, victim, TO_VICT); act("$n invokes the wrath of $s god, filling $N with righteous fury.", ch, NULL, victim, TO_NOTVICT); } else { act("You invoke the wrath of your god, filling yourself with divine fury.", ch, NULL, victim, TO_CHAR); act("$n invokes the wrath of $s god, filling $mself with divine fury.", ch, NULL, victim, TO_NOTVICT); } pop_call(); return; } DO_SPELL(spell_soothing_touch) { CHAR_DATA *gch; int heal; push_call("spell_soothing_touch(%p,%p,%p,%p)",sn,level,ch,vo); heal = dice(10, 10) + level*5/2 ; for (gch = ch->in_room->first_person ; gch ; gch = gch->next_in_room) { if (!is_same_group(gch, ch)) { continue; } if (is_safe_magic(ch, gch, sn)) { continue; } gch->hit = UMIN( gch->hit + heal, gch->max_hit ); update_pos( gch ); if (gch != ch) { act("$n's soothing touch makes your wounds close and your pain fade.", ch, NULL, gch, TO_VICT ); } else { act("Your soothing touch makes wounds close and pain fade.", ch, NULL, NULL, TO_CHAR ); } } pop_call(); return; } DO_SPELL(spell_farheal) { CHAR_DATA *victim; int heal; push_call("spell_farheal(%p,%p,%p,%p)",sn,level,ch,vo); if ( ( victim = get_player_world( ch, target_name ) ) == NULL) { send_to_char( "Farheal who ?\n\r", ch); pop_call(); return; } if (!IS_NPC(ch) && ch->pcdata->mclass[ch->class] != ch->level) { send_to_char("You lack the single minded devotion to reach through the void.\n\r", ch); pop_call(); return; } if (victim->in_room == NULL || IS_SET(victim->in_room->room_flags, ROOM_PRIVATE) || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) || victim->in_room->sector_type == SECT_ETHEREAL || victim->in_room->sector_type == SECT_ASTRAL || ch->in_room->sector_type == SECT_ETHEREAL || ch->in_room->sector_type == SECT_ASTRAL || IS_NPC(victim) || victim->fighting != NULL ) { ch_printf(ch, "You can not reach %s through the void.\n\r", get_name(victim)); pop_call(); return; } if (victim == ch) { send_to_char( "You can't farheal yourself!\n\r", ch); pop_call(); return; } if (victim->in_room == ch->in_room) { ch_printf(ch, "%s is in the same room as you!\n\r", get_name(victim)); pop_call(); return; } heal = dice(11, 9) + level; victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); act( "$n reaches through the void to fill you with healing energy.", ch, NULL, victim, TO_VICT ); act ( "You reach through the void to $N, filling $M with healing energy.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } DO_SPELL(spell_holy_word) { push_call("spell_holy word(%p,%p,%p,%p)",sn,level,ch,vo); pop_call(); return; } DO_SPELL(spell_unholy_word) { push_call("spell_unholy_word(%p,%p,%p,%p)",sn,level,ch,vo); pop_call(); return; } DO_SPELL(spell_invigorate) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal, scale_top, scale_bot; char buf[MAX_INPUT_LENGTH]; push_call("spell_invigorate(%p,%p,%p,%p)",sn,level,ch,vo); if( victim==NULL || victim->in_room == NULL || ch->in_room==NULL || victim->in_room != ch->in_room ) { send_to_char( "That person is not here.\n\r", ch ); pop_call(); return; } scale_top = 29; /* The fraction for the hp/mana ratio */ scale_bot = 7; if( value == -1 || value > ch->mana ) value = ch->mana; heal = value * scale_top / scale_bot ; if( victim->move + heal > victim->max_move ) heal = victim->max_move - victim->move ; value = ( heal * scale_bot / scale_top ); sprintf( buf, "Invigorating %d moves for %d mana.\n\r", heal, value + get_mana(ch,sn)); send_to_char( buf, ch); victim->move += heal; ch->mana -= value; send_to_char( "A delicious chill runs up your spine, cleansing the lethargy from your limbs.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_improved_invis) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_improved_invis(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF_IMP_INVISIBLE)) { send_to_char("They are already invisible.\n\r", ch); pop_call(); return; } act( "Something unseen enshrouds $n.", victim, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = number_fuzzy(level / 4); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_IMP_INVISIBLE; affect_to_char( victim, &af ); act("You are enshrouded by something unseen.", victim, NULL, NULL, TO_CHAR); act("$n is enshrouded by something unseen.", victim, NULL, NULL, TO_ROOM); pop_call(); return; } DO_SPELL(spell_truesight) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_truesight(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(ch, AFF_TRUESIGHT)) { send_to_char( "Your eyes already see through the facades of mundane reality.\n\r", ch); pop_call(); return; } if (IS_AFFECTED(ch, AFF_BLIND)) { affect_strip(victim, gsn_blindness); } af.type = sn; af.duration = number_fuzzy(level/4); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_TRUESIGHT; affect_to_char( victim, &af ); send_to_char( "Your eyes gain the ability to see through the facades of mundane reality.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_anti_magic_shell) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_anti_magic_shell(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "You are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = URANGE(2, number_fuzzy(4), 6); af.location = 0; af.modifier = 0; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "The flows of magic recede from your body.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_smoke) { ROOM_INDEX_DATA *room; push_call("spell_smoke(%p,%p,%p,%p)",sn,level,ch,vo); if( ch->in_room == NULL ) { pop_call(); return; } room = ch->in_room; if( IS_SET(room->room_flags, ROOM_SAFE ) ) { send_to_char( "The smoke dissipates immediately.\n\r", ch ); pop_call(); return; } SET_BIT( room->room_flags, ROOM_SMOKE ); set_room_timer(room->vnum, ROOM_TIMER_SMOKE, 1 + level / 10); act( "You conjure up an impenetrable cloud of dark purple smoke.", ch, NULL, NULL, TO_CHAR ); act( "$n conjures up an impenetrable cloud of dark purple smoke.", ch, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_nightmare) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_nightmare(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { act( "$N is still recovering from $S last fright!", ch, NULL, victim, TO_CHAR ); pop_call(); return; } if (IS_EVIL(victim) && saves_spell(level/3, ch, victim)) { act("$N smirks at your feeble attempt to scare $M.", ch, NULL, victim, TO_CHAR ); pop_call(); return; } else if( saves_spell( level, ch, victim ) ) { send_to_char( "Nothing happens.\n\r", ch ); pop_call(); return; } if (IS_NPC(victim) ) { af.type = sn; af.duration = number_fuzzy(level / 5); af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.location = APPLY_DAMROLL; af.modifier = 0-(level/7); affect_to_char( victim, &af ); af.location = APPLY_HITROLL; af.modifier = 0-(level/7); affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = number_fuzzy(level/7); affect_to_char( victim, &af ); } else { af.type = sn; af.duration = number_fuzzy(level/21); af.bitvector = 0; af.bittype = AFFECT_TO_NONE; af.location = APPLY_STR; af.modifier = 0 - number_fuzzy(level/21); affect_to_char( victim, &af ); af.location = APPLY_DEX; af.modifier = 0 - number_fuzzy(level/14); affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = number_fuzzy(level/7); affect_to_char( victim, &af ); } if (ch != victim) { ch_printf(victim, "A nightmarish apparition flies from %s's hands towards your face!\n\r", get_name(ch) ); ch_printf(ch, "A nightmarish apparition flies from your hands towards %s's face!\n\r", get_name(victim) ); } else { send_to_char("Ok.\n\r", ch); } damage( ch, victim, number_range(level/2, level*2), sn); pop_call(); return; } DO_SPELL(spell_possess) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_posses(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char("You are forbidden from casting that here.\n\r", ch); pop_call(); return; } if (IS_NPC(ch) || ch->desc->original) { send_to_char("You are not in your original state.\n\r", ch); pop_call(); return; } if (victim == ch) { send_to_char("You already have control over yourself.\n\r", ch); pop_call(); return; } if (!IS_NPC(victim) || !can_mass_cast(ch, victim)) { send_to_char("They seem to be unaffected by your magic.\n\r", ch); pop_call(); return; } if (victim->desc) { ch_printf(ch, "%s is already possessed.\n\r", victim->short_descr); pop_call(); return; } if (IS_AFFECTED(victim, AFF2_POSSESS) || level / 2 < victim->level || saves_spell(level/2, ch, victim)) { act("$N is unhappy with that you tried to seize control of $S brain.", ch, NULL, victim, TO_CHAR); multi_hit(victim, ch, TYPE_UNDEFINED); pop_call(); return; } SET_BIT(victim->act,ACT_SENTINEL); REMOVE_BIT(victim->act, ACT_AGGRESSIVE); af.type = sn; af.duration = 12; af.location = 0; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_POSSESS; affect_to_char( victim, &af ); log_printf("%s has possessed %s",get_name(ch), victim->short_descr); ch->desc->character = victim; ch->desc->original = ch; victim->desc = ch->desc; ch->desc = NULL; ch->pcdata->switched = TRUE; ch_printf(victim, "You have possessed %s.\n\r", get_name(victim)); pop_call(); return; } DO_SPELL(spell_transport) { CHAR_DATA *victim; char arg3[MAX_STRING_LENGTH]; OBJ_DATA *obj; push_call("spell_transport(%p,%p,%p,%p)",sn,level,ch,vo); target_name = one_argument(target_name, arg3 ); if ((victim = get_player_world(ch, target_name)) == NULL || victim == ch || IS_SET(victim->in_room->room_flags, ROOM_PRIVATE) || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) || victim->in_room->sector_type == SECT_ASTRAL || victim->in_room->sector_type == SECT_ETHEREAL || IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(ch->in_room->area->flags, AFLAG_NORECALL) || victim->level >= level + 15 || (IS_NPC(victim) && saves_spell( level, ch, victim )) ) { send_to_char("Your transport spell failed!\n\r", ch); pop_call(); return; } if (victim->in_room == ch->in_room) { send_to_char("They are right beside you!", ch); pop_call(); return; } if ((obj = get_obj_carry(ch, arg3)) == NULL || (victim->carry_weight + get_obj_weight (obj)) > can_carry_w(victim)) { send_to_char( "Your transport spell failed!\n\r", ch); pop_call(); return; } if (IS_OBJ_STAT(obj, ITEM_NODROP)) { send_to_char( "You can't seem to let go of it.\n\r", ch ); pop_call(); return; } act( "$p slowly dematerializes...", ch, obj, NULL, TO_CHAR ); act( "$p slowly dematerializes from $n's hands..", ch, obj, NULL, TO_ROOM ); obj_from_char( obj ); obj_to_char( obj, victim ); act( "$p from $n appears in your hands!", ch, obj, victim, TO_VICT); act( "$p appears in $n's hands!", victim, obj, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_slow) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_slow(%p,%p,%p,%p)",sn,level,ch,vo); if(IS_SET(ch->in_room->room_flags, ROOM_SAFE)) { send_to_char("You are forbidden from casting that here.\n\r", ch); pop_call(); return; } if( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } if ( IS_AFFECTED(victim, AFF_HASTE) ) { REMOVE_BIT(victim->act, AFF_HASTE); } act( "$n slows down.", victim, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = number_fuzzy(level/9); af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); victim->speed = UMIN(victim->speed, get_max_speed(victim)); send_to_char( "You slow down.\n\r", victim ); if ( ch != victim ) send_to_char( "Ok.\n\r", ch ); pop_call(); return; } DO_SPELL(spell_brew_potion) { char buf[MAX_INPUT_LENGTH]; char buf2[MAX_INPUT_LENGTH]; OBJ_DATA *potion; int sn2,i; push_call("spell_brew_potion(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_NPC(ch) || multi(ch, sn) == -1) { send_to_char( "You can't do that!\n\r", ch); pop_call(); return; } if ((potion = get_eq_char(ch, WEAR_HOLD)) == NULL || potion->item_type != ITEM_POTION) { send_to_char("You need to hold a vial for the potion you shall brew.\n\r", ch); pop_call(); return; } for (i = 0 ; i < 100 ; i++) { sn2 = number_range(0, MAX_SKILL -1); if (skill_table[sn2].slot <= 0) { continue; } if (!IS_SET(skill_table[sn2].flags, FSKILL_SPELL)) { continue; } if (ch->pcdata->learned[sn2] == 0) { continue; } break; } if (i >= 100) { send_to_char("Your mind goes blank!\n\r",ch); ch->mana = 0; pop_call(); return; } if (level < 51) { sprintf(buf, "a murky potion of %s", skill_table[sn2].name); sprintf(buf2, "murky potion %s", skill_table[sn2].name); } else if (level < 61) { sprintf(buf, "a cloudy potion of %s", skill_table[sn2].name); sprintf(buf2, "cloudy potion %s", skill_table[sn2].name); } else { sprintf(buf, "a clear potion of %s", skill_table[sn2].name); sprintf(buf2, "clear potion %s", skill_table[sn2].name); } RESTRING(potion->name, buf2); RESTRING(potion->short_descr, buf); RESTRING(potion->long_descr, ""); RESTRING(potion->description, buf); potion->cost = 0; potion->level = level * 3 / 4; potion->value[0] = level; potion->value[1] = sn2; potion->value[2] = 0; potion->value[3] = 0; SET_BIT(potion->extra_flags, ITEM_MODIFIED); act("$n brews up a potion.", ch, potion, NULL, TO_ROOM); act("You enter a trance and... ...you now hold $p!", ch, potion, NULL, TO_CHAR); pop_call(); return; } DO_SPELL(spell_elemental) { MOB_INDEX_DATA *pMob; CHAR_DATA *mh; push_call("spell_elemental(%p,%p,%p,%p)",sn,level,ch,vo); if (get_pets(ch) > 0) { send_to_char( "You have too many pets.\n\r", ch); pop_call(); return; } switch (ch->in_room->sector_type) { case SECT_LAVA: send_to_char( "A fiery shape emerges from the flames to do your bidding.\n\r", ch ); pMob = get_mob_index(MOB_VNUM_FIRE_ELEMENTAL); break; case SECT_LAKE: case SECT_RIVER: case SECT_OCEAN: case SECT_UNDER_WATER: send_to_char( "A ripple in the water forms into a man sized shape.\n\r", ch ); pMob = get_mob_index(MOB_VNUM_WATER_ELEMENTAL); break; case SECT_AIR : send_to_char( "A blast of wind circles you, ready to do your bidding.\n\r", ch ); pMob = get_mob_index(MOB_VNUM_AIR_ELEMENTAL); break; case SECT_FOREST : case SECT_DESERT : case SECT_MOUNTAIN : case SECT_HILLS : case SECT_UNDER_GROUND : case SECT_DEEP_EARTH : send_to_char( "A large mound of earth rises up out of the ground to do your bidding.\n\r", ch ); pMob = get_mob_index(MOB_VNUM_EARTH_ELEMENTAL); break; default : send_to_char( "No elementals appear to do your bidding.\n\r", ch ); pop_call(); return; } if (pMob == NULL) { send_to_char( "You cannot create an elemental now.\n\r", ch ); pop_call(); return; } mh = create_mobile( pMob ); char_to_room( mh, ch->in_room->vnum ); mh->level = level * 1 / 2; mh->npcdata->damnodice = mh->level / 2; mh->npcdata->damsizedice = 2; mh->npcdata->damplus = 7; mh->max_hit = 30 + level * 5; mh->hit = 30 + level * 5; SET_BIT( mh->affected_by , AFF_CHARM ); add_follower( mh , ch ); if (ch->fighting != NULL) { multi_hit(mh, ch->fighting->who, TYPE_UNDEFINED); } pop_call(); return; } DO_SPELL(spell_unbarring_ways) { int door; ROOM_INDEX_DATA *to_room; EXIT_DATA *pexit; EXIT_DATA *pexit_rev; push_call("spell_unbarring_ways(%p,%p,%p,%p)",sn,level,ch,vo); if (target_name[0] == '\0') { send_to_char( "What direction do you wish to cast this spell in?\n\r", ch); pop_call(); return; } if ((door = find_door(ch, target_name)) >= 0) { pexit = ch->in_room->exit[door]; if (pexit == NULL) { send_to_char( "There is no door in that direction.\n\r", ch); pop_call(); return; } if (IS_SET(pexit->exit_info, EX_MAGICPROOF)) { send_to_char( "It remains firm.\n\r", ch ); pop_call(); return; } REMOVE_BIT(pexit->exit_info, EX_LOCKED); REMOVE_BIT(pexit->exit_info, EX_CLOSED); SET_BIT (pexit->exit_info, EX_UNBARRED); if ((to_room = room_index[pexit->to_room]) != NULL && (pexit_rev = to_room->exit[rev_dir[door]]) != NULL && room_index[pexit_rev->to_room] == ch->in_room ) { REMOVE_BIT( pexit_rev->exit_info, EX_LOCKED); REMOVE_BIT( pexit_rev->exit_info, EX_CLOSED); SET_BIT ( pexit_rev->exit_info, EX_UNBARRED); } act( "$n causes the $d to dissolve.", ch, NULL, pexit->keyword, TO_ROOM ); act( "You cause the $d to dissolve.", ch, NULL, pexit->keyword, TO_CHAR ); } else { send_to_char("There's no valid target in that direction!\n\r", ch); } pop_call(); return; } DO_SPELL(spell_fire_shield) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_fire_shield(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/10; af.location = 0; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_FIRESHIELD; affect_to_char( victim, &af ); act( "$n bursts into flame!", victim, NULL, NULL, TO_ROOM ); send_to_char( "You burst into flame!\n\r", victim ); pop_call(); return; } DO_SPELL(spell_recharge) { OBJ_DATA *obj = (OBJ_DATA *) vo; push_call("spell_recharge(%p,%p,%p,%p)",sn,level,ch,vo); if (obj->item_type == ITEM_STAFF || obj->item_type == ITEM_WAND) { if (obj->value[2] == obj->value[1] || obj->value[1] > (obj->pIndexData->value[1] * 4)) { act( "$p bursts into flames, injuring you!", ch, obj, NULL, TO_CHAR ); act( "$p bursts into flames, charring $n!", ch, obj, NULL, TO_ROOM); junk_obj(obj); damage(ch, ch, obj->level * 2, TYPE_UNDEFINED); pop_call(); return; } if ( number_percent() <=2) { act( "$p glows with a blinding magical luminescence.", ch, obj, NULL, TO_CHAR); obj->value[1] *= 2; obj->value[2] = obj->value[1]; pop_call(); return ; } else if ( number_percent() <=5 ) { act( "$p glows brightly for a few seconds...", ch, obj, NULL, TO_CHAR); obj->value[2] = obj->value[1]; pop_call(); return; } else if (number_percent() <= 10 ) { act( "$p disintegrates into a void.", ch, obj, NULL, TO_CHAR); act( "$n's attempt at recharging fails, and $p disintegrates.", ch, obj, NULL, TO_ROOM); junk_obj(obj); pop_call(); return; } else if (number_percent() <= 10 + level / 4) { send_to_char("Nothing happens.\n\r", ch); pop_call(); return; } else { act( "$p feels warm to the touch.", ch, obj, NULL, TO_CHAR); --obj->value[1]; obj->value[2] = obj->value[1]; pop_call(); return; } } else { send_to_char( "You can't recharge that!\n\r", ch); pop_call(); return; } pop_call(); return; } DO_SPELL(spell_vampiric_touch) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_vampiric_touch(%p,%p,%p,%p)",sn,level,ch,vo); if (check_hit(ch, victim, 0, gsn_vampiric_touch)) { dam = number_fuzzy(number_range(level*3, level*5)); ch->hit = UMIN(ch->max_hit, ch->hit+dam/10); damage( ch, victim, dam, sn ); } else { act( "$n's hand glows with dark energy, but fails to strike $s foe.", ch, NULL, victim, TO_ROOM ); act( "The dark energies in your hand fail to strike $N.", ch, NULL, victim, TO_CHAR ); } pop_call(); return; } DO_SPELL(spell_windblast) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_windblast(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*3, level*5); if ( saves_spell( level, ch, victim ) ) dam /= 2; damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_waterburst) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_waterburst(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*2, level*6); if ( saves_spell( level, ch, victim ) ) dam /= 2; damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_mindblast) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_mindblast(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*1, level*7); if ( saves_spell( level, ch, victim ) ) dam /= 2; damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_snake_dart) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; push_call("spell_mindblast(%p,%p,%p,%p)",sn,level,ch,vo); dam = number_range(level*1, level*7); if (saves_spell(level, ch, victim)) { dam /= 2; } else { if (number_bits(3) == 0 && !IS_AFFECTED(victim, AFF_POISON)) { AFFECT_DATA af; af.type = gsn_poison; af.location = APPLY_AC; af.modifier = level/2; af.duration = level/20; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF_POISON; affect_to_char( victim, &af ); send_to_char( "You feel poison coursing through your vains.\n\r", victim ); if (ch != victim) { send_to_char( "They now feel your poison.\n\r", ch ); } } } damage( ch, victim, dam, sn ); pop_call(); return; } DO_SPELL(spell_metamorphose_liquids) { OBJ_DATA *obj = (OBJ_DATA *)vo; char arg3[MAX_INPUT_LENGTH]; int liquid; push_call("spell_metamorphose_liquids(%p,%p,%p,%p)",sn,level,ch,vo); if (obj == NULL) { send_to_char("You are not carrying that.\n\r",ch); pop_call(); return; } target_name = one_argument(target_name, arg3); target_name = one_argument(target_name, arg3); if (obj->item_type != ITEM_DRINK_CON) { send_to_char("That is not a drinkcontainer.\n\r",ch); pop_call(); return; } if (!strlen(arg3)) { send_to_char("Metamorphose to what kind of liquid?\n\r",ch); pop_call(); return; } for (liquid = 0 ; liquid < LIQ_MAX ; liquid++) { if (!str_prefix(arg3, liq_table[liquid].liq_name)) { break; } } if (liquid == LIQ_MAX) { send_to_char("There is no such liquid.\n\r", ch); pop_call(); return; } if (obj->value[2] == liquid) { ch_printf(ch, "%s is already filled with %s\n\r", capitalize(obj->short_descr), liq_table[liquid].liq_name); pop_call(); return; } else { ch_printf(ch, "You transform the %s in %s to %s.\n\r", liq_table[obj->value[2]].liq_name, obj->short_descr, liq_table[liquid].liq_name); obj->value[2] = liquid; } pop_call(); return; } DO_SPELL(spell_detect_good) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_detect_good(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "Traces of gold outline all good in plain sight.\n\r", victim ); if (ch != victim) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_firewalk) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; push_call("spell_firewalk(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_NPC(victim)) { send_to_char("You cannot cast this spell on mobs.\n",ch); pop_call(); return; } if (IS_AFFECTED(victim, AFF2_FIREWALK)) { send_to_char("They are already affected.\n\r", ch); pop_call(); return; } af.type = sn; af.duration = level/2; af.location = 0; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_FIREWALK; affect_to_char(victim, &af); act( "$n's feet glow a soft red.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your feet tingle.\n\r", victim ); pop_call(); return; } DO_SPELL(spell_divine_inspiration) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; push_call("spell_divine_inspiration(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_NPC(victim)) { send_to_char("You cannot cast this spell on mobs.\n",ch); pop_call(); return; } if (IS_AFFECTED(victim, AFF2_DIVINE_INSPIRATION)) { send_to_char("They are already affected.\n\r", ch); pop_call(); return; } af.type = sn; af.location = APPLY_INT; if (which_god(victim) != GOD_HYPNOS) { af.duration = URANGE(2, level/10, 8); af.modifier = 1 + (level > 49) + (level > 99); } else { af.duration = URANGE(8, level/5, 32); af.modifier = 1 + (level > 24) + (level > 49) + (level > 74) + (level > 99) + (level > 124); } af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_DIVINE_INSPIRATION; affect_to_char(victim, &af); act( "$n's eyes shine brightly.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your eyes shine brightly as divine inspiration sharpens your mind.\n\r", victim); pop_call(); return; } DO_SPELL(spell_black_aura) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_black_aura(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } if (saves_spell(4*level/5, ch, victim)) { act("Your shadow magic slithers around $N but fails to enshroud $M.", ch, NULL, victim, TO_CHAR); pop_call(); return; } af.type = sn; af.duration = number_range(0, level/70); af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n is surrounded by a black aura.", victim, NULL, NULL, TO_ROOM ); send_to_char( "A bitter cloud of darkness envelopes you.\n\r", victim); pop_call(); return; } DO_SPELL(spell_mana_shield) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_mana_shield(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/4; af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act( "A shield of sparkling blue energy coalesces around $n.", victim, NULL, NULL, TO_ROOM ); send_to_char( "A shield of sparkling blue energy coalesces around you.\n\r", victim); pop_call(); return; } DO_SPELL(spell_magic_mirror) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_magic_mirror(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/4; af.modifier = 0; af.location = APPLY_NONE; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act( "A shield of reflective magic coalesces around $n.", victim, NULL, NULL, TO_ROOM ); send_to_char( "A shield of reflective magic coalesces around you.\n\r", victim); pop_call(); return; } DO_SPELL(spell_animate_object) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf, af; CHAR_DATA *mob; char animatename[MAX_INPUT_LENGTH]; int i; push_call("spell_animte_object(%p,%p,%p,%p)",sn,level,ch,vo); if (!IS_NPC(ch) && multi(ch, sn) == -1) { send_to_char( "You can't do that!\n\r", ch); pop_call(); return; } if (obj->carried_by != ch || obj->wear_loc != WEAR_NONE) { send_to_char( "You are not carrying that.\n\r", ch); pop_call(); return; } if (obj->level > level) { send_to_char("You failed.\n\r", ch); pop_call(); return; } if (get_pets(ch) > 0) { send_to_char("You have too many pets.\n\r", ch); pop_call(); return; } mob = create_mobile( get_mob_index( MOB_VNUM_ILLUSION ) ); char_to_room( mob, ch->in_room->vnum ); mob->level = obj->level; mob->npcdata->damnodice = 0; mob->npcdata->damsizedice = 0; mob->npcdata->damplus = mob->level; if (obj->item_type == ITEM_WEAPON) { mob->max_hit = 100; } else { mob->max_hit = UMAX(200, mob->level * 20); } mob->hit = mob->max_hit; for (animatename[0] = '\0', i = 0 ; obj->name[i] != '\0' ; i++) { if (obj->name[i] == ' ') { strcat(animatename, "^ "); } else { cat_sprintf(animatename, "%c", obj->name[i]); } } strcat(animatename, "^"); RESTRING(mob->name, animatename); RESTRING(mob->short_descr, obj->short_descr); RESTRING(mob->long_descr, obj->long_descr); RESTRING(mob->description, obj->description); REMOVE_BIT(mob->act, ACT_RACE); REMOVE_BIT(mob->act, ACT_SMART); mob->sex = SEX_NEUTRAL; mob->race = RACE_HUMAN; mob->gold = obj->cost/2; af.type = sn; af.duration = -1; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; for (paf = obj->first_affect ; paf ; paf = paf->next) { switch (paf->location) { case APPLY_STR: mob->npcdata->damplus += paf->modifier * 10; break; case APPLY_DAMROLL: mob->npcdata->damplus += paf->modifier * 5; break; case APPLY_HIT: case APPLY_CON: mob->hit = mob->max_hit = UMAX(100, mob->max_hit + paf->modifier * 10); break; case APPLY_MANA: case APPLY_WIS: mob->mana = mob->max_mana = UMAX(100, mob->max_mana + paf->modifier * 10); break; case APPLY_MOVE: mob->move = mob->max_move = UMAX(100, mob->max_move + paf->modifier * 10); break; case APPLY_DEX: af.modifier = paf->modifier * 20; af.location = APPLY_AC; affect_to_char(mob, &af); break; case APPLY_AC: af.modifier = paf->modifier * 10; af.location = APPLY_AC; affect_to_char(mob, &af); break; case APPLY_HITROLL: mob->hitroll += paf->modifier * 5; break; case APPLY_SAVING_PARA: case APPLY_SAVING_ROD: case APPLY_SAVING_PETRI: case APPLY_SAVING_BREATH: case APPLY_SAVING_SPELL: case APPLY_INT: mob->saving_throw += paf->modifier * 5; break; } } for (paf = obj->pIndexData->first_affect ; paf ; paf = paf->next) { switch (paf->location) { case APPLY_STR: mob->npcdata->damplus += paf->modifier * 10; break; case APPLY_DAMROLL: mob->npcdata->damplus += paf->modifier * 5; break; case APPLY_HIT: case APPLY_CON: mob->hit = mob->max_hit = UMAX(100, mob->max_hit + paf->modifier * 10); break; case APPLY_MANA: case APPLY_WIS: mob->mana = mob->max_mana = UMAX(100, mob->max_mana + paf->modifier * 10); break; case APPLY_MOVE: mob->move = mob->max_move = UMAX(100, mob->max_move + paf->modifier * 10); break; case APPLY_DEX: af.modifier = paf->modifier * 20; af.location = APPLY_AC; affect_to_char(mob, &af); break; case APPLY_AC: af.modifier = paf->modifier * 10; af.location = APPLY_AC; affect_to_char(mob, &af); break; case APPLY_HITROLL: mob->hitroll += paf->modifier * 5; break; case APPLY_SAVING_PARA: case APPLY_SAVING_ROD: case APPLY_SAVING_PETRI: case APPLY_SAVING_BREATH: case APPLY_SAVING_SPELL: case APPLY_INT: mob->saving_throw += paf->modifier * 5; break; } } if (obj->item_type == ITEM_ARMOR) { af.modifier = obj->value[0] * -10; af.location = APPLY_AC; affect_to_char(mob, &af); } if (IS_OBJ_STAT(obj, ITEM_INVIS)) { SET_BIT(mob->affected_by, AFF_IMP_INVISIBLE); } if (IS_OBJ_STAT(obj, ITEM_BLESS)) { mob->alignment = 1000; } if (IS_OBJ_STAT(obj, ITEM_EVIL)) { mob->alignment = -1000; } while (obj->first_content != NULL) { obj_to_char(obj->first_content, mob); } act("$N flies from your hand and bows before you.", ch, NULL, mob, TO_CHAR); act("$N flies from $n's hand and bows before $m.", ch, NULL, mob, TO_ROOM); SET_BIT(mob->affected_by, AFF_CHARM ); add_follower( mob, ch ); if (IS_SET(obj->extra_flags, ITEM_MOUNT)) { SET_BIT( mob->act, ACT_MOUNT ); } REMOVE_BIT(obj->extra_flags, ITEM_ANTI_GOOD); REMOVE_BIT(obj->extra_flags, ITEM_ANTI_EVIL); REMOVE_BIT(obj->extra_flags, ITEM_ANTI_NEUTRAL); SET_BIT(obj->extra_flags, ITEM_ETHEREAL); SET_BIT(obj->extra_flags, ITEM_NOREMOVE); SET_BIT(obj->extra_flags, ITEM_NODROP); SET_BIT(obj->extra_flags, ITEM_INVENTORY); switch (obj->item_type) { case ITEM_WEAPON: obj_to_char(obj, mob); equip_char(mob, obj, WEAR_WIELD); break; case ITEM_LIGHT: obj_to_char(obj, mob); equip_char(mob, obj, WEAR_LIGHT); break; default: if (IS_SET(obj->wear_loc, ITEM_WEAR_SHIELD)) { obj_to_char(obj, mob); equip_char(mob, obj, WEAR_SHIELD); } else { junk_obj(obj); } break; } pop_call(); return; } DO_SPELL(spell_mana_shackles) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_mana_shackles(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char( "They are already shackled.\n\r", ch ); pop_call(); return; } if ( saves_spell( level, ch, victim ) ) { act("Strings of lightning shoot from your hands but fail to entangle $N.", ch, NULL, victim, TO_CHAR); act("Strings of lightning shoot from $n's hands but fail to entangle you.", ch, NULL, victim, TO_VICT); act("Strings of lightning shoot from $n's hands but fail to entangle $N.", ch, NULL, victim, TO_NOTVICT); pop_call(); return; } af.type = sn; af.duration = level/15; af.bittype = AFFECT_TO_NONE; af.bitvector = 0; af.location = APPLY_NONE; af.modifier = 0; affect_to_char( victim, &af ); act("Strings of lightning shoot from your hands, entangling $N.", ch, NULL, victim, TO_CHAR); act("Strings of lightning shoot from $n's hands, entangling you.", ch, NULL, victim, TO_VICT); act("Strings of lightning shoot from $n's hands, entangling $N.", ch, NULL, victim, TO_NOTVICT); pop_call(); return; } DO_SPELL(spell_earthbind) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_earthbind(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF2_EARTHBIND)) { send_to_char("They are already bound to the earth.\n\r", ch); pop_call(); return; } if (saves_spell(level, ch, victim)) { act("Your shadow magic slithers around $N but fails to bind $M.", ch, NULL, victim, TO_CHAR); pop_call(); return; } send_to_char("You have been bound to the earth.\n\r", victim); if (ch != victim) { send_to_char("You bind them to the earth.\n\r", ch); } if (CAN_FLY(victim)) { act("You fall to the ground.", ch, NULL, victim, TO_VICT); act("$n falls to the ground.", victim, NULL, ch, TO_ROOM); damage(ch, victim, number_range(level, level*3), sn); } affect_strip(victim, gsn_fly); af.type = sn; af.location = APPLY_NONE; af.modifier = 0; af.duration = 1+level/5; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_EARTHBIND; affect_to_char( victim, &af ); pop_call(); return; } DO_SPELL(spell_quicken) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_quicken(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF2_QUICKEN)) { send_to_char("They are already quick of mind.\n\r", ch); pop_call(); return; } act( "$n's eyes glitter as time wrinkles then slows to quicken $s mind.", victim, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = 12; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_QUICKEN; affect_to_char( victim, &af ); send_to_char( "Time wrinkles then slows as your thoughts start racing.\n\r", victim ); if (ch != victim) { send_to_char( "Ok.\n\r", ch ); } pop_call(); return; } DO_SPELL(spell_torrid_balm) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_torrid_balm(%p,%p,%p,%p)",sn,level,ch,vo); if (IS_AFFECTED(victim, AFF2_TORRID_BALM)) { send_to_char( "They are already engulfed by fire.\n\r", ch ); pop_call(); return; } if (saves_spell(level, ch, victim)) { send_to_char( "Flames ignite from your hands, but fail to surround your foe.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level / 20; af.location = IS_NPC(victim) ? APPLY_AC : APPLY_DEX; af.modifier = 0; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_TORRID_BALM; affect_to_char(victim, &af ); if (ch != victim) { act("Flames ignite from your hands, engulfing $N.", ch, NULL, victim, TO_CHAR); act("Flames ignite from $n's hands, engulfing you.", ch, NULL, victim, TO_VICT); act("Flames ignite from $n's hands, engulfing $N.", ch, NULL, victim, TO_NOTVICT); } else { act("Flames ignite from your hands, engulfing yourself.", ch, NULL, victim, TO_CHAR); act("Flames ignite from $n's hands, engulfing $mself.", ch, NULL, victim, TO_NOTVICT); } pop_call(); return; } DO_SPELL(spell_song_of_the_seas) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; push_call("spell_song_of_the_seas(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char("They are already affected.\n\r", ch); pop_call(); return; } af.type = sn; af.location = APPLY_WIS; if (which_god(victim) != GOD_ULMO) { af.duration = URANGE(2, level/10, 8); af.modifier = 1 + (level > 49) + (level > 99); } else { af.duration = URANGE(8, level/5, 32); af.modifier = 1 + (level > 24) + (level > 49) + (level > 74) + (level > 99) + (level > 124); } af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char(victim, &af); send_to_char( "Your eyes shine sagaciously as the song of the seas guides your path.\n\r", victim); act( "$n's eyes shine sagaciously.", victim, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_earthen_spirit) { CHAR_DATA *victim = (CHAR_DATA *)vo; AFFECT_DATA af; push_call("spell_earthen_spirit(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char("They are already affected.\n\r", ch); pop_call(); return; } af.type = sn; af.location = APPLY_CON; if (which_god(victim) != GOD_GAIA) { af.duration = URANGE(2, level/10, 8); af.modifier = 1 + (level > 49) + (level > 99); } else { af.duration = URANGE(8, level/5, 32); af.modifier = 1 + (level > 24) + (level > 49) + (level > 74) + (level > 99) + (level > 124); } af.bittype = AFFECT_TO_NONE; af.bitvector = 0; affect_to_char(victim, &af); send_to_char("The spirit of the earth swirls around you.\n\r", victim); act( "The spirit of the earth swirls around $n", victim, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_icicle_armor) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_icicle_armor(%p,%p,%p,%p)",sn,level,ch,vo); if (is_affected(victim, sn)) { send_to_char("You are already encased in an icicle armor.\n\r", ch); pop_call(); return; } af.type = sn; af.duration = level; af.modifier = -1 * UMAX(1, level / 15) * 5; af.location = APPLY_AC; af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_ICICLE_ARMOR; affect_to_char(victim, &af); send_to_char("Spikes of ice rip through your skin, encasing you in armor.\n\r", victim); act("Spikes of ice rip through $n's skin, encasing $m in armor.", victim, NULL, NULL, TO_ROOM ); pop_call(); return; } DO_SPELL(spell_flamewave) { CHAR_DATA *vch; CHAR_DATA *vch_next; EXIT_DATA *pexit; int door, temp_vnum; push_call("spell_flamewave(%p,%p,%p,%p)",sn,level,ch,vo); /* no flamewave under water */ if (ch->in_room->sector_type == SECT_UNDER_WATER) { send_to_char("The water boils around you.\n\r",ch); pop_call(); return; } switch (ch->in_room->sector_type) { case SECT_LAKE: case SECT_RIVER: case SECT_OCEAN: level /= 2; } act("Tongues of fire and flame spew forth by your command!", ch, NULL, NULL, TO_CHAR); act("Tongues of fire and flame spew forth by $n's command.", ch, NULL, NULL, TO_ROOM); temp_vnum = ch->in_room->vnum; for (door = 0 ; door <= 5 ; door++) { if ((pexit = get_exit(temp_vnum, door)) && pexit->to_room != temp_vnum) { ch->in_room = room_index[pexit->to_room]; act("The air about you sears with heat.", ch, NULL, NULL, TO_ROOM); } } ch->in_room = room_index[temp_vnum]; for (vch = ch->in_room->last_person ; vch ; vch = vch_next) { vch_next = vch->prev_in_room; if (!can_mass_cast(ch, vch)) { continue; } damage( ch, vch, level + dice(1, 50), sn ); } pop_call(); return; } DO_SPELL(spell_flame_blade) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA af; push_call("spell_flame_blade(%p,%p,%p,%p)",sn,level,ch,vo); if (obj->item_type != ITEM_WEAPON) { act("You can only imbue weapons with fire.", ch, NULL, NULL, TO_CHAR); pop_call(); return; } if (IS_SET(obj->extra_flags, ITEM_BURNING)) { act("$p is already burning.", ch, obj, NULL, TO_CHAR); pop_call(); return; } if (number_fuzzy(obj->level) >= level) { act("$p glows brightly, then returns to normal.", ch, obj, NULL, TO_CHAR); act("$p glows brightly, then returns to normal.", ch, obj, NULL, TO_ROOM); pop_call(); return; } SET_BIT(obj->extra_flags, ITEM_MODIFIED); SET_BIT(obj->extra_flags, ITEM_MAGIC); act("Blue flames ignite from $p.", ch, obj, NULL, TO_CHAR); act("Blue flames ignite from $p.", ch, obj, NULL, TO_ROOM); af.type = sn; af.duration = level * 5; af.location = APPLY_NONE; af.modifier = 0; af.bittype = AFFECT_TO_OBJ; af.bitvector = ITEM_BURNING; affect_to_obj(obj, &af); pop_call(); return; } DO_SPELL(spell_totem) { OBJ_DATA *totem; push_call("spell_totem(%p,%p,%p,%p)",sn,level,ch,vo); for (totem = ch->in_room->first_content ; totem ; totem = totem->next_content) { if (totem->item_type == ITEM_TOTEM) { send_to_char("There is already a totem in this room.\n\r", ch); pop_call(); return; } } switch (ch->in_room->sector_type) { case SECT_AIR: case SECT_ETHEREAL: case SECT_ASTRAL: case SECT_LAKE: case SECT_RIVER: case SECT_OCEAN: send_to_char("You cannot cast a totem in this room.\n\r", ch); pop_call(); return; } totem = create_object( get_obj_index( OBJ_VNUM_TOTEM ), 0 ); totem->timer = level; totem->level = level; act( "A totem rises up from the ground.", ch, NULL, NULL, TO_CHAR ); act( "A totem rises up from the ground.", ch, NULL, NULL, TO_ROOM ); obj_to_room( totem, ch->in_room->vnum ); switch (tolower(target_name[0])) { case 'c': totem->value[0] = slot_lookup(translate_bits("SPELL_CURE_POISON")); totem->value[1] = slot_lookup(translate_bits("SPELL_CURE_BLINDNESS")); totem->value[2] = slot_lookup(translate_bits("SPELL_REMOVE_CURSE")); totem->value[3] = slot_lookup(translate_bits("SPELL_CURE_CRITICAL")); break; case 'p': totem->value[0] = slot_lookup(translate_bits("SPELL_GIANT_STRENGTH")); totem->value[1] = slot_lookup(translate_bits("SPELL_ENHANCED_HEAL")); totem->value[2] = slot_lookup(translate_bits("SPELL_BLESS")); if (ch->alignment < 0) { totem->value[3] = slot_lookup(translate_bits("SPELL_PROTECTION_GOOD")); } else { totem->value[3] = slot_lookup(translate_bits("SPELL_PROTECTION_EVIL")); } break; default: totem->value[0] = slot_lookup(translate_bits("SPELL_HEAL")); totem->value[1] = slot_lookup(translate_bits("SPELL_CURE_LIGHT")); totem->value[2] = slot_lookup(translate_bits("SPELL_CURE_SERIOUS")); totem->value[3] = slot_lookup(translate_bits("SPELL_CURE_CRITICAL")); break; } pop_call(); return; } /* * 11 sept 2004, Michiel Lange * First stonefist implementation */ DO_SPELL(spell_steelhand) { CHAR_DATA *victim=(CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_steelhand(%p,%p,%p,%p)",sn,level,ch,vo); if ( is_affected( victim, sn ) ) { send_to_char( "They are already affected.\n\r", ch ); pop_call(); return; } af.type = sn; af.duration = level/2; af.location = 0; af.modifier = ((level/10)+1) * ((level/25)+6); af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_STEELHAND; affect_to_char(victim, &af); act( "$n's hands become razorsharp steel.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your hands turn to razorsharp steel blades.\n\r", victim ); pop_call(); return; } /* The sloth spell decreases the victim's agility for a certain amount of time Created by Hypnos 20041114. */ DO_SPELL(spell_sloth) { CHAR_DATA *victim=(CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_sloth(%d,%d,%p,%p,%d)", sn, level, ch, vo, target); if ( IS_AFFECTED( victim, AFF2_SLOTH ) ) { if(victim == ch) { ch_printf(ch, "You are already affected by the sloth spell.\n\r"); } else { ch_printf(ch, "%s is already affected by the sloth spell.\n\r", capitalize(get_name(victim))); } pop_call(); return; } af.type = sn; if (!IS_NPC(victim) && IS_IMMORTAL(victim)) { ch_printf(ch, "Immortal beings are immune to the sloth spell.\n\r"); pop_call(); return; } if (IS_NPC(victim)) { af.duration = number_fuzzy(level / 10); } else { af.duration = number_fuzzy(level / 15); } af.location = APPLY_DEX; af.modifier = -(1 + ((level / 30)) * ((level / 10) + 1)); af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_SLOTH; affect_to_char(victim, &af); act( "$n's agility dwindles.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your agility dwindles as sloth takes hold of you.\n\r", victim); pop_call(); return; } /* The spell "a touch of idiocy" decrease's the poor victim's Int and Wis scores by 1d6 Created by Hypnos 20041115 */ DO_SPELL(spell_touch_of_idiocy) { CHAR_DATA *victim=(CHAR_DATA *) vo; AFFECT_DATA af; push_call("spell_touch_of_idiocy(%d,%d,%p,%p,%d)", sn, level, ch, vo, target); if ( IS_AFFECTED( victim, AFF2_TOUCHOFIDIOCY ) ) { if(victim == ch) { ch_printf(ch, "You are already affected by the touch of idiocy spell.\n\r"); } else { ch_printf(ch, "%s is already affected by the touch of idiocy spell.\n\r", capitalize(get_name(victim))); } pop_call(); return; } af.type = sn; if (!IS_NPC(victim) && IS_IMMORTAL(victim)) { ch_printf(ch, "The infinite wisdom and intellect of the Immortals are immune to the touch of idocy spell.\n\r"); pop_call(); return; } af.duration = number_fuzzy(level / 8); af.location = APPLY_INT; af.modifier = -1 - dice(level / 25, 6); af.bittype = AFFECT_TO_CHAR; af.bitvector = AFF2_TOUCHOFIDIOCY; affect_to_char(victim, &af); af.location = APPLY_WIS; af.modifier = -1 - dice(level / 25, 6); affect_to_char(victim, &af); act( "A powerful curse descends upon $s.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You suddenly feel a lot less certain of yourself.\n\r", victim); pop_call(); return; }