/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David * * Love, Guilherme 'Willie' Arnold, and Mitchell Tse. * * * * In order to use any part of this Envy Diku Mud, you must comply with * * the original Diku license in 'license.doc', the Merc license in * * 'license.txt', as well as the Envy license in 'license.nvy'. * * In particular, you may not remove either of these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*$Id: magic.c,v 1.57 2005/04/04 16:02:46 ahsile Exp $*/ #if defined( macintosh ) #include <types.h> #else #include <sys/types.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" /* * External functions. */ bool is_safe args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); /* * Local functions. */ void set_fighting args( ( CHAR_DATA *ch, CHAR_DATA *victim ) ); void say_spell args( ( CHAR_DATA *ch, int sn ) ); int blood_count args( ( OBJ_DATA *list, int amount ) ); void magic_mob args( ( CHAR_DATA *ch, OBJ_DATA *obj, int vnum ) ); int slot_lookup args( ( int slot ) ); /* * "Permament sn's": slot loading for objects -- Altrag */ int slot_lookup( int slot ) { int sn; for ( sn = 0; skill_table[sn].name[0] != '\0'; sn++ ) if ( skill_table[sn].slot == slot ) return sn; bug( "Slot_lookup: no such slot #%d", slot ); return 0; } /* * Replacement for MAX_SKILL -- Altrag */ bool is_sn( int sn ) { int cnt; for ( cnt = 0; skill_table[cnt].name[0] != '\0'; cnt++ ) if ( cnt == sn ) return TRUE; return FALSE; } void magic_mob ( CHAR_DATA *ch, OBJ_DATA *obj, int vnum ) { CHAR_DATA *victim; CHAR_DATA *zombie; MOB_INDEX_DATA *ZombIndex; MOB_INDEX_DATA *pMobIndex; char *name; char buf [MAX_STRING_LENGTH]; if ( !( pMobIndex = get_mob_index( vnum ) ) ) { send_to_char(AT_BLUE, "Nothing happens.\n\r", ch); return; } ZombIndex = get_mob_index( 3 ); victim = create_mobile( pMobIndex ); zombie = create_mobile( ZombIndex ); name = victim->short_descr; sprintf( buf, zombie->short_descr, name ); free_string( zombie->short_descr ); zombie->short_descr = str_dup(buf); sprintf( buf, zombie->long_descr, name ); free_string( zombie->long_descr ); zombie->long_descr = str_dup(buf); victim->max_hit /= 2; victim->hit = victim->max_hit; zombie->max_hit = victim->max_hit; zombie->hit = victim->hit; zombie->level = victim->level; SET_BIT( zombie->act, PLR_UNDEAD ); SET_BIT( zombie->act, ACT_PET ); SET_BIT( zombie->affected_by, AFF_CHARM ); char_to_room( zombie, ch->in_room ); add_follower( zombie, ch ); update_pos( zombie ); act( AT_BLUE, "$n passes $s hands over $p, $E slowly rises to serve $S new master.", ch, obj, zombie, TO_ROOM ); act( AT_BLUE, "You animate $p, it rises to serve you.", ch, obj, NULL, TO_CHAR ); char_to_room( victim, ch->in_room ); extract_char ( victim, TRUE ); return; } int blood_count( OBJ_DATA *list, int amount ) { OBJ_DATA *obj; int count; OBJ_DATA *obj_next; count = 0; for ( obj = list; obj; obj = obj_next ) { obj_next = obj->next_content; if ( obj->deleted ) continue; if ( ( obj->item_type == ITEM_BLOOD ) && ( count != amount ) ) { count++; extract_obj( obj ); } } return count; } void update_skpell( CHAR_DATA *ch, int sn, int override ) { int pct = 0; int gain = 1; if (IS_NPC(ch)) return; if( override == 0 ) { if( ch->pcdata->learned[sn] == 0 ) { return; } if( ch->pcdata->learned[sn] <= 100 ) { pct = 100 + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = number_fuzzy( 10 ); } else if( ch->pcdata->learned[sn] <= 200 ) { pct = 95 + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = number_fuzzy( 9 ); } else if( ch->pcdata->learned[sn] <= 300 ) { pct = 90 + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = number_fuzzy( 8 ); } else if( ch->pcdata->learned[sn] <= 400 ) { pct = 85 + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = number_fuzzy( 7 ); } else if( ch->pcdata->learned[sn] <= 500 ) { pct = 75 + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = number_fuzzy( 6 ); } else if( ch->pcdata->learned[sn] <= 600 ) { pct = 65 + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = number_fuzzy( 4 ); } else if( ch->pcdata->learned[sn] <= 750 ) { pct = ( 125 - ( ch->pcdata->learned[sn] / 10 ) ) + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = number_fuzzy( 2 ); } else { pct = ( ( 125 - ( ch->pcdata->learned[sn] / 10 ) ) / 2 ) + ( skill_table[sn].is_spell ? int_app[get_curr_int(ch)].bonus : dex_app[get_curr_dex(ch)].bonus ); gain = 1; } if( gain < 1 ) gain = 1; } else { gain = override; pct = 101; } if ( number_percent() < pct ) { if ( ch->pcdata->learned[sn] < 1000 ) { if( ( ch->level < LEVEL_HERO && number_percent( ) <= 50 ) || ch->level >= LEVEL_HERO || override != 0 ) { char buf[MAX_STRING_LENGTH]; ch->pcdata->learned[sn] += gain; if( ch->pcdata->learned[sn] > 1000 ) ch->pcdata->learned[sn] = 1000; sprintf(buf, "Your %s \"%s\" improves to %3.1f%%!\n\r", skill_table[sn].is_spell ? "spell" : "skill" , skill_table[sn].name, ch->pcdata->learned[sn] / 10.0f ); send_to_char(AT_CYAN, buf, ch ); if( ch->pcdata->learned[sn] >= 1000 ) { sprintf(buf, "Congratulations! Your %s \"%s\" has reached grandmaster level!\n\r", skill_table[sn].is_spell ? "spell" : "skill" , skill_table[sn].name ); send_to_char(AT_CYAN, buf, ch ); } } } } return; } int skill_lookup( const char *name ) { // char buf[MAX_STRING_LENGTH]; int sn; if (!str_cmp(name,"")) return -1; for ( sn = 0; skill_table[sn].name[0] != '\0'; sn++ ) { if ( !skill_table[sn].name ) break; if ( LOWER( name[0] ) == LOWER( skill_table[sn].name[0] ) && !str_prefix( name, skill_table[sn].name ) ) return sn; } /* sprintf(buf, "Skill Lookup: Can't find skill: \"%s\"", name); bug(buf,0); */ return -1; } /* * Utter mystical words for an sn. */ void say_spell( CHAR_DATA *ch, int sn ) { CHAR_DATA *rch; char *pName; char buf [ MAX_STRING_LENGTH ]; char buf2 [ MAX_STRING_LENGTH ]; 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" }, { "light", "dies" }, { "lo", "hi" }, { "mor", "zak" }, { "move", "sido" }, { "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" }, { "", "" } }; 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 ); for ( rch = ch->in_room->people; rch; rch = rch->next_in_room ) { if ( rch != ch ) act(AT_BLUE, ch->class==rch->class ? buf : buf2, ch, NULL, rch, TO_VICT ); } return; } /* * Compute a saving throw. * Negative apply's make saving throw better. */ bool saves_spell( int level, CHAR_DATA *victim ) { int save; int base = 20; int savebase; if ( IS_NPC( victim ) ) base += 30; savebase = 0 - (victim->saving_throw < -440 ? -440 : victim->saving_throw); if ( !IS_NPC( victim ) ) savebase /= 8; else savebase /= 2; save = base + ( victim->level - level ) + savebase; save = URANGE( 5, save, 90 ); return number_percent( ) < save; } /* * The kludgy global is for spells who want more stuff from command line. */ char *target_name; void do_acspell ( CHAR_DATA *ch, OBJ_DATA *pObj, char *argument ) { void *vo; OBJ_DATA *obj = NULL; CHAR_DATA *victim; char arg1 [ MAX_INPUT_LENGTH ]; char arg2 [ MAX_INPUT_LENGTH ]; int sn; int spec; int dmg = 0; spec = skill_lookup( "astral walk" ); target_name = one_argument( argument, arg1 ); one_argument( target_name, arg2 ); if ( IS_NPC( ch ) ) if ( IS_SET( ch->affected_by, AFF_CHARM ) ) return; if ( ( sn = skill_lookup( arg1 ) ) < 0) { send_to_char(AT_BLUE, "You can't do that.\n\r", ch ); return; } if ( ( sn == spec ) && ( is_name( arg2, ch->name ) ) ) { send_to_char( AT_BLUE, "You are already in the same room as yourself.\n\r", ch ); return; } /* * Locate targets. */ victim = NULL; obj = NULL; vo = NULL; switch ( skill_table[sn].target ) { default: bug( "Do_cast: bad target for sn %d.", sn ); return; case TAR_GROUP_OFFENSIVE: case TAR_GROUP_DEFENSIVE: case TAR_GROUP_ALL: case TAR_GROUP_OBJ: case TAR_GROUP_IGNORE: group_cast( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, arg2 ); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if ( IS_SET( ch->in_room->room_flags, ROOM_NO_OFFENSIVE ) ) { send_to_char( AT_BLUE, "Your spell has failed.\n\r", ch ); return; } if ( arg2[0] == '\0' ) { if ( !( victim = ch->fighting ) ) { send_to_char(AT_BLUE, "Cast the spell on whom?\n\r", ch ); return; } } else { if ( !( victim = get_char_room( ch, arg2 ) ) ) { send_to_char(AT_BLUE, "They aren't here.\n\r", ch ); return; } } if ( !is_pkillable( ch, victim ) ) { return; } if ( IS_AFFECTED(victim, AFF_PEACE) ) { send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch); return; } if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You must exit the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You can not attack someone who is in the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED4( ch, AFF_BURROW) ) { send_to_char(AT_WHITE, "You must wait for the earth to heal you!\n\r", ch); return; } if ( IS_AFFECTED4( victim, AFF_BURROW) ) { send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch); return; } if (!IS_NPC(victim)) { if (victim->pkill == TRUE) ch->pkill_timer = 0; } if ( IS_AFFECTED( ch, AFF_PEACE) ) { affect_strip( ch, skill_lookup("aura of peace") ); REMOVE_BIT( ch->affected_by, AFF_PEACE ); } vo = (void *) victim; if (!pk_combat_check(ch, victim)) return; break; case TAR_CHAR_DEFENSIVE: if ( arg2[0] == '\0' ) { victim = ch; } else { if ( !( victim = get_char_room( ch, arg2 ) ) ) { send_to_char(AT_BLUE, "They aren't here.\n\r", ch ); return; } } vo = (void *) victim; if (!pk_combat_check(ch, victim)) return; break; case TAR_CHAR_SELF: if ( arg2[0] != '\0' && !is_name( arg2, ch->name ) ) { send_to_char(AT_BLUE, "You cannot cast this spell on another.\n\r", ch ); return; } vo = (void *) ch; break; case TAR_OBJ_INV: if ( arg2[0] == '\0' ) { send_to_char(AT_BLUE, "What should the spell be cast upon?\n\r", ch ); return; } if ( !( obj = get_obj_carry( ch, arg2 ) ) ) { send_to_char(AT_BLUE, "You are not carrying that.\n\r", ch ); return; } vo = (void *) obj; break; } WAIT_STATE( ch, skill_table[sn].beats ); if ( IS_SET( ch->in_room->room_flags, ROOM_NO_MAGIC ) ) { send_to_char( AT_BLUE, "You failed.\n\r", ch ); return; } dmg = (*skill_table[sn].spell_fun) ( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, vo ); if (dmg > SKPELL_NO_DAMAGE) damage(ch, victim, dmg, sn); if ( vo ) { oprog_invoke_trigger( pObj, ch, vo ); if ( skill_table[sn].target == TAR_OBJ_INV ) oprog_cast_sn_trigger( obj, ch, sn, vo ); rprog_cast_sn_trigger( ch->in_room, ch, sn, vo ); } if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE && victim->master != ch && victim != ch && IS_AWAKE( victim ) ) { CHAR_DATA *vch; for ( vch = ch->in_room->people; vch; vch = vch->next_in_room ) { if ( vch->deleted ) continue; if ( victim == vch && !victim->fighting ) { multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } return; } bool pk_combat_check(CHAR_DATA *ch, CHAR_DATA *victim) { CHAR_DATA * rch; bool found = FALSE; if (!victim->fighting || IS_NPC( victim ) || IS_NPC( ch ) ) return TRUE; if (IS_SET(ch->in_room->room_flags, ROOM_PKILL ) && IS_SET(victim->in_room->room_flags, ROOM_PKILL )) { ch->pkill_timer = 0; victim->pkill_timer = 0; return TRUE; } for( rch= ch->in_room->people; rch; rch= rch->next_in_room ) { if (rch->deleted || !rch->fighting || rch == victim || rch == ch || IS_NPC(rch) ) continue; /* ok, a player in the room is fighting the victim, should we allow the spell? allow the spell and set their pk timer? or not allow the spell? */ if (rch->fighting == victim && rch != ch ) { /*peacefuls shouldn't get involved*/ if (ch->pkill == 0) { send_to_char(AT_WHITE, "You can't get involved in pkill battles!\r\n", ch); return FALSE; } else if ( abs( ch->level - rch->level ) > PKILL_RANGE || abs( ch->level - victim->level ) > PKILL_RANGE ) { send_to_char(AT_RED, "You can't get involved in this pk battle\r\nValid Range is +/- 8 levels.\r\n", ch); return FALSE; } else if (abs( ch->level - rch->level ) <= PKILL_RANGE || abs( ch->level - victim->level) <= PKILL_RANGE ) { /*This target is in range, so, set the found flag, there may still be other out of range ppl in the fight. */ found = TRUE; } } } /*if we get to here, then it's ok to cast the spell, if we found a pk fight along the way, reset the caster's pk timer */ if (found) ch->pkill_timer = 0; return TRUE; } void do_cast( CHAR_DATA *ch, char *argument ) { void *vo; OBJ_DATA *obj; CHAR_DATA *victim; char arg1 [ MAX_INPUT_LENGTH ]; char arg2 [ MAX_INPUT_LENGTH ]; int mana; int sn = 0; int spec; int intreq = 0; int intreq1 = 0; int intreq2 = 0; spec = skill_lookup( "astral walk" ); target_name = one_argument( argument, arg1 ); one_argument( target_name, arg2 ); if ( arg1[0] == '\0' ) { send_to_char(AT_BLUE, "Cast which what where?\n\r", ch ); return; } if ( !IS_NPC( ch ) ) if ( IS_AFFECTED4( ch, AFF_BURROW ) ) { send_to_char(AT_RED, "You cannot cast while burrowed!\n\r", ch); return; } if ( IS_NPC( ch ) ) if ( IS_SET( ch->affected_by, AFF_CHARM ) ) return; if (IS_NPC( ch ) ) if (ch->mana == 0) return; if ( !IS_NPC( ch ) ) if ( ( sn = skill_lookup( arg1 ) ) < 0 || ( ch->level < skill_table[sn].skill_level[ch->class] && ch->level < skill_table[sn].skill_level[ch->multied] ) ) { send_to_char(AT_BLUE, "You can't do that.\n\r", ch ); return; } if (!skill_table[sn].is_spell) { send_to_char(AT_WHITE, "Casting a skill? Try using it...\n\r", ch); return; } if ( !IS_NPC( ch ) ) if ( ch->class == CLASS_BARBARIAN || ch->multied == CLASS_BARBARIAN ) { if ( skill_table[sn].skill_level[ch->class] > 60 && skill_table[sn].skill_level[ch->multied] > 60 ) { send_to_char(C_DEFAULT, "Barbarians can not cast magic of such high level.\n\r", ch ); return; } } if ( !IS_NPC( ch ) ) if ( ( ch->race == 10 && IS_EVIL( ch ) ) || ( ch->race == 10 && IS_NEUTRAL( ch ) ) || ( ch->race == 15 && IS_GOOD( ch ) ) || ( ch->race == 15 && IS_NEUTRAL( ch ) ) || ( ch->class == CLASS_CLERIC && IS_EVIL( ch ) ) || ( ch->multied == CLASS_CLERIC && IS_EVIL( ch ) ) || ( ch->class == CLASS_PALADIN && IS_EVIL( ch ) ) || ( ch->multied == CLASS_PALADIN && IS_EVIL( ch ) ) || ( ch->class == CLASS_ANTI_PALADIN && IS_GOOD( ch ) ) || ( ch->multied == CLASS_ANTI_PALADIN && IS_GOOD( ch ) ) || ( ch->class == CLASS_DARKPRIEST && IS_GOOD( ch ) ) || ( ch->multied == CLASS_DARKPRIEST && IS_GOOD( ch ) ) ) { send_to_char(AT_BLUE, "You can not cast when you are that alignment.\n\r", ch ); return; } if ( IS_NPC( ch ) ) if ( ( sn = skill_lookup( arg1 ) ) < 0 ) return; if ( ch->position < skill_table[sn].minimum_position ) { send_to_char(AT_BLUE, "You can't concentrate enough.\n\r", ch ); return; } if IS_AFFECTED2( ch, AFF_SLIT) { send_to_char(AT_BLOOD, "Your throat is slit, you can not cast.\n\r", ch ); return; } if ( IS_STUNNED( ch, STUN_MAGIC ) ) { send_to_char(AT_LBLUE, "You're too stunned to cast spells.\n\r", ch ); return; } mana = 0; if(!IS_NPC( ch ) && ch->level >= skill_table[sn].skill_level[ch->multied] ) { mana = MANA_COST_MULTI(ch, sn ); intreq1 = ( skill_table[sn].skill_level[ch->multied] / 2 ) - 5; if( intreq1 >= 40 ) { intreq1 = 40; } } if(!IS_NPC( ch ) && ch->level >= skill_table[sn].skill_level[ch->class] ) { mana = MANA_COST( ch, sn ); intreq2 = ( skill_table[sn].skill_level[ch->class] / 2) - 5; if( intreq2 >= 40 ) { intreq2 = 40; } } intreq = UMIN(intreq1, intreq2); if ( ch->class == CLASS_VAMPIRE || ch->class == CLASS_ANTI_PALADIN ) { mana /= 4; } if(ch->class != CLASS_CLERIC && ch->class != CLASS_DARKPRIEST ) { if( get_curr_int( ch ) < intreq ) { send_to_char(AT_BLUE, "You do not have the required intelligence.\n\r", ch ); return; } } if(ch->class == CLASS_CLERIC || ch->class == CLASS_DARKPRIEST ) { if( get_curr_wis (ch ) < intreq ) { send_to_char(AT_BLUE, "You do not have the required wisdom.\n\r", ch ); return; } } /* * Locate targets. */ victim = NULL; obj = NULL; vo = NULL; switch ( skill_table[sn].target ) { default: bug( "Do_cast: bad target for sn %d.", sn ); return; case TAR_GROUP_OFFENSIVE: case TAR_GROUP_DEFENSIVE: case TAR_GROUP_ALL: case TAR_GROUP_OBJ: case TAR_GROUP_IGNORE: group_cast( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, arg2 ); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if ( IS_SET( ch->in_room->room_flags, ROOM_NO_OFFENSIVE ) ) { send_to_char( AT_BLUE, "You failed.\n\r", ch ); return; } if ( arg2[0] == '\0' ) { if ( !( victim = ch->fighting ) ) { send_to_char(AT_BLUE, "Cast the spell on whom?\n\r", ch ); return; } } else { if ( !( victim = get_char_room( ch, arg2 ) ) ) { send_to_char(AT_BLUE, "They aren't here.\n\r", ch ); return; } } if( !is_pkillable(ch, victim ) ) { return; } if (!IS_NPC(victim)) ch->pkill_timer = 0; if ( IS_AFFECTED(victim, AFF_PEACE) ) { send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch); return; } if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You must exit the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You can not attack someone who is in the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED4( ch, AFF_BURROW) ) { send_to_char(AT_WHITE, "You must wait for the earth to heal you!\n\r", ch); return; } if ( IS_AFFECTED4( victim, AFF_BURROW) ) { send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch); return; } if ( IS_AFFECTED( ch, AFF_PEACE) ) { affect_strip( ch, skill_lookup("aura of peace") ); REMOVE_BIT( ch->affected_by, AFF_PEACE ); } if (is_safe(ch, victim ) ) { send_to_char( AT_BLUE, "You failed.\n\r",ch); return; } if (!pk_combat_check(ch, victim)) return; vo = (void *) victim; break; case TAR_CHAR_DEFENSIVE: if ( arg2[0] == '\0' ) { victim = ch; } else { if ( !( victim = get_char_room( ch, arg2 ) ) ) { send_to_char(AT_BLUE, "They aren't here.\n\r", ch ); return; } } vo = (void *) victim; if (!pk_combat_check(ch, victim)) return; break; case TAR_CHAR_SELF: if ( arg2[0] != '\0' && !is_name( arg2, ch->name ) ) { send_to_char(AT_BLUE, "You cannot cast this spell on another.\n\r", ch ); return; } vo = (void *) ch; break; case TAR_OBJ_INV: if ( arg2[0] == '\0' ) { send_to_char(AT_BLUE, "What should the spell be cast upon?\n\r", ch ); return; } if ( !(obj = get_obj_here( ch, arg2 ) ) ) { send_to_char( AT_BLUE, "You can't find that.\n\r", ch ); return; } vo = (void *) obj; break; } if ( !IS_NPC( ch ) ) { if ( ( ch->class != 9 ) && ( ch->class != 11) && ( ch->mana < mana ) ) { send_to_char(AT_BLUE, "You don't have enough mana.\n\r", ch ); return; } else if ( ( ch->bp < mana ) && (( ch->class == 9 )||( ch->class == 11)) ) { send_to_char(AT_RED, "You are to starved to cast, you must feed.\n\r", ch ); return; } } if ( str_cmp( skill_table[sn].name, "ventriloquate" ) ) say_spell( ch, sn ); if ( IS_SET( ch->in_room->room_flags, ROOM_NO_MAGIC ) ) { send_to_char( AT_BLUE, "You failed.\n\r", ch ); return; } if ( ( IS_SET( ch->in_room->room_flags, ROOM_NO_OFFENSIVE ) ) && ( skill_table[sn].target == TAR_CHAR_OFFENSIVE ) ) { send_to_char( AT_BLUE, "You failed.\n\r", ch ); return; } if ( !IS_NPC( ch ) ) { if ( number_percent( ) > ( ch->pcdata->learned[sn] / 10 ) ) { send_to_char(AT_BLUE, "You lost your concentration.\n\r", ch ); if (( ch->class != 9 )&&( ch->class != 11)) ch->mana -= mana / 2; else ch->bp -= mana / 2; if( ch->pcdata->learned[sn] <= 750 ) update_skpell( ch, sn, 0 ); if( !ch->fighting ) { if( ch->class == CLASS_CLERIC || ch->class == CLASS_DARKPRIEST ) { WAIT_STATE( ch, skill_table[sn].beats / ( get_curr_wis( ch ) / 10 ) ); } else { WAIT_STATE( ch, skill_table[sn].beats / ( get_curr_int( ch ) / 10 ) ); } } else { WAIT_STATE( ch, skill_table[sn].beats ); } } else { int dam = 0; WAIT_STATE( ch, skill_table[sn].beats ); if (( ch->class != 9 )&&(ch->class != 11)) ch->mana -= mana; else ch->bp -= mana; if ( ( IS_AFFECTED2( ch, AFF_CONFUSED ) ) && number_percent( ) < 10 ) { act(AT_YELLOW, "$n looks around confused at what's going on.", ch, NULL, NULL, TO_ROOM ); send_to_char( AT_YELLOW, "You become confused and botch the spell.\n\r", ch ); return; } if (ch->pcdata->learned[skill_lookup("psionic casting")]) update_skpell(ch, skill_lookup("psionic casting"), 0); dam = (*skill_table[sn].spell_fun) ( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, vo ); if (dam > SKPELL_NO_DAMAGE ) { damage( ch, victim, dam, sn ); } else if ( dam == SKPELL_MISSED || dam == SKPELL_BOTCHED ) { // something } if (dam >= SKPELL_NO_DAMAGE) update_skpell( ch, sn, 0 ); } } if ( IS_NPC( ch ) ) { int dam = 0; if ((dam = (*skill_table[sn].spell_fun) ( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, vo )) > SKPELL_NO_DAMAGE) { damage(ch, victim, dam, sn ); } } if ( vo ) { if ( skill_table[sn].target == TAR_OBJ_INV ) oprog_cast_sn_trigger( obj, ch, sn, vo ); rprog_cast_sn_trigger( ch->in_room, ch, sn, vo ); } if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE && victim->master != ch && victim != ch && IS_AWAKE( victim ) ) { CHAR_DATA *vch; for ( vch = ch->in_room->people; vch; vch = vch->next_in_room ) { if ( vch->deleted ) continue; if ( victim == vch && !victim->fighting ) { multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } return; } void do_quickburst( CHAR_DATA *ch, char *argument ) { void *vo; OBJ_DATA *obj; CHAR_DATA *victim; char arg1 [ MAX_INPUT_LENGTH ]; char arg2 [ MAX_INPUT_LENGTH ]; int mana; int sn= -1; int spec; int intreq = 0; int intreq1 = 0; int intreq2 = 0; spec = skill_lookup( "astral walk" ); target_name = one_argument( argument, arg1 ); one_argument( target_name, arg2 ); if ( ( !IS_NPC( ch ) && ((ch->level < skill_table[skill_lookup("quickburst")].skill_level[ch->class] ) && (ch->level < skill_table[skill_lookup("quickburst")].skill_level[ch->multied])))) { send_to_char(C_DEFAULT, "You'd better leave the spellcasting to the spellcasters.\n\r", ch ); return; } if ( IS_NPC( ch ) ) if ( IS_SET( ch->affected_by, AFF_CHARM ) ) return; if ( arg1[0] == '\0' ) { send_to_char(AT_BLUE, "Cast which what where?\n\r", ch ); return; } if ( !ch->fighting ) { send_to_char(C_DEFAULT, "You aren't fighting anyone.\n\r", ch ); return; } if (!IS_NPC(ch) && (ch->pcdata->learned[skill_lookup("quickburst")] == 0)) { send_to_char(C_DEFAULT, "You can't do that.\n\r", ch ); return; } else { if ( !IS_NPC( ch ) ) if ( ( sn = skill_lookup( arg1 ) ) < 0 || ((ch->level < skill_table[sn].skill_level[ch->class]) && (ch->level < skill_table[sn].skill_level[ch->multied]) )) { send_to_char(AT_BLUE, "You can't do that.\n\r", ch ); return; } if (!skill_table[sn].is_spell) { send_to_char(AT_WHITE, "Casting a skill? Try using it...\n\r", ch); return; } if ( !IS_NPC( ch ) ) if ( ch->class == CLASS_BARBARIAN || ch->multied == CLASS_BARBARIAN ) { if ( skill_table[sn].skill_level[ch->class] > 60 && skill_table[sn].skill_level[ch->multied] > 60 ) { send_to_char(C_DEFAULT, "Barbarians can not cast magic of such high level.\n\r", ch ); return; } } if ( !IS_NPC( ch ) ) if ( ( ch->race == 10 && IS_EVIL( ch ) ) || ( ch->race == 10 && IS_NEUTRAL( ch ) ) || ( ch->race == 15 && IS_GOOD( ch ) ) || ( ch->race == 15 && IS_NEUTRAL( ch ) ) || ( ch->class == CLASS_CLERIC && IS_EVIL( ch ) ) || ( ch->multied == CLASS_CLERIC && IS_EVIL( ch ) ) || ( ch->class == CLASS_PALADIN && IS_EVIL( ch ) ) || ( ch->multied == CLASS_PALADIN && IS_EVIL( ch ) ) || ( ch->class == CLASS_ANTI_PALADIN && IS_GOOD( ch ) ) || ( ch->multied == CLASS_ANTI_PALADIN && IS_GOOD( ch ) ) || ( ch->class == CLASS_DARKPRIEST && IS_GOOD( ch ) ) || ( ch->multied == CLASS_DARKPRIEST && IS_GOOD( ch ) ) ) { send_to_char(AT_BLUE, "You can not cast when you are that alignment.\n\r", ch ); return; } if ( IS_NPC( ch ) ) if ( ( sn = skill_lookup( arg1 ) ) < 0 ) return; if ( ch->position < skill_table[sn].minimum_position ) { send_to_char(AT_BLUE, "You can't concentrate enough.\n\r", ch ); return; } if IS_AFFECTED2( ch, AFF_SLIT) { send_to_char(AT_BLOOD, "Your throat is slit, you can not cast.\n\r", ch ); return; } if ( IS_STUNNED( ch, STUN_MAGIC ) ) { send_to_char(AT_LBLUE, "You're too stunned to cast spells.\n\r", ch ); return; } victim = ch->fighting; mana = 0; if ( !IS_NPC( ch ) && ch->level >= skill_table[sn].skill_level[ch->multied] ) { mana = MANA_COST_MULTI( ch, sn ); intreq1 = ( skill_table[sn].skill_level[ch->multied] / 2 ) - 5; if( intreq1 >= 40 ) { intreq1 = 40; } } if ( !IS_NPC( ch ) && ch->level >= skill_table[sn].skill_level[ch->class] ) { mana = MANA_COST( ch, sn ); intreq2 = ( skill_table[sn].skill_level[ch->class] / 2 ) - 5; if( intreq2 >= 40 ) { intreq2 = 40; } } intreq = UMIN( intreq1, intreq2 ); if ( ch->class == CLASS_VAMPIRE || ch->class == CLASS_ANTI_PALADIN ) { mana /= 4; } if(ch->class != CLASS_CLERIC && ch->class != CLASS_DARKPRIEST ) { if( get_curr_int( ch ) < intreq ) { send_to_char(AT_BLUE, "You do not have the required intelligence.\n\r", ch ); return; } } if(ch->class == CLASS_CLERIC || ch->class == CLASS_DARKPRIEST) { if( get_curr_wis( ch ) < intreq ) { send_to_char(AT_BLUE, "You do not have the required wisdom.\n\r", ch ); return; } } update_skpell( ch, skill_lookup("quickburst"), 0 ); /* * Locate targets. */ victim = NULL; obj = NULL; vo = NULL; switch ( skill_table[sn].target ) { default: bug( "Do_cast: bad target for sn %d.", sn ); return; case TAR_GROUP_OFFENSIVE: case TAR_GROUP_DEFENSIVE: case TAR_GROUP_ALL: case TAR_GROUP_OBJ: case TAR_GROUP_IGNORE: group_cast( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, arg2 ); return; case TAR_IGNORE: break; case TAR_CHAR_OFFENSIVE: if ( IS_SET( ch->in_room->room_flags, ROOM_NO_OFFENSIVE ) ) { send_to_char( AT_BLUE, "You failed.\n\r", ch ); return; } if ( arg2[0] == '\0' ) { if ( !( victim = ch->fighting ) ) { send_to_char(AT_BLUE, "Cast the spell on whom?\n\r", ch ); return; } } else { if ( !( victim = get_char_room( ch, arg2 ) ) ) { send_to_char(AT_BLUE, "They aren't here.\n\r", ch ); return; } } if ( IS_AFFECTED(victim, AFF_PEACE) ) { send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch); return; } if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You must exit the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You can not attack someone who is in the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED4( ch, AFF_BURROW) ) { send_to_char(AT_WHITE, "You must wait for the earth to heal you!\n\r", ch); return; } if ( IS_AFFECTED4( victim, AFF_BURROW) ) { send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch); return; } if ( IS_AFFECTED( ch, AFF_PEACE) ) { affect_strip( ch, skill_lookup("aura of peace") ); REMOVE_BIT( ch->affected_by, AFF_PEACE ); } if (is_safe(ch, victim ) ) { send_to_char( AT_BLUE, "You failed.\n\r",ch); return; } vo = (void *) victim; if (!pk_combat_check(ch, victim)) return; break; case TAR_CHAR_DEFENSIVE: if ( arg2[0] == '\0' ) { victim = ch; } else { if ( !( victim = get_char_room( ch, arg2 ) ) ) { send_to_char(AT_BLUE, "They aren't here.\n\r", ch ); return; } } vo = (void *) victim; if (!pk_combat_check(ch, victim)) return; break; case TAR_CHAR_SELF: if ( arg2[0] != '\0' && !is_name( arg2, ch->name ) ) { send_to_char(AT_BLUE, "You cannot cast this spell on another.\n\r", ch ); return; } vo = (void *) ch; break; case TAR_OBJ_INV: if ( arg2[0] == '\0' ) { send_to_char(AT_BLUE, "What should the spell be cast upon?\n\r", ch ); return; } if ( !(obj = get_obj_here( ch, arg2 ) ) ) { send_to_char( AT_BLUE, "You can't find that.\n\r", ch ); return; } vo = (void *) obj; break; } if ( !IS_NPC( ch ) ) { if ( ( ch->class != 9 ) && ( ch->class != 11) && ( ch->mana < mana ) ) { send_to_char(AT_BLUE, "You don't have enough mana.\n\r", ch ); return; } else if ( ( ch->bp < mana ) && (( ch->class == 9 )||( ch->class == 11)) ) { send_to_char(AT_RED, "You are to starved to cast, you must feed.\n\r", ch ); return; } } if ( IS_SET( ch->in_room->room_flags, ROOM_NO_MAGIC ) ) { send_to_char( AT_BLUE, "You failed.\n\r", ch ); return; } if ( ( IS_SET( ch->in_room->room_flags, ROOM_NO_OFFENSIVE ) ) && ( skill_table[sn].target == TAR_CHAR_OFFENSIVE ) ) { send_to_char( AT_BLUE, "You failed.\n\r", ch ); return; } WAIT_STATE( ch, skill_table[sn].beats / 2); if ( !IS_NPC( ch ) ) { if ( number_percent( ) > ( ch->pcdata->learned[sn] / 10 ) || ( number_percent( ) > ch->pcdata->learned[skill_lookup("quickburst")] / 10 ) ) { send_to_char(AT_BLUE, "You lost your concentration.\n\r", ch ); if (( ch->class != 9 )&&( ch->class != 11)) ch->mana -= mana / 2; else ch->bp -= mana / 2; if( ch->pcdata->learned[sn] <= 750 ) update_skpell( ch, sn, 0 ); } else { int dmg = 0; if (( ch->class != 9 )&&(ch->class != 11)) ch->mana -= mana; else ch->bp -= mana; if ( ( IS_AFFECTED2( ch, AFF_CONFUSED ) ) && number_percent( ) < 10 ) { act(AT_YELLOW, "$n looks around confused at what's going on.", ch, NULL, NULL, TO_ROOM ); send_to_char( AT_YELLOW, "You become confused and botch the spell.\n\r", ch ); return; } if (ch->pcdata->learned[skill_lookup("psionic casting")]) update_skpell(ch, skill_lookup("psionic casting"), 0); say_spell( ch, sn ); dmg = (*skill_table[sn].spell_fun) ( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, vo ); if ( dmg > SKPELL_NO_DAMAGE ) { /* Insert level adjustment code here */ damage(ch, victim, dmg, sn); } else if ( dmg == SKPELL_BOTCHED || dmg == SKPELL_MISSED ) { /* do something for failed skills, maybe*/ } if (dmg >= SKPELL_NO_DAMAGE) update_skpell( ch, sn, 0 ); } } if ( IS_NPC( ch ) ) { int dmg = 0; if ( (dmg = (*skill_table[sn].spell_fun) ( sn, URANGE( 1, ch->level, LEVEL_DEMIGOD ), ch, vo )) > SKPELL_NO_DAMAGE ) damage( ch, victim, dmg, sn); } if ( vo ) { if ( skill_table[sn].target == TAR_OBJ_INV ) oprog_cast_sn_trigger( obj, ch, sn, vo ); rprog_cast_sn_trigger( ch->in_room, ch, sn, vo ); } if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE && victim->master != ch && victim != ch && IS_AWAKE( victim ) ) { CHAR_DATA *vch; for ( vch = ch->in_room->people; vch; vch = vch->next_in_room ) { if ( vch->deleted ) continue; if ( victim == vch && !victim->fighting ) { multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } 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 dam = 0; if ( sn <= 0 ) return; if ( !is_sn(sn) || skill_table[sn].spell_fun == 0 ) { bug( "Obj_cast_spell: bad sn %d.", sn ); return; } if ( IS_SET( ch->in_room->room_flags, ROOM_NO_MAGIC ) ) { send_to_char( AT_BLUE, "The magic of the item fizzles.\n\r", ch ); return; } switch ( skill_table[sn].target ) { default: bug( "Obj_cast_spell: bad target for sn %d.", sn ); return; case TAR_GROUP_OFFENSIVE: case TAR_GROUP_DEFENSIVE: case TAR_GROUP_ALL: case TAR_GROUP_OBJ: case TAR_GROUP_IGNORE: group_cast( sn, URANGE( 1, level, LEVEL_DEMIGOD ), ch, victim ? (void *)victim : (void *)obj ); return; case TAR_IGNORE: vo = NULL; break; case TAR_CHAR_OFFENSIVE: if ( IS_SET( ch->in_room->room_flags, ROOM_NO_OFFENSIVE ) ) { send_to_char( AT_BLUE, "The magic of the item fizzles.\n\r", ch ); return; } if ( !victim ) victim = ch->fighting; if ( victim && victim->deleted) return; /* if ( !victim || ( !IS_NPC( victim ) && ch != victim ) ) { send_to_char(AT_BLUE, "You can't do that.\n\r", ch ); return; } */ if (!victim) { send_to_char(AT_BLUE, "You cannot find a target.\n\r", ch); return; } if ( IS_AFFECTED(victim, AFF_PEACE) ) { send_to_char(AT_WHITE, "A wave of peace overcomes you.\n\r", ch); return; } if ( IS_AFFECTED2( ch, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You must exit the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE) ) { send_to_char(AT_WHITE, "You can not attack someone who is in the shadow realm.\n\r", ch); return; } if ( IS_AFFECTED4( ch, AFF_BURROW) ) { send_to_char(AT_WHITE, "You must wait for the earth to heal you!\n\r", ch); return; } if ( IS_AFFECTED4( victim, AFF_BURROW) ) { send_to_char(AT_WHITE, "You can not attack someone who is burrowed.\n\r", ch); return; } if ( IS_AFFECTED( ch, AFF_PEACE) ) { affect_strip( ch, skill_lookup("aura of peace") ); REMOVE_BIT( ch->affected_by, AFF_PEACE ); } if ( !is_pkillable( ch, victim ) ) { return; } vo = (void *) victim; if (!pk_combat_check(ch, victim)) return; break; case TAR_CHAR_DEFENSIVE: if ( !victim ) victim = ch; if (!pk_combat_check(ch, victim)) return; vo = (void *) victim; break; case TAR_CHAR_SELF: vo = (void *) ch; break; case TAR_OBJ_INV: if ( !obj ) { send_to_char(AT_BLUE, "You can't do that.\n\r", ch ); return; } vo = (void *) obj; break; } /* target_name = "";*/ dam = (*skill_table[sn].spell_fun) ( sn, level, ch, vo ); if (dam > SKPELL_NO_DAMAGE) { damage( ch, victim, dam, sn); } else if( dam == SKPELL_BOTCHED || dam == SKPELL_MISSED) { // something } if ( vo ) { if ( skill_table[sn].target == TAR_OBJ_INV ) oprog_cast_sn_trigger( obj, ch, sn, vo ); rprog_cast_sn_trigger( ch->in_room, ch, sn, vo ); } if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE && victim->master != ch && ch != victim ) { CHAR_DATA *vch; for ( vch = ch->in_room->people; vch; vch = vch->next_in_room ) { if ( vch->deleted ) continue; if ( victim == vch && !victim->fighting ) { multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } return; } /* Control spells. All the extra checks are JUST IN CASE... heh */ void do_control_switch( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; char arg [ MAX_INPUT_LENGTH ]; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char(AT_WHITE, "Switch into whom?\n\r", ch ); return; } if ( !ch->desc ) return; if ( ch->desc->original ) { send_to_char(AT_WHITE, "You are already switched.\n\r", ch ); return; } if ( !( victim = get_char_world( ch, arg ) ) ) { send_to_char(AT_WHITE, "They aren't here.\n\r", ch ); return; } if ( victim == ch ) { send_to_char(AT_BLUE, "Ok.\n\r", ch ); return; } if ( !IS_NPC( victim ) ) { send_to_char(AT_WHITE, "You cannot switch into a player!\n\r", ch ); return; } if ( victim->desc ) { send_to_char(AT_WHITE, "Character in use.\n\r", ch ); return; } ch->pcdata->switched = TRUE; ch->desc->character = victim; ch->desc->original = ch; victim->desc = ch->desc; victim->prompt = ch->prompt; victim->deaf = ch->deaf; ch->desc = NULL; send_to_char(AT_BLUE, "Ok.\n\r", victim ); return; } /* * Spell functions. */ int spell_acid_blast( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice( level, 8 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_animate( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; OBJ_DATA *obj_next; if ( obj->item_type != ITEM_CORPSE_NPC ) { send_to_char(AT_BLUE, "You cannot animate that.\n\r", ch ); return SKPELL_BOTCHED; } obj_next = obj->next; if (obj->deleted) return SKPELL_MISSED; magic_mob( ch, obj, obj->ac_vnum ); extract_obj(obj); return SKPELL_NO_DAMAGE; } int spell_armor( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level / 2; af.location = APPLY_AC; af.modifier = -50; af.bitvector = 0; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "You feel someone protecting you.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_astral( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim; CHAR_DATA *pet; if ( !( victim = get_char_world( ch, target_name ) ) || 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_ASTRAL_IN ) || IS_SET( ch->in_room->room_flags, ROOM_NO_ASTRAL_OUT ) || IS_SET( victim->in_room->area->area_flags, AREA_PROTOTYPE ) || IS_AFFECTED( victim, AFF_NOASTRAL ) || IS_AFFECTED4( victim, AFF_DECEPTION) ) { send_to_char(AT_BLUE, "You failed.\n\r", ch ); return SKPELL_MISSED; } if ( IS_SET(ch->in_room->area->area_flags, AREA_PRESENT) && (IS_SET( victim->in_room->area->area_flags, AREA_FUTURE ) || IS_SET( victim->in_room->area->area_flags, AREA_PAST ) ) ) { send_to_char(AT_BLUE, "You can't astral walk through time.\n\r", ch ); return SKPELL_MISSED; } if ( IS_SET(ch->in_room->area->area_flags, AREA_FUTURE) && (IS_SET( victim->in_room->area->area_flags, AREA_PRESENT ) || IS_SET( victim->in_room->area->area_flags, AREA_PAST ) ) ) { send_to_char(AT_BLUE, "You can't astral walk through time.\n\r", ch ); return SKPELL_MISSED; } if ( IS_SET(ch->in_room->area->area_flags, AREA_PAST) && (IS_SET( victim->in_room->area->area_flags, AREA_FUTURE ) || IS_SET( victim->in_room->area->area_flags, AREA_PRESENT ) ) ) { send_to_char(AT_BLUE, "You can't astral walk through time.\n\r", ch ); return SKPELL_MISSED; } for ( pet = ch->in_room->people; pet; pet = pet->next_in_room ) { if ( IS_NPC( pet ) ) if ( IS_SET( pet->act, ACT_PET ) && ( pet->master == ch ) ) break; } act(AT_BLUE, "$n vanishes in a flash of blinding light.", ch, NULL, NULL, TO_ROOM ); if ( ch != victim ) { if ( pet ) { act( AT_BLUE, "$n vanishes in a flash of blinding light.", pet, NULL, NULL, TO_ROOM ); char_from_room( pet ); } char_from_room( ch ); char_to_room( ch, victim->in_room ); } act(AT_BLUE, "$n appears in a flash of blinding light.", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); if ( pet ) { char_to_room( pet, victim->in_room ); act( AT_BLUE, "$n appears in a flash of blinding light.", pet, NULL, NULL, TO_ROOM ); } return SKPELL_NO_DAMAGE; } int spell_aura( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_PEACE) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = number_fuzzy( level / 5 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_PEACE; affect_to_char( victim, &af ); send_to_char(AT_BLUE, "You feel a wave of peace flow lightly over your body.\n\r", victim ); act(AT_BLUE, "$n looks very peaceful.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_shadow_plane( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED2( victim, AFF_SHADOW_PLANE) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = number_fuzzy( level ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SHADOW_PLANE; affect_to_char2( victim, &af ); send_to_char(AT_BLUE, "You phase out of reality and into the shadow realm.\n\r", victim ); act(AT_BLUE, "$n's phases out of reality and enters the shadow plane.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_bless( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( victim->position == POS_FIGHTING || is_affected( victim, sn ) ) return SKPELL_BOTCHED; af.type = sn; af.level = level; af.duration = level / 2; af.location = APPLY_HITROLL; af.modifier = level / 6; af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = 0 - level / 6; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "You feel righteous.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_darkbless( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( victim->position == POS_FIGHTING || is_affected( victim, sn ) ) return SKPELL_BOTCHED; af.type = sn; af.level = level; af.duration = 40 + level; af.location = APPLY_DAMROLL; af.modifier = level / 5; af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_HITROLL; af.modifier = level / 5; affect_to_char( victim, &af ); af.location = APPLY_HIT; af.modifier = level * 8; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "You call forth the hand of oblivion.\n\r", ch ); send_to_char(AT_BLUE, "The hand of oblivion rests upon you.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_bio_acceleration( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( victim->position == POS_FIGHTING || is_affected( victim, sn ) ) return SKPELL_BOTCHED; af.type = sn; af.level = level; af.duration = 40 + level; af.location = APPLY_HIT; af.modifier = number_fuzzy ( level * 10 ); af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_MOVE; af.modifier = level * 2; affect_to_char( victim, &af ); send_to_char( AT_BLUE, "You greatly enhance your bio-functions.\n\r", ch ); act(AT_BLUE, "$n's body shudders briefly.", ch, NULL, NULL, TO_ROOM); return SKPELL_NO_DAMAGE; } int spell_blindness( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) || saves_spell( level, victim ) || IS_AFFECTED2( victim, AFF_BLINDFOLD ) ) { send_to_char(AT_BLUE, "You have failed.\n\r", ch ); return SKPELL_BOTCHED; } af.type = sn; af.level = level; af.duration = level / 20; af.location = APPLY_HITROLL; af.modifier = -50; af.bitvector = AFF_BLIND; affect_to_char( victim, &af ); act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_CHAR ); send_to_char(AT_WHITE, "You are blinded!\n\r", victim ); act(AT_WHITE, "$N is blinded!", ch, NULL, victim, TO_NOTVICT ); return SKPELL_NO_DAMAGE; } int spell_blood_bath( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim; if ( blood_count( ch->in_room->contents, 5 ) < 2 ) { send_to_char( AT_RED, "There is not enough blood in the room.\n\r", ch ); return SKPELL_MISSED; } for ( victim = ch->in_room->people; victim; victim = victim->next_in_room ) { if ( victim->deleted ) continue; if ( IS_NPC( victim ) ) continue; victim->hit = UMIN( victim->hit + 500, victim->max_hit ); update_pos( victim ); act( AT_RED, "You bath $N in the life giving fluid.", ch, NULL, victim, TO_CHAR ); act( AT_RED, "$n baths $N in blood.", ch, NULL, victim, TO_ROOM ); act( AT_RED, "$n baths you in blood.", ch, NULL, victim, TO_VICT ); } send_to_char( AT_RED, "The blood bath is over.\n\r", ch ); return SKPELL_NO_DAMAGE; } int spell_burning_hands( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const int dam_each [ ] = { 0, 0, 0, 0, 0, 14, 17, 20, 23, 26, 29, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 57, 57, 58, 59, 60 }; int dam; level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 ); level = UMAX( 0, level ); dam = number_range( dam_each[level] / 2, dam_each[level] * 2 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_call_lightning( int sn, int level, CHAR_DATA *ch, void *vo ) { //CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; static const int dam_each [ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 104, 106, 107, 108, 110, 113, 115, 117, 120, 122, 124, 127, 129, 132, 134, 137, 139, 142, 144, 147, 149, 152, 154, 157, 159, 162, 164, 167, 169, 172, 174, 177, 179, 182, 184, 187, 189, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 242, 244, 246, 248, 250, 255, 260 }; level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 ); level = UMAX( 0, level ); dam = number_range( dam_each[level] / 2, dam_each[level] * 7 ); if ( !IS_OUTSIDE( ch ) ) { send_to_char(AT_WHITE, "You must be out of doors.\n\r", ch ); return SKPELL_BOTCHED; } if ( weather_info.sky < SKY_RAINING ) { send_to_char(AT_WHITE, "You need bad weather for this spell to be effective.\n\r", ch ); dam /= 2; } if ( weather_info.sky > SKY_RAINING ) { send_to_char(AT_WHITE, "The Lightning in the air increases the spells power!\n\r", ch ); dam *= 2; } send_to_char(AT_WHITE, "Lightning slashes out of the sky to strike your foe!\n\r", ch ); act(AT_WHITE, "$n calls lightning from the sky to strike $s foe!", ch, NULL, NULL, TO_ROOM ); //damage( ch, victim, dam, sn ); return dam; } int spell_cause_light( int sn, int level, CHAR_DATA *ch, void *vo ) { //damage( ch, (CHAR_DATA *) vo, dice( 5, 10 ) + level / 3, sn ); return (dice(5,10)+level/3); } int spell_cause_critical( int sn, int level, CHAR_DATA *ch, void *vo ) { //damage( ch, (CHAR_DATA *) vo, dice( 20, 10 ) + level, sn ); return (dice(20,10) + level); } int spell_cause_serious( int sn, int level, CHAR_DATA *ch, void *vo ) { //damage( ch, (CHAR_DATA *) vo, dice( 10, 10 ) + level, sn ); return (dice(10,10)+level); } int spell_change_sex( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_SEX; do { af.modifier = number_range( 0, 2 ) - victim->sex; } while ( af.modifier == 0 ); af.bitvector = 0; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_WHITE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "You feel different.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_charm_person( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( victim == ch ) { send_to_char(AT_BLUE, "You like yourself even better!\n\r", ch ); return SKPELL_MISSED; } if ( !IS_NPC( victim ) ) return SKPELL_BOTCHED; if ( IS_AFFECTED( victim, AFF_CHARM ) || IS_AFFECTED( ch, AFF_CHARM ) || level < victim->level || ( saves_spell(level + IS_SRES(victim, RES_CHARM) ? -5 : 0, victim) && !(get_trust( ch ) > 100) ) ) return SKPELL_MISSED; if(IS_SIMM(victim, IMM_CHARM)) return SKPELL_MISSED; if ( victim->master ) stop_follower( victim ); add_follower( victim, ch ); af.type = sn; af.level = level; af.duration = number_fuzzy( level / 4 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_CHARM; affect_to_char( victim, &af ); send_to_char(AT_BLUE, "Ok.\n\r", ch ); act(AT_BLUE, "Isn't $n just so nice?", ch, NULL, victim, TO_VICT ); return SKPELL_NO_DAMAGE; } int spell_chill_touch( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; static const int dam_each [ ] = { 0, 0, 0, 6, 7, 8, 9, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 39, 40, 40, 40, 41, 41, 42, 43 }; int dam; level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 ); level = UMAX( 0, level ); dam = number_range( dam_each[level] / 2, dam_each[level] * 2 ); if ( !saves_spell( level, victim ) ) { af.type = sn; af.level = level; af.duration = 6; af.location = APPLY_STR; af.modifier = -1; af.bitvector = 0; affect_join( victim, &af ); } else { dam /= 2; } //damage( ch, victim, dam, sn ); return dam; } int spell_colour_spray( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const int dam_each [ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 35, 40, 45, 50, 55, 55, 55, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 64, 64, 65, 66, 67, 67, 68, 69, 70, 70, 71, 72, 73, 73, 74, 75, 76, 76, 77, 78, 79, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, 100,101,102,102,103, 104,105,106,107,120 }; int dam; level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 ); level = UMAX( 0, level ); dam = number_range( dam_each[level] / 2, dam_each[level] * 4 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_continual_light( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *light; light = create_object( get_obj_index( OBJ_VNUM_LIGHT_BALL ), 0 ); obj_to_room( light, ch->in_room ); act(AT_BLUE, "You twiddle your thumbs and $p appears.", ch, light, NULL, TO_CHAR ); act(AT_BLUE, "$n twiddles $s thumbs and $p appears.", ch, light, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_control_weather( int sn, int level, CHAR_DATA *ch, void *vo ) { if ( !str_cmp( target_name, "better" ) ) weather_info.change += dice( level / 3, 4 ); else if ( !str_cmp( target_name, "worse" ) ) weather_info.change -= dice( level / 3, 4 ); else send_to_char (AT_BLUE, "Do you want it to get better or worse?\n\r", ch ); send_to_char(AT_BLUE, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } int spell_create_food( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *mushroom; mushroom = create_object( get_obj_index( OBJ_VNUM_MUSHROOM ), 0 ); mushroom->value[0] = 5 + level; obj_to_room( mushroom, ch->in_room ); act(AT_ORANGE, "$p suddenly appears.", ch, mushroom, NULL, TO_CHAR ); act(AT_ORANGE, "$p suddenly appears.", ch, mushroom, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_create_spring( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *spring; spring = create_object( get_obj_index( OBJ_VNUM_SPRING ), 0 ); spring->timer = level; obj_to_room( spring, ch->in_room ); act(AT_BLUE, "$p flows from the ground.", ch, spring, NULL, TO_CHAR ); act(AT_BLUE, "$p flows from the ground.", ch, spring, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_create_water( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; int water; if ( obj->item_type != ITEM_DRINK_CON ) { send_to_char(AT_BLUE, "It is unable to hold water.\n\r", ch ); return SKPELL_BOTCHED; } if ( obj->value[2] != LIQ_WATER && obj->value[1] != 0 ) { send_to_char(AT_BLUE, "It contains some other liquid.\n\r", ch ); return SKPELL_BOTCHED; } water = UMIN( level * ( weather_info.sky >= SKY_RAINING ? 4 : 2 ), obj->value[0] - obj->value[1] ); if ( water > 0 ) { obj->value[2] = LIQ_WATER; obj->value[1] += water; if ( !is_name( "water", obj->name ) ) { char buf [ MAX_STRING_LENGTH ]; sprintf( buf, "%s water", obj->name ); free_string( obj->name ); obj->name = str_dup( buf ); } act(AT_BLUE, "$p is filled.", ch, obj, NULL, TO_CHAR ); } return SKPELL_NO_DAMAGE; } int spell_cure_blindness( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; if ( !is_affected( victim, skill_lookup("blindness") ) ) return SKPELL_MISSED; affect_strip( victim, skill_lookup("blindness") ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_WHITE, "Your vision returns!\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_cure_critical( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; heal = (int)(victim->max_hit * 0.08); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "You feel better!\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_cure_light( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; heal = (int)(victim->max_hit * 0.02); heal = UMIN(heal, 400); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "You feel better!\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_cure_poison( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; if ( !is_affected( victim, skill_lookup("poison") ) ) return SKPELL_MISSED; victim->poison_level -= number_fuzzy(ch->level/10); if( victim->poison_level <= 0 ) { victim->poison_level = 0; affect_strip( victim, skill_lookup("poison") ); } send_to_char(AT_GREEN, "Ok.\n\r", ch ); send_to_char(AT_GREEN, "A warm feeling runs through your body.\n\r", victim ); act(AT_GREEN, "$N looks better.", ch, NULL, victim, TO_NOTVICT ); return SKPELL_NO_DAMAGE; } int spell_create_illusion( int sn, int level, CHAR_DATA *ch, void *vo ) { char speaker[ MAX_INPUT_LENGTH ]; CHAR_DATA *victim = NULL; char buf[ MAX_STRING_LENGTH ]; target_name = one_argument( target_name, speaker ); victim = get_char_world( ch, target_name ); if ((victim = get_char_world(ch, speaker))) { send_to_char( AT_GREY, target_name, victim ); send_to_char( AT_GREY, "\n\r", victim ); sprintf( buf, "Create Illusion (%s): %s: Sent to %s", ch->name, target_name, victim->name ); log_string( buf, CHANNEL_LOG, -1 ); } else { send_to_char(AT_GREY, "You do not find them.\n\r", ch); } return SKPELL_NO_DAMAGE; } int spell_cure_serious( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; heal = (int)(victim->max_hit * 0.05); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); send_to_char(AT_BLUE, "You feel better!\n\r", victim ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } int spell_curse( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( victim, sn )) { send_to_char(AT_RED, "A curse has already been inflicted.\n\r", ch ); return SKPELL_MISSED; } if (saves_spell( level, victim )) { send_to_char(AT_RED, "You have failed.\n\r", ch); return SKPELL_BOTCHED; } af.type = sn; af.level = level; af.duration = level / 5; af.location = APPLY_HITROLL; af.modifier = -50; af.bitvector = AFF_CURSE; affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = 100; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_RED, "You have inflicted a curse.\n\r", ch ); send_to_char(AT_RED, "You feel unclean.\n\r", victim ); act(AT_RED, "$n has cursed $N!", ch, NULL, victim, TO_ROOM); return SKPELL_NO_DAMAGE; } int spell_detect_evil( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_DETECT_EVIL ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DETECT_EVIL; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "Your eyes tingle.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_detect_hidden( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_DETECT_HIDDEN ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DETECT_HIDDEN; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "Your awareness improves.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_detect_invis( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_DETECT_INVIS ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DETECT_INVIS; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "Your eyes tingle.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_truesight( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED2( victim, AFF_TRUESIGHT ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level / 6; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_TRUESIGHT; affect_to_char2( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "Your eyes tingle.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_detect_magic( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_DETECT_MAGIC ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DETECT_MAGIC; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "Your eyes tingle.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_detect_poison( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; if ( obj->item_type == ITEM_DRINK_CON || obj->item_type == ITEM_FOOD ) { if ( obj->value[3] != 0 ) send_to_char(AT_GREEN, "You smell poisonous fumes.\n\r", ch ); else send_to_char(AT_GREEN, "It looks very delicious.\n\r", ch ); } else { send_to_char(AT_GREEN, "It looks very delicious.\n\r", ch ); } return SKPELL_NO_DAMAGE; } int spell_dispel_evil( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if ( !IS_NPC( ch ) && IS_EVIL( ch ) ) { send_to_char(AT_RED, "You are too EVIL to cast this.\n\r", ch ); return SKPELL_MISSED; } if ( IS_GOOD( victim ) ) { act(AT_BLUE, "God protects $N.", ch, NULL, victim, TO_ROOM ); return SKPELL_MISSED; } if ( IS_NEUTRAL( victim ) ) { act(AT_BLUE, "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); return SKPELL_MISSED; } dam = dice( level, 4 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_earthquake( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *vch; send_to_char(AT_ORANGE, "The earth trembles beneath your feet!\n\r", ch ); act(AT_ORANGE, "$n makes the earth tremble and shiver.", ch, NULL, NULL, TO_ROOM ); if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE)) { send_to_char(AT_WHITE, "You are in a safe room!!!!", ch); return SKPELL_MISSED; } for ( vch = char_list; vch; vch = vch->next ) { if ( vch->deleted || !vch->in_room ) continue; if ( vch->in_room == ch->in_room ) { if ( vch != ch && ( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) ) damage( ch, vch, level + dice( 2, 8 ), sn ); continue; } if ( vch->in_room->area == ch->in_room->area ) send_to_char(AT_ORANGE, "The earth trembles and shivers.\n\r", vch ); } return SKPELL_NO_DAMAGE; } int spell_chain_lightning( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *vch; send_to_char(AT_BLUE, "Bolts of electricity arc from your hands!\n\r", ch ); act(AT_BLUE, "Electrical energy bursts from $n's hands.", ch, NULL, NULL, TO_ROOM ); if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE)) { send_to_char(AT_WHITE, "You are in a safe room!!!!", ch); return SKPELL_MISSED; } for ( vch = char_list; vch; vch = vch->next ) { if ( vch->deleted || !vch->in_room ) continue; if ( vch->in_room == ch->in_room && vch != ch ) { damage( ch, vch, level + dice( level, level/4 ), sn ); continue; } if ( vch->in_room->area == ch->in_room->area ) send_to_char(AT_BLUE, "The air fills with static.\n\r", vch ); } return SKPELL_NO_DAMAGE; } int spell_psychic_quake( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *vch; send_to_char(AT_YELLOW, "You let the chaos free from your mind!\n\r", ch ); act(AT_YELLOW, "$n's face becomes blank and concentrated.", ch, NULL, NULL, TO_ROOM ); for ( vch = char_list; vch; vch = vch->next ) { if ( vch->deleted || !vch->in_room ) continue; if ( vch->in_room == ch->in_room ) { if ( vch != ch && ( IS_NPC( ch ) ? !IS_NPC( vch ) : 1 ) ) if (vch != ch ) damage( ch, vch, level + dice( level, 6 ), sn ); continue; } if ( vch->in_room->area == ch->in_room->area ) send_to_char(AT_BLUE, "A wave of chaos brushes your mind.\n\r", vch ); } return SKPELL_NO_DAMAGE; } int spell_meteor_swarm( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *vch; AFFECT_DATA af; if ( IS_SET( ch->in_room->room_flags, ROOM_SAFE)) { send_to_char(AT_WHITE, "You are in a safe room!!!!\n\r", ch); return SKPELL_MISSED; } send_to_char(AT_RED, "Flaming meteors fly forth from your outstreched hands!\n\r", ch ); act(AT_RED, "Hundreds of flaming meteors fly forth from $n's hands.", ch, NULL, NULL, TO_ROOM ); for ( vch = char_list; vch; vch = vch->next ) { if ( vch->deleted || !vch->in_room ) continue; if ( vch->in_room == ch->in_room && vch != ch && vch->position != POS_GHOST ) { damage( ch, vch, level + dice( level/2, level/2 ), sn ); if ( vch != ch && !is_affected(vch, sn) && !IS_AFFECTED4(vch,AFF_BURROW)) { af.type = sn; af.level = level; af.duration = level / 20; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_FLAMING; affect_join( vch, &af ); send_to_char(AT_RED, "Your body bursts into flames!\n\r", vch); } continue; } } return SKPELL_NO_DAMAGE; } int spell_enchant_weapon( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; if ( obj->item_type != ITEM_WEAPON || IS_OBJ_STAT( obj, ITEM_MAGIC ) || obj->affected ) { send_to_char(AT_BLUE, "That item cannot be enchanted.\n\r", ch ); return SKPELL_MISSED; } paf = new_affect(); paf->type = sn; paf->duration = -1; paf->location = APPLY_HITROLL; paf->modifier = 1 + (level >= 18) + (level >= 25) + (level >= 45) + (level >= 65) +(level >= 90); paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; paf = new_affect(); paf->type = sn; paf->duration = -1; paf->location = APPLY_DAMROLL; paf->modifier = 1 + (level >= 18) + (level >= 25) + (level >= 45) + (level >= 65) +(level >= 90);; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; if ( IS_GOOD( ch ) ) { SET_BIT( obj->extra_flags, ITEM_ANTI_EVIL); act(AT_BLUE, "$p glows.", ch, obj, NULL, TO_CHAR ); } else if ( IS_EVIL( ch ) ) { SET_BIT( obj->extra_flags, ITEM_ANTI_GOOD ); act(AT_RED, "$p glows", ch, obj, NULL, TO_CHAR ); } else { SET_BIT( obj->extra_flags, ITEM_ANTI_EVIL ); SET_BIT( obj->extra_flags, ITEM_ANTI_GOOD ); act(AT_YELLOW, "$p glows.", ch, obj, NULL, TO_CHAR ); } send_to_char(AT_BLUE, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } int spell_flame_blade( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; if ( obj->item_type != ITEM_WEAPON || IS_OBJ_STAT( obj, ITEM_MAGIC ) || IS_OBJ_STAT( obj, ITEM_FLAME ) || obj->affected ) { send_to_char(AT_RED, "That item cannot be enchanted.\n\r", ch ); return SKPELL_BOTCHED; } SET_BIT( obj->extra_flags, ITEM_MAGIC); SET_BIT( obj->extra_flags, ITEM_FLAME ); send_to_char(AT_RED, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } /* void spell_acid_blade( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; if ( obj->item_type != ITEM_WEAPON || IS_OBJ_STAT( obj, ITEM_MAGIC ) || IS_OBJ_STAT( obj, ITEM_ACID ) || obj->affected ) { send_to_char(AT_GREEN, "That item cannot be enchanted.\n\r", ch ); return; } SET_BIT( obj->extra_flags, ITEM_MAGIC); SET_BIT( obj->extra_flags, ITEM_ACID ); send_to_char(AT_GREEN, "You bestow the enchantment of acid blade.\n\r", ch ); return; } */ int spell_dispel_blade( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; if ( obj->item_type != ITEM_WEAPON || IS_OBJ_STAT( obj, ITEM_MAGIC ) || IS_OBJ_STAT2( obj, ITEM_DISPEL ) || obj->affected ) { send_to_char(AT_RED, "That item cannot be enchanted.\n\r", ch ); return SKPELL_BOTCHED; } SET_BIT( obj->extra_flags, ITEM_MAGIC); SET_BIT( obj->extra_flags2, ITEM_DISPEL ); send_to_char(AT_RED, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } int spell_chaos_blade( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; if ( obj->item_type != ITEM_WEAPON || IS_OBJ_STAT( obj, ITEM_MAGIC ) || IS_OBJ_STAT( obj, ITEM_CHAOS ) || obj->affected ) { send_to_char(AT_YELLOW, "That item cannot be enchanted.\n\r", ch ); return SKPELL_BOTCHED; } SET_BIT( obj->extra_flags, ITEM_MAGIC); SET_BIT( obj->extra_flags, ITEM_CHAOS ); send_to_char(AT_YELLOW, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } int spell_frost_blade( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; if ( obj->item_type != ITEM_WEAPON || IS_OBJ_STAT( obj, ITEM_MAGIC ) || IS_OBJ_STAT( obj, ITEM_ICY ) || obj->affected ) { send_to_char(AT_LBLUE, "That item cannot be enchanted.\n\r", ch ); return SKPELL_BOTCHED; } SET_BIT( obj->extra_flags, ITEM_MAGIC); SET_BIT( obj->extra_flags, ITEM_ICY ); send_to_char(AT_LBLUE, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } int spell_holysword( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; if ( obj->item_type != ITEM_WEAPON || IS_OBJ_STAT( obj, ITEM_MAGIC ) || obj->affected ) { send_to_char(AT_BLUE, "That item cannot be consecrated.\n\r", ch ); return SKPELL_BOTCHED; } paf = new_affect(); paf->type = sn; paf->duration = -1; paf->location = APPLY_HITROLL; paf->modifier = 16 + (level >= 18) + (level >= 25) + (level >= 40) + (level >= 60) +(level >= 90); paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; paf = new_affect(); paf->type = sn; paf->duration = -1; paf->location = APPLY_DAMROLL; paf->modifier = 16 + (level >= 18) + (level >= 25) + (level >= 45) + (level >= 65) +(level >= 90);; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; paf = new_affect(); paf->type = sn; paf->duration = -1; paf->location = APPLY_HIT; paf->modifier = 90 + ( (level >=18) * 10) + ( (level >=25) * 10) + ( (level >= 45) * 10) + ( (level >= 65) * 10) + ( ( level >= 90) * 10); paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; obj->ac_type = 5; obj->ac_spell = skill_table[skill_lookup("holy enchantment")].name; obj->ac_charge[0] = 1; obj->ac_charge[1] = 1; if ( IS_GOOD( ch ) ) { SET_BIT( obj->extra_flags, ITEM_ANTI_EVIL); act(AT_YELLOW, "$p glows.", ch, obj, NULL, TO_CHAR ); } else if ( IS_EVIL( ch ) ) { SET_BIT( obj->extra_flags, ITEM_ANTI_GOOD ); act(AT_RED, "$p glows", ch, obj, NULL, TO_CHAR ); } else { SET_BIT( obj->extra_flags, ITEM_ANTI_EVIL ); SET_BIT( obj->extra_flags, ITEM_ANTI_GOOD ); act(AT_WHITE, "$p glows.", ch, obj, NULL, TO_CHAR ); } if( ch->multied == CLASS_MAGE || ch->class == CLASS_MAGE ) { SET_BIT( obj->extra_flags3, ITEM_PRO_MAGE ); } if( ch->multied == CLASS_CLERIC || ch->class == CLASS_CLERIC ) { SET_BIT( obj->extra_flags3, ITEM_PRO_CLERIC ); } if( ch->multied == CLASS_THIEF || ch->class == CLASS_THIEF ) { SET_BIT( obj->extra_flags3, ITEM_PRO_THIEF ); } if( ch->multied == CLASS_WARRIOR || ch->class == CLASS_WARRIOR ) { SET_BIT( obj->extra_flags3, ITEM_PRO_WARRIOR ); } if( ch->multied == CLASS_PSIONICIST || ch->class == CLASS_PSIONICIST ) { SET_BIT( obj->extra_flags3, ITEM_PRO_PSI ); } if( ch->multied == CLASS_DRUID || ch->class == CLASS_DRUID ) { SET_BIT( obj->extra_flags3, ITEM_PRO_DRUID ); } if( ch->multied == CLASS_RANGER || ch->class == CLASS_RANGER ) { SET_BIT( obj->extra_flags3, ITEM_PRO_RANGER ); } if( ch->multied == CLASS_PALADIN || ch->class == CLASS_PALADIN ) { SET_BIT( obj->extra_flags3, ITEM_PRO_PALADIN ); } if( ch->multied == CLASS_BARD || ch->class == CLASS_BARD ) { SET_BIT( obj->extra_flags3, ITEM_PRO_BARD ); } if( ch->multied == CLASS_VAMPIRE || ch->class == CLASS_VAMPIRE ) { SET_BIT( obj->extra_flags3, ITEM_PRO_VAMP ); } if( ch->multied == CLASS_WEREWOLF || ch->class == CLASS_WEREWOLF ) { SET_BIT( obj->extra_flags3, ITEM_PRO_WEREWOLF ); } if( ch->multied == CLASS_ANTI_PALADIN || ch->class == CLASS_ANTI_PALADIN ) { SET_BIT( obj->extra_flags3, ITEM_PRO_ANTIPAL ); } if( ch->multied == CLASS_ASSASSIN || ch->class == CLASS_ASSASSIN ) { SET_BIT( obj->extra_flags3, ITEM_PRO_ASSASSIN ); } if( ch->multied == CLASS_MONK || ch->class == CLASS_MONK ) { SET_BIT( obj->extra_flags3, ITEM_PRO_MONK ); } if( ch->multied == CLASS_BARBARIAN || ch->class == CLASS_BARBARIAN ) { SET_BIT( obj->extra_flags3, ITEM_PRO_BARBARIAN ); } if( ch->multied == CLASS_ILLUSIONIST || ch->class == CLASS_ILLUSIONIST ) { SET_BIT( obj->extra_flags3, ITEM_PRO_ILLUSIONIST ); } if( ch->multied == CLASS_NECROMANCER || ch->class == CLASS_NECROMANCER ) { SET_BIT( obj->extra_flags3, ITEM_PRO_NECROMANCER ); } if( ch->multied == CLASS_DEMONOLOGIST || ch->class == CLASS_DEMONOLOGIST ) { SET_BIT( obj->extra_flags3, ITEM_PRO_DEMONOLOGIST ); } if( ch->multied == CLASS_SHAMAN || ch->class == CLASS_SHAMAN ) { SET_BIT( obj->extra_flags3, ITEM_PRO_SHAMAN ); } if( ch->multied == CLASS_DARKPRIEST || ch->class == CLASS_DARKPRIEST ) { SET_BIT( obj->extra_flags3, ITEM_PRO_DARKPRIEST ); } send_to_char(AT_BLUE, "Ok.\n\r", ch ); return SKPELL_NO_DAMAGE; } /* * Drain XP, MANA, HP. * Caster gains HP. */ int spell_energy_drain( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if ( saves_spell( level, victim ) ) return SKPELL_ZERO_DAMAGE; if ( victim->level <= 2 ) { dam = ch->hit + 1; } else { dam = dice( 4, level ); if ( ( ch->hit + dam ) > ( ch->max_hit + 200 ) ) ch->hit = ( ch->max_hit + 200 ); else ch->hit += dam; if (victim->move - dam >= 0) victim->move -= dam; else victim->move = 0; if (ch->move + dam > ch->max_move + 200) ch->move = ch->move + 200; else ch->move += dam; } //damage( ch, victim, dam, sn ); return dam; } int spell_farsight( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim; ROOM_INDEX_DATA *blah; if ( !( victim = get_char_world( ch, target_name ) ) || 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_ASTRAL_IN ) || IS_SET( ch->in_room->room_flags, ROOM_NO_ASTRAL_OUT ) ) { send_to_char(AT_BLUE, "You failed.\n\r", ch ); return SKPELL_MISSED; } if ( IS_SET(ch->in_room->area->area_flags, AREA_PRESENT) && (IS_SET( victim->in_room->area->area_flags, AREA_FUTURE ) || IS_SET( victim->in_room->area->area_flags, AREA_PAST ) ) ) { send_to_char(AT_BLUE, "You cannot!!!!!!!\n\r", ch ); return SKPELL_MISSED; } if ( IS_SET(ch->in_room->area->area_flags, AREA_FUTURE) && (IS_SET( victim->in_room->area->area_flags, AREA_PRESENT ) || IS_SET( victim->in_room->area->area_flags, AREA_PAST ) ) ) { send_to_char(AT_BLUE, "You cannot!!!!!!!\n\r", ch ); return SKPELL_MISSED; } if ( IS_SET(ch->in_room->area->area_flags, AREA_PAST) && (IS_SET( victim->in_room->area->area_flags, AREA_FUTURE ) || IS_SET( victim->in_room->area->area_flags, AREA_PRESENT ) ) ) { send_to_char(AT_BLUE, "You cannot!!!!!!!\n\r", ch ); return SKPELL_MISSED; } blah = ch->in_room; if ( ch != victim ) { char_from_room( ch ); char_to_room( ch, victim->in_room ); } do_look( ch, "auto" ); if (ch != victim ) { char_from_room( ch ); char_to_room( ch, blah ); } return SKPELL_NO_DAMAGE; } int spell_fireball( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const int dam_each [ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 215, 220, 225, 230, 235, 240, 245, 250, 255, 260 }; int dam; level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 ); level = UMAX( 0, level ); dam = number_range( dam_each[level] / 2, dam_each[level] * 6 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_molecular_unbind( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; if(saves_spell ( level, victim )) { send_to_char(AT_BLUE, "You failed.\n\r", ch ); return SKPELL_MISSED; } for ( obj_lose = victim->carrying; obj_lose; obj_lose = obj_next ) { char *msg; obj_next = obj_lose->next_content; if ( obj_lose->deleted ) continue; if ( obj_lose->wear_loc == WEAR_NONE ) continue; if ( IS_SET( obj_lose->extra_flags, ITEM_NO_DAMAGE ) ) continue; switch ( obj_lose->item_type ) { default: msg = "Your $p gets ruined!"; extract_obj( obj_lose ); break; case ITEM_DRINK_CON: case ITEM_POTION: case ITEM_CONTAINER: case ITEM_LIGHT: msg = "Your $p shatters!"; extract_obj( obj_lose ); break; case ITEM_WEAPON: case ITEM_ARMOR: { OBJ_DATA *pObj; OBJ_INDEX_DATA *pObjIndex; char *name; char buf[MAX_STRING_LENGTH]; pObjIndex = get_obj_index(4); pObj = create_object(pObjIndex, obj_lose->level); name = obj_lose->short_descr; sprintf(buf, pObj->description, name); free_string(pObj->description); pObj->description = str_dup(buf); pObj->weight = obj_lose->weight; pObj->timer = obj_lose->level; msg = "$p has been destroyed!"; extract_obj( obj_lose ); obj_to_room ( pObj, victim->in_room ); act(AT_YELLOW, msg, victim, obj_lose, NULL, TO_CHAR ); act(AT_YELLOW, "You destroyed $p!", ch, obj_lose, NULL, TO_CHAR ); break; } } return SKPELL_NO_DAMAGE; } return SKPELL_NO_DAMAGE; } int spell_shatter( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; if(saves_spell ( level, victim )) { send_to_char(AT_BLUE, "You failed.\n\r", ch ); return SKPELL_MISSED; } for ( obj_lose = victim->carrying; obj_lose; obj_lose = obj_next ) { char *msg; obj_next = obj_lose->next_content; if ( obj_lose->deleted ) continue; if ( obj_lose->wear_loc == WEAR_NONE ) continue; if ( IS_SET( obj_lose->extra_flags, ITEM_NO_DAMAGE ) ) continue; switch ( obj_lose->item_type ) { default: msg = "Your $p gets ruined!"; extract_obj( obj_lose ); break; case ITEM_DRINK_CON: case ITEM_POTION: case ITEM_CONTAINER: case ITEM_LIGHT: msg = "Your $p shatters!"; extract_obj( obj_lose ); break; case ITEM_WEAPON: case ITEM_ARMOR: { OBJ_DATA *pObj; OBJ_INDEX_DATA *pObjIndex; char *name; char buf[MAX_STRING_LENGTH]; pObjIndex = get_obj_index(4); pObj = create_object(pObjIndex, obj_lose->level); name = obj_lose->short_descr; sprintf(buf, pObj->description, name); free_string(pObj->description); pObj->description = str_dup(buf); pObj->weight = obj_lose->weight; pObj->timer = obj_lose->level; msg = "$p has been destroyed!"; extract_obj( obj_lose ); obj_to_room ( pObj, victim->in_room ); act(AT_YELLOW, msg, victim, obj_lose, NULL, TO_CHAR ); act(AT_YELLOW, "You destroyed $p!", ch, obj_lose, NULL, TO_CHAR ); break; } } return SKPELL_NO_DAMAGE; } return SKPELL_NO_DAMAGE; } int spell_fireshield( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_FIRESHIELD ) ) { affect_strip(victim, sn); if(skill_table[sn].msg_off) { send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim ); send_to_char(C_DEFAULT, "\n\r", victim ); } act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT); victim->shields -= 1; return SKPELL_NO_DAMAGE; } if ( !IS_SHIELDABLE( victim ) ) return SKPELL_MISSED; af.type = sn; af.level = level; /* af.duration = number_fuzzy( level / 8 );*/ af.duration = -1; af.location = APPLY_DAM_WATER; af.modifier = 75; af.bitvector = AFF_FIRESHIELD; affect_to_char( victim, &af ); victim->shields += 1; send_to_char(AT_RED, "Your body is engulfed by unfelt flame.\n\r", victim ); act(AT_RED, "$n's body is engulfed in flames.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_demonshield( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED3( victim, AFF_DEMONSHIELD ) ) { affect_strip(victim, sn); if(skill_table[sn].msg_off) { send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim ); send_to_char(C_DEFAULT, "\n\r", victim ); } act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT); victim->shields -= 1; return SKPELL_NO_DAMAGE; } if ( !IS_SHIELDABLE( victim ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = -1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DEMONSHIELD; affect_to_char3( victim, &af ); victim->shields += 1; send_to_char(AT_RED, "Your body is engulfed by swirling demons.\n\r", victim ); act(AT_RED, "$n's body is engulfed by demons.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_acid_shield( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED3( victim, AFF_ACIDSHIELD ) ) { affect_strip(victim, sn); if(skill_table[sn].msg_off) { send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim ); send_to_char(C_DEFAULT, "\n\r", victim ); } act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT); victim->shields -= 1; return SKPELL_NO_DAMAGE; } if ( !IS_SHIELDABLE( victim ) ) return SKPELL_NO_DAMAGE; af.type = sn; af.level = level; af.duration = -1; af.location = APPLY_DAM_ACID; af.modifier = 30; af.bitvector = AFF_ACIDSHIELD; affect_to_char3( victim, &af ); victim->shields += 1; send_to_char(AT_GREEN, "Your body is surrounded by bubbling acid.\n\r", victim ); act(AT_GREEN, "$n's body is drenched in bubbling acid.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_flamestrike( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice( 6, level/2 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_faerie_fire( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_FAERIE_FIRE ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_AC; af.modifier = 2 * level; af.bitvector = AFF_FAERIE_FIRE; affect_to_char( victim, &af ); af.location = APPLY_HITROLL; af.modifier = 0 - level/10; affect_to_char( victim, &af ); send_to_char(AT_PINK, "You are surrounded by a pink outline.\n\r", victim ); act(AT_PINK, "$n is surrounded by a pink outline.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_faerie_fog( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *ich; send_to_char(AT_PURPLE, "You conjure a cloud of purple smoke.\n\r", ch ); act(AT_PURPLE, "$n conjures a cloud of purple smoke.", ch, NULL, NULL, TO_ROOM ); for ( ich = ch->in_room->people; ich; ich = ich->next_in_room ) { if ( !IS_NPC( ich ) && IS_SET( ich->act, PLR_WIZINVIS ) ) continue; if ( ich == ch || saves_spell( level, ich ) ) continue; affect_strip ( ich, skill_lookup("invis") ); affect_strip ( ich, skill_lookup("improved invis") ); affect_strip ( ich, skill_lookup("mass invis") ); affect_strip ( ich, skill_lookup("sneak") ); affect_strip ( ich, skill_lookup("shadow") ); affect_strip ( ich, skill_lookup("phase shift") ); affect_strip ( ich, skill_lookup("shadow plane") ); REMOVE_BIT ( ich->affected_by, AFF_HIDE ); REMOVE_BIT ( ich->affected_by, AFF_INVISIBLE ); REMOVE_BIT ( ich->affected_by2, AFF_IMPROVED_INVIS ); REMOVE_BIT ( ich->affected_by, AFF_SNEAK ); REMOVE_BIT ( ich->affected_by2, AFF_SHADOW_PLANE ); REMOVE_BIT ( ich->affected_by2, AFF_PHASED ); act(AT_PURPLE, "$n is revealed!", ich, NULL, NULL, TO_ROOM ); send_to_char(AT_PURPLE, "You are revealed!\n\r", ich ); } return SKPELL_NO_DAMAGE; } int spell_fly( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected( victim, sn ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level + 3; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_FLYING; affect_to_char( victim, &af ); send_to_char(AT_BLUE, "Your feet rise off the ground.\n\r", victim ); act(AT_BLUE, "$n's feet rise off the ground.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_gate( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *gch; int npccount = 0; int pccount = 0; for ( gch = ch->in_room->people; gch; gch = gch->next_in_room ) { if ( IS_NPC( gch ) && !IS_AFFECTED( gch, AFF_CHARM ) ) npccount++; if ( !IS_NPC( gch ) || ( IS_NPC( gch ) && IS_AFFECTED( gch, AFF_CHARM ) ) ) pccount++; } if ( npccount > pccount ) { do_say( ch, "There are too many of us here! One must die!" ); return SKPELL_NO_DAMAGE; } do_say( ch, "Come brothers! Join me in this glorious bloodbath!" ); char_to_room( create_mobile( get_mob_index( MOB_VNUM_DEMON1 ) ), ch->in_room ); return SKPELL_NO_DAMAGE; } /* * Spell for mega1.are from Glop/Erkenbrand. */ int spell_general_purpose( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = number_range( 25, 100 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_giant_strength( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_STR; af.modifier = 1 + (level >= 18) + (level >= 25) + (level >= 32) + (level >= 39) + (level >=46) + (level >= 70) + (level >= 100); af.bitvector = 0; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "You feel stronger.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_titan_strength( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_STR; af.modifier = ch->level/7; af.bitvector = 0; affect_to_char( victim, &af ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "You feel much stronger.\n\r", victim ); return SKPELL_NO_DAMAGE; } int spell_goodberry( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; OBJ_DATA *berry; if ( obj->item_type != ITEM_FOOD || IS_OBJ_STAT( obj, ITEM_MAGIC ) ) { send_to_char(AT_BLUE, "You can do nothing to that item.\n\r", ch ); return SKPELL_MISSED; } act(AT_BLUE, "You pass your hand over $p slowly.", ch, obj, NULL, TO_CHAR ); act(AT_BLUE, "$n has created a goodberry.", ch, NULL, NULL, TO_ROOM ); berry = create_object( get_obj_index( OBJ_VNUM_BERRY ), 0 ); berry->timer = ch->level; berry->value[0] = ch->level * 2; berry->value[1] = ch->level * 5; extract_obj( obj ); obj_to_char( berry, ch ); return SKPELL_NO_DAMAGE; } int spell_harm( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = UMAX( 20, victim->hit - dice( 1,4 ) ); if ( saves_spell( level, victim ) ) dam = UMIN( 50, dam / 4 ); dam = UMIN( 175, dam ); //damage( ch, victim, dam, sn ); return dam; } int spell_heal( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal; heal = (int)(victim->max_hit * 0.12); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); if ( ch != victim ) send_to_char(AT_BLUE, "Ok.\n\r", ch ); send_to_char(AT_BLUE, "A warm feeling fills your body.\n\r", victim ); return SKPELL_NO_DAMAGE; } /* * Spell for mega1.are from Glop/Erkenbrand. */ int spell_high_explosive( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = number_range( 30, 120 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_iceshield( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_ICESHIELD ) ) { affect_strip(victim, sn); if(skill_table[sn].msg_off) { send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim ); send_to_char(C_DEFAULT, "\n\r", victim ); } act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT); victim->shields -= 1; return SKPELL_NO_DAMAGE; } if ( !IS_SHIELDABLE( victim ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = -1; af.location = APPLY_DAM_FIRE; af.modifier = 75; af.bitvector = AFF_ICESHIELD; affect_to_char( victim, &af ); victim->shields += 1; send_to_char(AT_LBLUE, "An Icy crust forms about your body.\n\r", victim ); act(AT_LBLUE, "An icy crust forms about $n's body.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_icestorm( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice( level, 10 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_holy_fires( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; dam = dice( level, 20 ); if ( saves_spell( level, victim ) ) dam /= 2; //damage( ch, victim, dam, sn ); return dam; } int spell_identify( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; char buf [ MAX_STRING_LENGTH * 4]; int spn; sprintf( buf, "Object '%s' is type %s, extra flags %s %s %s %s.\n\r", obj->name, item_type_name( obj ), extra_bit_name( obj->extra_flags ), extra_bit_name2( obj->extra_flags2 ), extra_bit_name3( obj->extra_flags3 ), extra_bit_name4( obj->extra_flags4 )); send_to_char(AT_CYAN, buf, ch ); sprintf( buf, "Weight : %d, value : %d, level : %d.\n\r", obj->weight, obj->cost, obj->level ); send_to_char(AT_CYAN, buf, ch ); sprintf( buf, "Durability: [%d/%d]\n\r", obj->durability_cur, obj->durability_max); send_to_char(AT_CYAN, buf, ch ); switch ( obj->item_type ) { case ITEM_RUNE: sprintf( buf, "Destination: Unmarked.\n\r" ); if( obj->value[0] != 0 ) { if (get_room_index(obj->value[0])) sprintf( buf, "Destination: %s.\n\r", get_room_index(obj->value[0] )->name ); else sprintf( buf, "Destination: Unknown Location.\n\r" ); } send_to_char(AT_CYAN, buf, ch ); break; case ITEM_PILL: case ITEM_SCROLL: case ITEM_POTION: sprintf( buf, "Level %d spells of:", obj->value[0] ); send_to_char(AT_CYAN, buf, ch ); if ( is_sn(obj->value[1]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[1]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } if ( is_sn(obj->value[2]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[2]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } if ( is_sn(obj->value[3]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[3]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } send_to_char(AT_CYAN, ".\n\r", ch ); break; case ITEM_BOOK: sprintf( buf, "Gain %3.1f%% of:", obj->value[0] / 10.0f ); send_to_char(AT_CYAN, buf, ch ); if ( is_sn(obj->value[1]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[1]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } if ( is_sn(obj->value[2]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[2]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } if ( is_sn(obj->value[3]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[3]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } send_to_char(AT_CYAN, ".\n\r", ch ); break; case ITEM_SKIN: sprintf(buf, "Leather: %d yards\n\r", obj->value[1]); send_to_char(AT_CYAN, buf, ch); sprintf(buf, "Quality: %d (%s)", obj->value[0], flag_string(quality_flags, obj->value[0])); send_to_char(AT_CYAN, buf, ch); break; case ITEM_BULLET: case ITEM_BOLT: case ITEM_ARROW: sprintf(buf, "Remaining: %d. ", obj->value[0]); send_to_char(AT_CYAN, buf, ch ); sprintf(buf, "Damage Class: %s. ", flag_string( damage_flags, obj->value[1]) ); send_to_char(AT_CYAN, buf, ch ); sprintf(buf, "Damage Bonus: %d to %d (average %d).\n\r", obj->value[2], obj->value[3], ( (obj->value[2] + obj->value[3]) / 2 ) ); send_to_char(AT_CYAN, buf, ch ); break; case ITEM_WAND: case ITEM_LENSE: case ITEM_STAFF: if (!(obj->value[1] == -1 ) ) sprintf( buf, "Has %d(%d) charges of level %d", obj->value[1], obj->value[2], obj->value[0] ); else sprintf( buf, "Has unlimited charges of level %d", obj->value[0] ); send_to_char(AT_CYAN, buf, ch ); if ( is_sn(obj->value[3]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[3]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } send_to_char(AT_CYAN, ".\n\r", ch ); break; case ITEM_GUN: if (!(obj->value[1] == -1 ) ) sprintf( buf, "Has %d(%d) shots of level %d", obj->value[1], obj->value[2], obj->value[0] ); else sprintf( buf, "Has unlimited shots of level %d", obj->value[0] ); send_to_char(AT_CYAN, buf, ch ); if ( is_sn(obj->value[3]) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, skill_table[obj->value[3]].name, ch ); send_to_char(AT_CYAN, "'", ch ); } send_to_char(AT_CYAN, ".\n\r", ch ); break; case ITEM_WEAPON: sprintf( buf, "Damage is %d to %d (average %d).\n\r", obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 ); send_to_char(AT_RED, buf, ch ); break; case ITEM_ARMOR: sprintf( buf, "Armor class is %d.\n\r", obj->value[0] ); send_to_char(AT_CYAN, buf, ch ); break; } if ( obj->ac_type != 0 ) { switch( obj->ac_type ) { default: send_to_char(AT_CYAN, "Invoke Type Unknown.\n\r", ch ); break; case 1 : { if ( obj->ac_charge[1] != -1 ) sprintf( buf, "Object creation invoke \ , with [%d/%d] charges.\n\r", obj->ac_charge[0], obj->ac_charge[1] ); else sprintf( buf, "Object creation invoke, with unlimited charges.\n\r" ); send_to_char(AT_CYAN, buf, ch ); break; } case 2 : { if ( obj->ac_charge[1] != -1 ) sprintf( buf, "Monster creation invoke, with [%d/%d] charges.\n\r", obj->ac_charge[0], obj->ac_charge[1] ); else sprintf( buf, "Monster creation invoke, with unlimited charges.\n\r" ); send_to_char(AT_CYAN, buf, ch ); break; } case 3 : { if ( obj->ac_charge[1] != -1 ) sprintf( buf, "Transfer invoke, with [%d/%d] charges.\n\r", obj->ac_charge[0], obj->ac_charge[1] ); else sprintf( buf, "Transfer invoke, with unlimited charges.\n\r" ); send_to_char(AT_CYAN, buf, ch ); break; } case 4 : { if ( obj->ac_charge[1] != -1 ) sprintf( buf, "Object morph invoke, with [%d/%d] charges.\n\r", obj->ac_charge[0], obj->ac_charge[1] ); else sprintf( buf, "Object morph invoke, with unlimited charges.\n\r" ); send_to_char(AT_CYAN, buf, ch ); break; } case 5 : { if ( obj->ac_charge[1] != -1 ) sprintf( buf, "Spell invoke, has [%d/%d] charges of ", obj->ac_charge[0], obj->ac_charge[1] ); else sprintf( buf, "Spell invoke, with unlimited charges of " ); send_to_char(AT_CYAN, buf, ch ); spn = skill_lookup( obj->ac_spell ); if ( is_sn(spn) ) { send_to_char(AT_CYAN, " '", ch ); send_to_char(AT_WHITE, spn ? obj->ac_spell : "(none)", ch ); send_to_char(AT_CYAN, "'\n\r", ch ); } break; } } } for ( paf = obj->pIndexData->affected; paf; paf = paf->next ) { if ( paf->location != APPLY_NONE && paf->modifier != 0 ) { sprintf( buf, "Affects %s by %d.\n\r", affect_loc_name( paf->location ), paf->modifier ); send_to_char(AT_BLUE, buf, ch ); } } for ( paf = obj->affected; paf; paf = paf->next ) { if ( paf->location != APPLY_NONE && paf->modifier != 0 ) { char buf2[MAX_STRING_LENGTH]; if (paf->location > PERM_SPELL_BEGIN) strcpy(buf2, "Affects '%s' by %d.\n\r"); else strcpy(buf2, "Affects %s by %d.\n\r"); sprintf( buf, buf2, affect_loc_name( paf->location ), paf->modifier ); send_to_char(AT_BLUE, buf, ch ); } } return SKPELL_NO_DAMAGE; } int spell_inertial( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_INERTIAL ) ) { affect_strip(victim, sn); if(skill_table[sn].msg_off) { send_to_char(C_DEFAULT, skill_table[sn].msg_off, victim ); send_to_char(C_DEFAULT, "\n\r", victim ); } act(C_DEFAULT, skill_table[sn].msg_off_room, victim, NULL, NULL, TO_NOTVICT); victim->shields -= 1; return SKPELL_NO_DAMAGE; } if ( !IS_SHIELDABLE( victim ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = -1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INERTIAL; affect_to_char( victim, &af ); victim->shields += 1; send_to_char(AT_LBLUE, "You set up a complex set of vibrations around your body.\n\r", victim ); act(AT_LBLUE, "$n's body begins to vibrate.", victim, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; } int spell_infravision( int sn, int level, CHAR_DATA *ch, void *vo ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED( victim, AFF_INFRARED ) ) return SKPELL_MISSED; af.type = sn; af.level = level; af.duration = 2 * level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INFRARED; affect_to_char( victim, &af ); send_to_char(AT_RED, "Your eyes glow.\n\r", victim ); act(AT_RED, "$n's eyes glow.\n\r", ch, NULL, NULL, TO_ROOM ); return SKPELL_NO_DAMAGE; }