/*************************************************************************** * 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. * * * * Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * _/ _/_/_/ _/ _/ _/ ACK! MUD is modified * * _/_/ _/ _/ _/ _/ Merc2.0/2.1/2.2 code * * _/ _/ _/ _/_/ _/ (c)Stephen Zepp 1998 * * _/_/_/_/ _/ _/ _/ Version #: 4.3 * * _/ _/ _/_/_/ _/ _/ _/ * * * * http://ackmud.nuc.net/ * * zenithar@ackmud.nuc.net * * 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. * ***************************************************************************/ /* Original 'magic.c' now contains the first half of the file, while the second half is in this 'magic2.c' file. -S- */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "globals.h" #ifndef DEC_MAGIC_H #include "magic.h" #endif extern bool deathmatch; bool spell_invis( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim; OBJ_DATA *ob; AFFECT_DATA af; if( target_name[0] == '\0' ) { send_to_char( "Make who or what invisible?\n\r", ch ); return FALSE; } if( ( victim = get_char_room( ch, target_name ) ) != NULL ) { if( IS_AFFECTED( victim, AFF_INVISIBLE ) || item_has_apply( victim, ITEM_APPLY_INV ) ) return ( ch == victim ? FALSE : TRUE ); act( "$n fades out of existence.", victim, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = 4 + ( level / 5 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INVISIBLE; affect_to_char( victim, &af ); send_to_char( "You fade out of existence.\n\r", victim ); return TRUE; } else if( ( ob = get_obj_carry( ch, target_name ) ) != NULL ) { if( !IS_SET( ob->extra_flags, ITEM_INVIS ) ) { SET_BIT( ob->extra_flags, ITEM_INVIS ); act( "$p shimmers out of visibility.", ch, ob, NULL, TO_CHAR ); act( "$p shimmers out of visibility.", ch, ob, NULL, TO_ROOM ); return TRUE; } else { act( "$p is already invisible!", ch, ob, NULL, TO_CHAR ); return FALSE; } } else { send_to_char( "Couldn't find that person or object.\n\r", ch ); return FALSE; } return FALSE; } bool spell_know_alignment( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; char *msg; int ap; ap = victim->alignment; if( ap > 700 ) msg = "$N has an aura as white as the driven snow."; else if( ap > 350 ) msg = "$N is of excellent moral character."; else if( ap > 100 ) msg = "$N is often kind and thoughtful."; else if( ap > -100 ) msg = "$N doesn't have a firm moral commitment."; else if( ap > -350 ) msg = "$N lies to $S friends."; else if( ap > -700 ) msg = "$N's slash DISEMBOWELS you!"; else msg = "I'd rather just not say anything at all about $N."; act( msg, ch, NULL, victim, TO_CHAR ); return TRUE; } bool spell_lightning_bolt( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; static const sh_int dam_each[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 28, 31, 34, 37, 40, 40, 41, 42, 42, 43, 44, 44, 45, 46, 46, 47, 48, 48, 49, 50, 50, 51, 52, 52, 53, 54, 54, 55, 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 64 }; 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; sp_damage( obj, ch, victim, dam, REALM_SHOCK, sn, TRUE ); return TRUE; } bool spell_locate_object( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { char buf[MAX_INPUT_LENGTH]; OBJ_DATA *ob; OBJ_DATA *in_obj; bool found; found = FALSE; for( ob = first_obj; ob != NULL; ob = ob->next ) { if( !can_see_obj( ch, ob ) || !is_name( target_name, ob->name ) || IS_SET( ob->extra_flags, ITEM_RARE ) || ( ob->item_type == ITEM_PIECE ) || ( IS_SET( ob->extra_flags, ITEM_UNIQUE ) ) || ( !str_prefix( target_name, "unique" ) ) ) continue; for( in_obj = ob; in_obj->in_obj != NULL; in_obj = in_obj->in_obj ) ; if( ( in_obj->carried_by != NULL ) && ( IS_IMMORTAL( in_obj->carried_by ) || ( !IS_NPC( in_obj->carried_by ) && IS_WOLF( in_obj->carried_by ) && ( IS_SHIFTED( in_obj->carried_by ) || ( IS_RAGED( in_obj->carried_by ) ) ) ) ) ) break; if( in_obj->carried_by != NULL ) { found = TRUE; xprintf( buf, "%s carried by %s.\n\r", ob->short_descr, can_see( ch, in_obj->carried_by ) ? PERS( in_obj->carried_by, ch ) : "someone" ); } else { found = TRUE; xprintf( buf, "%s in %s.\n\r", ob->short_descr, in_obj->in_room == NULL ? "somewhere" : in_obj->in_room->name ); } buf[0] = UPPER( buf[0] ); send_to_char( buf, ch ); } if( !found ) send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch ); return TRUE; } bool spell_magic_missile( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; int cnt; int hits; static const sh_int dam_each[] = { 0, 3, 3, 4, 4, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14 }; int dam; 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; cnt = 1 + ( level >= 30 ) + ( level >= 60 ) + ( level >= 80 ); for( hits = 0; hits < cnt; hits++ ) { sp_damage( obj, ch, victim, dam, REALM_IMPACT, sn, TRUE ); } return TRUE; } bool spell_mass_invis( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { AFFECT_DATA af; CHAR_DATA *gch; for( gch = ch->in_room->first_person; gch != NULL; gch = gch->next_in_room ) { if( IS_AFFECTED( gch, AFF_INVISIBLE ) || item_has_apply( gch, ITEM_APPLY_INV ) ) continue; act( "$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM ); send_to_char( "You slowly fade out of existence.\n\r", gch ); af.type = sn; af.duration = 4 + ( level / 5 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INVISIBLE; affect_to_char( gch, &af ); } send_to_char( "Ok.\n\r", ch ); return TRUE; } bool spell_null( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { send_to_char( "That's not a spell!\n\r", ch ); return FALSE; } bool spell_pass_door( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_PASS_DOOR ) || item_has_apply( victim, ITEM_APPLY_PASS_DOOR ) ) return FALSE; af.type = sn; af.duration = 2 + ( level / 20 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_PASS_DOOR; affect_to_char( victim, &af ); act( "$n turns translucent.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You turn translucent.\n\r", victim ); return TRUE; } bool spell_poison( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( saves_spell( level, victim ) ) return TRUE; af.type = sn; af.duration = 12 + ( level / 10 ); af.location = APPLY_STR; af.modifier = -2; af.bitvector = AFF_POISON; affect_join( victim, &af ); send_to_char( "You feel very sick.\n\r", victim ); act( "$n looks very sick.", victim, NULL, NULL, TO_ROOM ); return TRUE; } bool spell_protection( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_PROTECT ) || item_has_apply( victim, ITEM_APPLY_PROT ) ) return ( ch == victim ? FALSE : TRUE ); af.type = sn; af.duration = 8 + ( level / 5 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_PROTECT; affect_to_char( victim, &af ); send_to_char( "You feel protected.\n\r", victim ); act( "$n looks better protected.", victim, NULL, NULL, TO_ROOM ); return TRUE; } bool spell_refresh( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( ch->carry_weight >= can_carry_w( ch ) ) { send_to_char( "That's not gonna help, you are carrying too much wieght!\n\r", ch ); return FALSE; } victim->move = UMIN( victim->move + level, victim->max_move ); send_to_char( "You feel less tired.\n\r", victim ); act( "$n looks less tired.", victim, NULL, NULL, TO_ROOM ); return TRUE; } bool spell_remove_curse( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( is_affected( victim, gsn_curse ) ) { affect_strip( victim, gsn_curse ); send_to_char( "You feel better.\n\r", victim ); act( "$n looks more Holy.", victim, NULL, NULL, TO_ROOM ); } return TRUE; } bool spell_sanctuary( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_SANCTUARY ) || item_has_apply( victim, ITEM_APPLY_SANC ) ) return ( ch == victim ? FALSE : TRUE ); af.type = sn; af.duration = 5 + ( level / 20 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SANCTUARY; affect_to_char( victim, &af ); act( "$n is surrounded by a white aura.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are surrounded by a white aura.\n\r", victim ); return TRUE; } bool spell_sense_evil( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_DETECT_EVIL ) ) return FALSE; af.type = sn; af.duration = 5 + ( level / 10 ); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_EVIL; affect_to_char( victim, &af ); send_to_char( "Your eyes tingle.\n\r", victim ); act( "$n's eyes glow briefly.", victim, NULL, NULL, TO_ROOM ); return TRUE; } bool spell_shield( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( is_affected( victim, sn ) ) return FALSE; af.type = sn; af.duration = 4 + ( level / 5 ); af.location = APPLY_AC; af.modifier = -20 - get_psuedo_level( ch ) / 5; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n is surrounded by a force shield.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are surrounded by a force shield.\n\r", victim ); return TRUE; } bool spell_shocking_grasp( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; static const int dam_each[] = { 0, 0, 0, 0, 0, 0, 0, 20, 25, 29, 33, 36, 39, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57 }; int dam; level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 ); level = UMAX( 0, level ); dam = number_range( dam_each[level] / 2, dam_each[level] * 2 ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_SHOCK, sn, TRUE ); return TRUE; } bool spell_sleep( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_SLEEP ) || level < victim->level || saves_spell( level, victim ) ) return TRUE; af.type = sn; af.duration = 4 + ( level / 15 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; affect_join( victim, &af ); if( IS_AWAKE( victim ) ) { send_to_char( "You feel very sleepy ..... zzzzzz.\n\r", victim ); /* * will stop the char from attackin' right away (4-24-96) * -Damane- */ if( victim->position == POS_FIGHTING ) stop_fighting( victim, TRUE ); do_sleep( victim, "" ); } return TRUE; } bool spell_stone_skin( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( is_affected( ch, sn ) || is_affected( ch, skill_lookup( "stone skin" ) ) ) return FALSE; af.type = sn; af.duration = 5 + ( level / 12 ); af.location = APPLY_AC; af.modifier = -40 - get_psuedo_level( ch ) / 10; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n's skin turns to stone.", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your skin turns to stone.\n\r", victim ); return TRUE; } bool spell_summon( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim; char buf[MAX_STRING_LENGTH]; if( ( victim = get_char_world( ch, target_name ) ) == NULL || victim == ch || victim->in_room == NULL || IS_SET( victim->in_room->room_flags, ROOM_SAFE ) || IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL ) || !( IS_SET( victim->in_room->area->flags, AREA_TELEPORT ) ) || victim->level >= level + 10 || victim->fighting != NULL || ( IS_NPC( victim ) && saves_spell( level, victim ) ) || room_is_private( ch->in_room ) || ( ch->in_room->area->max_level < ( victim->level - 15 ) ) ) { send_to_char( "You failed.\n\r", ch ); return TRUE; } if( ( IS_SET( victim->act, PLR_NOSUMMON ) ) || ( IS_NPC( victim ) && ( victim->level > ( level - 21 ) ) ) ) { send_to_char( "You seemed unable to snatch your victim!\n\r", ch ); send_to_char( "You feel a slight tugging sensation.\n\r", victim ); return TRUE; } act( "$n disappears suddenly.", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, ch->in_room ); act( "$n arrives suddenly.", victim, NULL, NULL, TO_ROOM ); xprintf( buf, "%s has summoned you!!", ch->name ); send_to_char( buf, victim ); do_look( victim, "auto" ); return TRUE; } bool spell_teleport( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; ROOM_INDEX_DATA *pRoomIndex; if( deathmatch ) { send_to_char( "Not during a @@eDeath Match@@N!!\n\r", ch ); return FALSE; } if( victim->in_room == NULL || IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL ) || ( !IS_NPC( ch ) && victim->fighting != NULL ) || ( victim != ch && ( saves_spell( level, victim ) || saves_spell( level, victim ) ) ) ) { send_to_char( "You failed.\n\r", ch ); return TRUE; } for( ;; ) { pRoomIndex = get_room_index( number_range( 0, 32767 ) ); if( pRoomIndex == NULL ) continue; if( !IS_SET( pRoomIndex->room_flags, ROOM_PRIVATE ) && !IS_SET( pRoomIndex->room_flags, ROOM_SOLITARY ) && IS_SET( pRoomIndex->area->flags, AREA_TELEPORT ) ) break; } act( "$n slowly fades out of existence.", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, pRoomIndex ); act( "$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM ); do_look( victim, "auto" ); return TRUE; } bool spell_ventriloquate( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { char buf1[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; char speaker[MAX_INPUT_LENGTH]; CHAR_DATA *vch; target_name = one_argument( target_name, speaker ); xprintf( buf1, "%s says '%s'.\n\r", speaker, target_name ); xprintf( buf2, "Someone makes %s say '%s'.\n\r", speaker, target_name ); buf1[0] = UPPER( buf1[0] ); for( vch = ch->in_room->first_person; vch != NULL; vch = vch->next_in_room ) { if( !is_name( speaker, vch->name ) ) send_to_char( saves_spell( level, vch ) ? buf2 : buf1, vch ); } return TRUE; } bool spell_weaken( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( is_affected( victim, sn ) || saves_spell( level, victim ) ) return TRUE; af.type = sn; af.duration = 1 + ( level / 16 ); af.location = APPLY_STR; af.modifier = -2; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "You feel weaker.\n\r", victim ); if( ch != victim ) send_to_char( "Ok.\n\r", ch ); return TRUE; } /* * For Ack! : Level 66 Priest spell - allow 100% recall. */ bool spell_word_of_recall( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; ROOM_INDEX_DATA *location; act( "$n requests Holy transport!", victim, NULL, NULL, TO_ROOM ); if( IS_AFFECTED( victim, AFF_CURSE ) ) { send_to_char( "The Gods do not transport cursed players!\n\r", ch ); return FALSE; } if( IS_NPC( victim ) || victim->level < 6 ) location = get_room_index( ROOM_VNUM_TEMPLE ); else location = get_room_index( race_table[victim->race].recall ); if( location == NULL ) { send_to_char( "You are completely lost.\n\r", victim ); return FALSE; } if( victim->in_room == location ) return FALSE; if( IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL ) ) { send_to_char( "Some strange force prevents your transport.\n\r", victim ); return TRUE; } if( victim->fighting != NULL ) stop_fighting( victim, TRUE ); act( "$n is engulfed by a stream of blue light!", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, location ); act( "$n arrives, carried by a blue stream of light!", victim, NULL, NULL, TO_ROOM ); do_look( victim, "auto" ); return TRUE; } /* * NPC spells. */ bool spell_acid_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Fixed the nice bug that referenced the _caster's_ equipment, * * so that it checks the victim's instead *laugh* -S- */ CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; int dam; int hpch; if( number_percent( ) < 2 * level && !saves_spell( level, victim ) ) { OREF( obj_next, OBJ_NEXTCONTENT ); for( obj_lose = victim->first_carry; obj_lose != NULL; obj_lose = obj_next ) { int iWear; obj_next = obj_lose->next_in_carry_list; if( number_bits( 2 ) != 0 ) continue; switch ( obj_lose->item_type ) { case ITEM_ARMOR: if( obj_lose->value[0] > 0 ) { act( "$p is pitted and etched!", victim, obj_lose, NULL, TO_CHAR ); if( ( iWear = obj_lose->wear_loc ) != WEAR_NONE ) victim->armor -= apply_ac( obj_lose, iWear ); obj_lose->value[0] -= 1; obj_lose->cost = 0; if( iWear != WEAR_NONE ) victim->armor += apply_ac( obj_lose, iWear ); } break; case ITEM_CONTAINER: { OBJ_DATA *content; OBJ_DATA *content_next; act( "$p fumes and dissolves!", victim, obj_lose, NULL, TO_CHAR ); for( content = obj_lose->first_in_carry_list; content; content = content_next ) { content_next = content->next_in_carry_list; obj_from_obj( content ); obj_to_room( content, victim->in_room != NULL ? victim->in_room : get_room_index( ROOM_VNUM_LIMBO ) ); } extract_obj( obj_lose ); break; } } } OUREF( obj_next ); } hpch = UMAX( 10, ch->hit ); dam = number_range( hpch / 16 + 1, hpch / 8 ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_ACID | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_fire_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; int dam; int hpch; if( !IS_NPC( ch ) ) { dam = number_range( get_psuedo_level( ch ) * 1.2, get_psuedo_level( ch ) * 1.6 ); if( saves_spell( level, victim ) ) dam /= 2; damage( ch, victim, dam, sn ); return TRUE; } if( number_percent( ) < 2 * level && !saves_spell( level, victim ) ) { OREF( obj_next, OBJ_NEXTCONTENT ); for( obj_lose = victim->first_carry; obj_lose != NULL; obj_lose = obj_next ) { char *msg; obj_next = obj_lose->next_in_carry_list; if( number_bits( 2 ) != 0 ) continue; switch ( obj_lose->item_type ) { default: continue; case ITEM_CONTAINER: msg = "$p ignites and burns!"; break; case ITEM_POTION: msg = "$p bubbles and boils!"; break; case ITEM_SCROLL: msg = "$p crackles and burns!"; break; case ITEM_STAFF: msg = "$p smokes and chars!"; break; case ITEM_WAND: msg = "$p sparks and sputters!"; break; case ITEM_FOOD: msg = "$p blackens and crisps!"; break; case ITEM_PILL: msg = "$p melts and drips!"; break; } act( msg, victim, obj_lose, NULL, TO_CHAR ); if( obj_lose->item_type == ITEM_CONTAINER ) { OBJ_DATA *content; OBJ_DATA *content_next; OREF( content_next, OBJ_NEXTCONTENT ); for( content = obj_lose->first_in_carry_list; content; content = content_next ) { content_next = content->next_in_carry_list; obj_from_obj( content ); obj_to_room( content, victim->in_room != NULL ? victim->in_room : get_room_index( ROOM_VNUM_LIMBO ) ); } OUREF( content_next ); extract_obj( obj_lose ); } } OUREF( obj_next ); } hpch = UMAX( 10, ch->hit ); dam = number_range( hpch / 16 + 1, hpch / 8 ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_FIRE | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_frost_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; OBJ_DATA *obj_lose; OBJ_DATA *obj_next; int dam; int hpch; if( number_percent( ) < 2 * level && !saves_spell( level, victim ) ) { OREF( obj_next, OBJ_NEXTCONTENT ); for( obj_lose = victim->first_carry; obj_lose != NULL; obj_lose = obj_next ) { char *msg; obj_next = obj_lose->next_in_carry_list; if( number_bits( 2 ) != 0 ) continue; switch ( obj_lose->item_type ) { default: continue; case ITEM_CONTAINER: case ITEM_DRINK_CON: case ITEM_POTION: msg = "$p freezes and shatters!"; break; } act( msg, victim, obj_lose, NULL, TO_CHAR ); if( obj_lose->item_type == ITEM_CONTAINER ) { OBJ_DATA *content; OBJ_DATA *content_next; OREF( content_next, OBJ_NEXTCONTENT ); for( content = obj_lose->first_in_carry_list; content; content = content_next ) { content_next = content->next_in_carry_list; obj_from_obj( content ); obj_to_room( content, victim->in_room != NULL ? victim->in_room : get_room_index( ROOM_VNUM_LIMBO ) ); } OUREF( content_next ); } } OUREF( obj_next ); } hpch = UMAX( 10, ch->hit ); dam = number_range( hpch / 16 + 1, hpch / 8 ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_COLD | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_gas_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *vch; CHAR_DATA *vch_next; int dam; int hpch; CREF( vch_next, CHAR_NEXTROOM ); for( vch = ch->in_room->first_person; vch != NULL; vch = vch_next ) { vch_next = vch->next_in_room; if( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) { hpch = UMAX( 10, ch->hit ); dam = number_range( hpch / 16 + 1, hpch / 8 ); if( saves_spell( level, vch ) ) dam /= 2; sp_damage( obj, ch, vch, dam, REALM_GAS | NO_REFLECT | NO_ABSORB, sn, TRUE ); } } CUREF( vch_next ); return TRUE; } bool spell_lightning_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; int dam; int hpch; hpch = UMAX( 10, ch->hit ); dam = number_range( hpch / 16 + 1, hpch / 8 ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_SHOCK | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_hellspawn( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * High level mag / psi spell. -S- */ CHAR_DATA *victim = ( CHAR_DATA * ) vo; int dam; dam = number_range( level / 2, level * 5 / 2 ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_DRAIN, sn, TRUE ); return TRUE; } bool spell_planergy( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Psi spell. Work out which energy to summon, according to * * ch's level. Each 9 levels, the Psi gets the use of a different * * spell, and more damage! ;) (planergy = planar energy) * * --Stephen */ CHAR_DATA *victim = ( CHAR_DATA * ) vo; int dam; int lvl; int plane; if( level <= 8 ) { lvl = 4; plane = REALM_IMPACT; } else if( level <= 17 ) { lvl = 13; plane = REALM_GAS; } else if( level <= 26 ) { lvl = 22; plane = REALM_FIRE; } else if( level <= 35 ) { lvl = 31; plane = REALM_LIGHT; } else if( level <= 44 ) { lvl = 40; plane = REALM_SHOCK; } else if( level <= 53 ) { lvl = 49; plane = REALM_SOUND; } else if( level <= 62 ) { lvl = 58; plane = REALM_MIND; } else if( level <= 71 ) { lvl = 67; plane = REALM_ACID; } else { lvl = 80; plane = REALM_POISON; } dam = dice( 6, lvl / 2 ); if( saves_spell( level, victim ) ) dam /= 2; SET_BIT( plane, NO_REFLECT ); SET_BIT( plane, NO_ABSORB ); sp_damage( obj, ch, victim, dam, plane, sn, TRUE ); return TRUE; } bool spell_visit( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Psi spell. Kinda like summon, but almost done in reverse. * * allows the Psi to try and transfer themself to the 'victim' * * --Stephen */ CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( deathmatch ) { send_to_char( "Not during a @@eDeath Match@@N!!\n\r", ch ); return FALSE; } if( ( victim = get_char_world( ch, target_name ) ) == NULL || victim == ch || IS_NPC( victim ) || victim->in_room == NULL || 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_SAFE ) || IS_SET( ch->in_room->room_flags, ROOM_NO_RECALL ) || !IS_SET( victim->in_room->area->flags, AREA_TELEPORT ) ) { send_to_char( "You failed.\n\r", ch ); return TRUE; } if( IS_SET( victim->act, PLR_NOVISIT ) ) { send_to_char( "You seem unable to visit your target!\n\r", ch ); return TRUE; } /* * Check is ch screws up, and ends up in limbo... <grin> */ if( number_percent( ) < 25 ) /* 25% chance */ { send_to_char( "You get distracted, and appear in the middle of nowhere!\n\r", ch ); act( "$n disappears suddenly.", ch, NULL, NULL, TO_ROOM ); char_from_room( ch ); char_to_room( ch, get_room_index( ROOM_VNUM_LIMBO ) ); act( "$n arrives suddenly.", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); return TRUE; } act( "$n disappears suddenly.", ch, NULL, NULL, TO_ROOM ); char_from_room( ch ); char_to_room( ch, victim->in_room ); act( "$n arrives suddenly.", ch, NULL, NULL, TO_ROOM ); send_to_char( "You change locations!\n\r", ch ); do_look( ch, "auto" ); return TRUE; } bool spell_barrier( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Psi spell, like shield, but slightly better. Good idea to make * * sure Psi's don't have access to shield as well as this... ;) * * -- Stephen */ CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( is_affected( victim, sn ) ) return FALSE; af.type = sn; af.duration = 4 + ( level / 20 ); af.location = APPLY_AC; af.modifier = -20 - get_psuedo_level( ch ) / 10; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n is surrounded by a telekinetic barrier.", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are surrounded by a telekinetic barrier.\n\r", victim ); return TRUE; } bool spell_static( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Psi Spell. * * Uses ch's movement, which is transfered to static electricity * * which is then chanelled at the poor victim <laugh> * * --Stephen */ CHAR_DATA *victim = ( CHAR_DATA * ) vo; int dam; int loss; send_to_char( "You transfer kinetic to static energy!\n\r", ch ); loss = dice( 2, level ) + dice( 2, level ); dam = number_range( 6, 8 ) * ( level / 3 ); if( ( ch->move - loss ) <= 0 ) { send_to_char( "You have no kinetic energy left!!\n\r", ch ); return FALSE; } ch->move = UMAX( 1, ch->move - loss ); if( saves_spell( level, victim ) ) dam /= 2; act( "$n transfers kinetic to static energy.", ch, NULL, NULL, TO_ROOM ); sp_damage( obj, ch, victim, dam, REALM_SHOCK | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_phobia( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Psi Spell. * * Conjures victims's phobia in their mind, does dam (small) or * * causes them to flee. * * --Stephen */ CHAR_DATA *victim = ( CHAR_DATA * ) vo; int dam; if( ( victim->level ) > ( level + 8 ) ) { send_to_char( "Your spell fails to take affect!\n\r", ch ); return TRUE; } /* * figure out dam.... not too much as spell is meant to make vo flee */ dam = dice( 2, level / 8 ); if( obj == NULL ) { act( "$n projects nightmare images into $N's mind!", ch, NULL, victim, TO_NOTVICT ); act( "You project nightmare images into $N's mind!", ch, NULL, victim, TO_CHAR ); act( "$N projects nightmare images into your mind!", victim, NULL, ch, TO_CHAR ); } else { act( "$p projects nightmare images into $n's mind!", victim, obj, NULL, TO_ROOM ); act( "$p projects nightmare images into your mind!", victim, obj, NULL, TO_CHAR ); } send_to_char( "Your worst phobia springs to life in your mind. Arrrggghhh!\n\r", victim ); act( "$N suffers a mental phobia attack!", ch, NULL, victim, TO_NOTVICT ); if( sp_damage( obj, ch, victim, dam, REALM_MIND, sn, TRUE ) ) { if( !IS_NPC( victim ) && ( IS_WOLF( victim ) || IS_VAMP( victim ) ) ) return TRUE; if( number_percent( ) < 70 ) /* 70% chance */ { act( "$N screams at $n in horror!!", ch, NULL, victim, TO_ROOM ); act( "$N screams at you in horror!!", ch, NULL, victim, TO_CHAR ); send_to_char( "You flip, and look for escape!!\n\r", victim ); do_flee( victim, "" ); } } return TRUE; } bool spell_mindflame( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Psi Multiple Attack - screws up all those affected */ CHAR_DATA *vch; CHAR_DATA *vch_next; if( obj == NULL ) { send_to_char( "You initiate a mindflame attack!!\n\r", ch ); act( "$n concentrates, and initiates a mindlame attack!", ch, NULL, NULL, TO_ROOM ); } else { act( "$p glows, and initiates a mindflame attack!", ch, obj, NULL, TO_ROOM ); act( "$p glows, and initiates a mindflame attack!", ch, obj, NULL, TO_CHAR ); } CREF( vch_next, CHAR_NEXT ); for( vch = first_char; vch != NULL; vch = vch_next ) { vch_next = vch->next; if( vch->in_room == NULL ) continue; if( vch->in_room == ch->in_room ) { if( vch != ch && ( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) ) { act( "$n rolls on the floor, clutching $s head in pain!", vch, NULL, NULL, TO_ROOM ); send_to_char( "You roll on the floor, clutching your head in pain!\n\r", vch ); sp_damage( obj, ch, vch, ( get_psuedo_level( ch ) / 2 ) + dice( 6, 12 ), REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE ); } continue; } if( vch->in_room->area == ch->in_room->area ) send_to_char( "You notice a slight burning feeling in your mind.\n\r", vch ); } CUREF( vch_next ); return TRUE; } bool spell_chain_lightning( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * affects all in a room, can also hit caster <grin> */ CHAR_DATA *vch; CHAR_DATA *vch_next; int dam; /* * Work out starting damage. */ dam = dice( 10, ( get_psuedo_level( ch ) / 2 ) ); if( obj == NULL ) { send_to_char( "Lightning flashes from your fingers!\n\r", ch ); act( "$n unleashes lightning from $s fingers!", ch, NULL, NULL, TO_ROOM ); } else { act( "A lightning bolt flashes from $p!", ch, obj, NULL, TO_ROOM ); act( "A lightning bolt flashes from $p!", ch, obj, NULL, TO_CHAR ); } CREF( vch_next, CHAR_NEXTROOM ); for( vch = ch->in_room->first_person; vch != NULL; vch = vch_next ) { vch_next = vch->next_in_room; if( vch != ch && IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) { send_to_char( "The lightning bolt strikes you!\n\r", vch ); act( "The lightning bolt strikes $n!", vch, NULL, NULL, TO_ROOM ); sp_damage( obj, ch, vch, dam, REALM_SHOCK | NO_REFLECT, sn, TRUE ); dam = ( 4 * dam / 5 ); } } CUREF( vch_next ); /* * Now see if caster gets hit. */ if( saves_spell( level, ch ) ) { act( "The lightning bolt hits the ground, and is GONE!", ch, NULL, NULL, TO_ROOM ); send_to_char( "Your lightning bolts hits the ground and is GONE!\n\r", ch ); } else { act( "The lightning bolt strikes $n and vanishes!", ch, NULL, NULL, TO_ROOM ); send_to_char( "Your lightning returns, and hits you!\n\r", ch ); dam = UMIN( level / 2, dam ); sp_damage( obj, ch, ch, dam, REALM_SHOCK | NO_REFLECT | NO_ABSORB, sn, TRUE ); } return TRUE; } bool spell_suffocate( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; int dam; dam = dice( level / 3, 2 ); if( ( level + 5 ) > victim->level ) dam += ( ( ( level + 5 ) - victim->level ) * 2 ); else dam -= ( ( victim->level - level ) * 2 ); act( "$n chokes and gags!", victim, NULL, NULL, TO_ROOM ); send_to_char( "You feel your throat squeezed by an invisible force!\n\r", victim ); sp_damage( obj, ch, victim, dam, REALM_IMPACT, sn, TRUE ); /* -1 = no dam message */ return TRUE; } bool spell_enhance_weapon( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { OBJ_DATA *ob = ( OBJ_DATA * ) vo; AFFECT_DATA *paf; /* * Quick way to stop imms (Bash?) enchanting weapons for players */ if( IS_IMMORTAL( ch ) && ch->level != 85 ) { send_to_char( "Nothing Happens.\n\r", ch ); return FALSE; } if( ob->item_type != ITEM_WEAPON || IS_OBJ_STAT( ob, ITEM_MAGIC ) || ob->first_apply != NULL ) return TRUE; GET_FREE( paf, affect_free ); paf->type = sn; paf->duration = 3 + ( level / 4 ); paf->location = APPLY_HITROLL; paf->modifier = 3; paf->bitvector = 0; LINK( paf, ob->first_apply, ob->last_apply, next, prev ); GET_FREE( paf, affect_free ); paf->type = -1; paf->duration = 3 + ( level / 4 ); paf->location = APPLY_DAMROLL; paf->modifier = 2; paf->bitvector = 0; LINK( paf, ob->first_apply, ob->last_apply, next, prev ); act( "$p shines brightly.", ch, ob, NULL, TO_CHAR ); act( "$p belonging to $n shines brightly.", ch, ob, NULL, TO_ROOM ); return TRUE; } bool spell_bloody_tears( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( IS_AFFECTED( victim, AFF_BLIND ) || saves_spell( level, victim ) ) return TRUE; act( "$n's eyes start bleeding!", victim, NULL, NULL, TO_ROOM ); send_to_char( "Your eyes start bleeding!\n\r", victim ); spell_blindness( skill_lookup( "blindness" ), level, ch, vo, obj ); sp_damage( obj, ch, victim, ( level / 2 ), REALM_MIND | NO_REFLECT | NO_ABSORB, sn, FALSE ); /* -1 = no dam message */ return TRUE; } bool spell_mind_bolt( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; int cnt; int foo; int dam; cnt = ( level >= 12 ) + ( level >= 30 ) + ( level >= 60 ) + ( ch->level >= 75 ); for( foo = 0; foo < cnt; foo++ ) { if( number_range( 0, 99 ) < 30 ) continue; dam = number_range( level / 4, level * 2 / 3 ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE ); /* -1 = no dam message */ } return TRUE; } bool spell_nerve_fire( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *vch; CHAR_DATA *vch_next; if( obj == NULL ) { send_to_char( "You initiate a Nerve Fire attack!!\n\r", ch ); act( "$n concentrates, and initiates a Nerve Fire attack!", ch, NULL, NULL, TO_ROOM ); } else { act( "$p glows with the power of Nerve Fire!", ch, obj, NULL, TO_ROOM ); act( "$p glows with the power of Nerve Fire!", ch, obj, NULL, TO_CHAR ); } CREF( vch_next, CHAR_NEXT ); for( vch = first_char; vch != NULL; vch = vch_next ) { vch_next = vch->next; if( vch->in_room == NULL ) continue; if( vch->in_room == ch->in_room ) { if( vch != ch && ( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) ) { sp_damage( obj, ch, vch, ( level ) + dice( 5, 20 ), REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE ); } continue; } if( vch->in_room->area == ch->in_room->area ) send_to_char( "You notice a slight burning feeling in your body.\n\r", vch ); } CUREF( vch_next ); return TRUE; } bool spell_fighting_trance( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( is_affected( victim, sn ) ) return FALSE; af.type = sn; af.duration = 6 + ( level / 20 ); af.location = APPLY_HITROLL; af.modifier = get_psuedo_level( ch ) / 10; af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = 0 - level / 8; affect_to_char( victim, &af ); af.location = APPLY_DAMROLL; af.modifier = get_psuedo_level( ch ) / 10; affect_to_char( victim, &af ); af.location = APPLY_AC; af.modifier = -10 - get_psuedo_level( ch ) / 10; affect_to_char( victim, &af ); send_to_char( "You feel much stronger.\n\r", victim ); act( "$n looks much stronger.", victim, NULL, NULL, TO_ROOM ); if( ch != victim ) send_to_char( "Ok.\n\r", ch ); return TRUE; } bool spell_phase( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_PASS_DOOR ) || item_has_apply( victim, ITEM_APPLY_PASS_DOOR ) ) return FALSE; af.type = sn; af.duration = 3 + ( level / 20 ); af.location = APPLY_AC; af.modifier = -10 - get_psuedo_level( ch ) / 10; af.bitvector = AFF_PASS_DOOR; affect_to_char( victim, &af ); send_to_char( "Your body switches phase.\n\r", victim ); act( "$n's body switches phase.", victim, NULL, NULL, TO_ROOM ); return TRUE; } bool spell_dimension_blade( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { OBJ_DATA *ob = ( OBJ_DATA * ) vo; AFFECT_DATA *paf; /* * Quick way to stop imms (Bash?) enchanting weapons for players */ if( IS_IMMORTAL( ch ) && ch->level != 85 ) { send_to_char( "Nothing Happens.\n\r", ch ); return FALSE; } if( dice( 4, 5 ) == 20 ) { act( "$p shatters into pieces!", ch, ob, NULL, TO_CHAR ); act( "$p carried by $n shatters!", ch, ob, NULL, TO_ROOM ); extract_obj( ob ); return TRUE; } if( ob->item_type != ITEM_WEAPON || IS_OBJ_STAT( ob, ITEM_MAGIC ) || ob->first_apply != NULL ) return TRUE; GET_FREE( paf, affect_free ); paf->type = sn; paf->duration = -1; paf->location = APPLY_HITROLL; paf->modifier = 1 + ( level >= 50 ) + ( level >= 60 ) + ( level >= 70 ); paf->bitvector = 0; LINK( paf, ob->first_apply, ob->last_apply, next, prev ); GET_FREE( paf, affect_free ); paf->type = -1; paf->duration = -1; paf->location = APPLY_DAMROLL; paf->modifier = 1 + ( level >= 55 ) + ( level >= 70 ); paf->bitvector = 0; LINK( paf, ob->first_apply, ob->last_apply, next, prev ); act( "Part of $p switches into a different plane.", ch, ob, NULL, TO_CHAR ); act( "$n makes $p into a dimension blade.", ch, ob, NULL, TO_ROOM ); return TRUE; } bool spell_produce_food( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { OBJ_DATA *mushroom; mushroom = create_object( get_obj_index( OBJ_VNUM_FOOD ), 0 ); mushroom->value[0] = 5 + level; obj_to_room( mushroom, ch->in_room ); act( "$p suddenly appears.", ch, mushroom, NULL, TO_ROOM ); act( "$p suddenly appears.", ch, mushroom, NULL, TO_CHAR ); return TRUE; } bool spell_animate( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { OBJ_DATA *ob; OBJ_DATA *bits; CHAR_DATA *corpse; if( IS_NPC( ch ) ) return FALSE; ob = get_obj_here( ch, target_name ); if( ob == NULL ) { send_to_char( "Couldn't find it.\n\r", ch ); return FALSE; } if( ch->lvl2[3] < 70 ) { send_to_char( " @@eDUE TO A ROLEPLAYING CHANGE, THIS SPELL IS NO LONGER AVAILABLE TO ANY CLASS\n\r", ch ); send_to_char( " BUT a high level @@dNECRMOANCER@@N. THE SKILL HAS BEEN REMOVED FROM YOU CHARACTER, \n\r", ch ); send_to_char( " SORRY FOR THE INCONVIENENCE. @@mTHANK YOU@@N :)\n\r", ch ); ch->pcdata->learned[sn] = 0; return FALSE; } if( ob->item_type != ITEM_CORPSE_NPC ) { send_to_char( "You can't animate that!\n\r", ch ); return FALSE; } act( "$n lays $s hands onto the $p!", ch, ob, NULL, TO_ROOM ); act( "You lay your hands upon the $p.", ch, ob, NULL, TO_CHAR ); act( "Bright bolts of lightning fly out from $p!!", ch, ob, NULL, TO_ROOM ); act( "Bright bolts of lightning fly out from $p!!", ch, ob, NULL, TO_CHAR ); corpse = create_mobile( get_mob_index( MOB_VNUM_ZOMBIE ) ); char_to_room( corpse, ch->in_room ); act( "$n stands up, and stretches slowly.", corpse, NULL, NULL, TO_ROOM ); if( ob->item_type == ITEM_CORPSE_NPC ) { SET_BIT( corpse->act, ACT_UNDEAD ); act( "$n's eyes glow black!", corpse, NULL, NULL, TO_ROOM ); } corpse->level = ob->level; /* Level of (N)PC before death */ corpse->max_hit = dice( 5, level ); corpse->hit = corpse->max_hit; corpse->max_move = dice( 10, level ); corpse->move = corpse->max_move; /* Set Zombie's stats */ for( ;; ) { if( ob->first_in_carry_list == NULL ) break; bits = ob->first_in_carry_list; obj_from_obj( bits ); obj_to_char( bits, corpse ); } extract_obj( ob ); do_wear( corpse, "all" ); /* FIXME: better to check items, then wear... */ SET_BIT( corpse->act, ACT_PET ); SET_BIT( corpse->affected_by, AFF_CHARM ); corpse->extract_timer = get_psuedo_level( ch ) / 3; add_follower( corpse, ch ); return TRUE; } bool spell_see_magic( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_DETECT_MAGIC ) || item_has_apply( victim, ITEM_APPLY_HIDE ) ) return FALSE; af.type = sn; af.duration = 6 + ( level / 4 ); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_MAGIC; affect_to_char( victim, &af ); send_to_char( "Your eyes tingle.\n\r", victim ); act( "$n's eyes glow briefly.", victim, NULL, NULL, TO_ROOM ); return TRUE; } bool spell_detection( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { char buf[MAX_INPUT_LENGTH]; OBJ_DATA *ob; OBJ_DATA *in_obj; bool found; found = FALSE; for( ob = first_obj; ob != NULL; ob = ob->next ) { if( !can_see_obj( ch, ob ) || !is_name( target_name, ob->name ) || IS_SET( ob->extra_flags, ITEM_RARE ) || ( ob->item_type == ITEM_PIECE ) || ( IS_SET( ob->extra_flags, ITEM_UNIQUE ) ) || ( !str_prefix( target_name, "unique" ) ) ) continue; for( in_obj = ob; in_obj->in_obj != NULL; in_obj = in_obj->in_obj ) ; if( ( in_obj->carried_by != NULL ) && ( IS_IMMORTAL( in_obj->carried_by ) || ( !IS_NPC( in_obj->carried_by ) && IS_WOLF( in_obj->carried_by ) && ( IS_SHIFTED( in_obj->carried_by ) || ( IS_RAGED( in_obj->carried_by ) ) ) ) ) ) break; if( in_obj->carried_by != NULL ) { found = TRUE; xprintf( buf, "%s carried by %s.\n\r", ob->short_descr, can_see( ch, in_obj->carried_by ) ? PERS( in_obj->carried_by, ch ) : "someone" ); } else { found = TRUE; xprintf( buf, "%s in %s.\n\r", ob->short_descr, in_obj->in_room == NULL ? "somewhere" : in_obj->in_room->name ); } buf[0] = UPPER( buf[0] ); send_to_char( buf, ch ); } if( !found ) send_to_char( "You fail to detect any such object.\n\r", ch ); return TRUE; } bool spell_fire_blade( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { OBJ_DATA *blade; if( get_obj_wear( ch, "fireblade" ) != NULL ) return FALSE; /* Only have one at a time.. */ if( remove_obj( ch, WEAR_HOLD_HAND_L, TRUE ) ) { blade = create_object( get_obj_index( OBJ_VNUM_FIREBLADE ), level ); obj_to_char( blade, ch ); equip_char( ch, blade, WEAR_HOLD_HAND_L ); blade->timer = 2 + ( level / 20 ); act( "A blazing FireBlade appears in $n's hand!", ch, NULL, NULL, TO_ROOM ); send_to_char( "A blazing FireBlade appears in your hand!", ch ); } return TRUE; } bool spell_know_weakness( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { AFFECT_DATA af; if( is_affected( ch, sn ) ) return FALSE; af.type = sn; af.duration = 2 + ( level >= 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 80 ); af.location = APPLY_HITROLL; af.modifier = 3; af.bitvector = 0; affect_to_char( ch, &af ); send_to_char( "You are more aware of your enemy's weaknesses.\n\r", ch ); return TRUE; } bool spell_know_critical( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { AFFECT_DATA af; if( is_affected( ch, sn ) ) return FALSE; af.type = sn; af.duration = 2 + ( level >= 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 80 ); af.location = APPLY_DAMROLL; af.modifier = 3; af.bitvector = 0; affect_to_char( ch, &af ); send_to_char( "You are more aware of critical damage points.\n\r", ch ); return TRUE; } bool spell_calm( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *ppl; int chance; for( ppl = ch->in_room->first_person; ppl != NULL; ppl = ppl->next_in_room ) if( IS_NPC( ppl ) && ppl != ch ) { chance = ( ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[sn] / 2 ) + ( 5 * ( level - ppl->level ) ) ); if( number_percent( ) < chance ) stop_fighting( ppl, TRUE ); } if( obj == NULL ) { act( "$n emits a great feeling of calm around you.", ch, NULL, NULL, TO_ROOM ); send_to_char( "You emit a great feeling of calm around you.\n\r", ch ); } else { act( "$p glows with a clam light.", ch, obj, NULL, TO_ROOM ); act( "$p glows with a clam light.", ch, obj, NULL, TO_CHAR ); } return TRUE; } bool spell_hypnosis( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( victim == ch ) { send_to_char( "You like yourself even better!\n\r", ch ); return FALSE; } if( !IS_NPC( victim ) ) { send_to_char( "You're not that powerful.\n\r", ch ); return FALSE; } if( IS_AFFECTED( victim, AFF_CHARM ) || IS_AFFECTED( ch, AFF_CHARM ) || level - 5 < victim->level || saves_spell( level, victim ) ) return TRUE; if( IS_VAMP( victim ) && ( IS_NPC( victim ) ) ) { send_to_char( "Wow, it seems to be immune--imagine that!\n\r", ch ); return TRUE; } if( victim->master ) stop_follower( victim ); add_follower( victim, ch ); af.type = sn; af.duration = 3 + ( level / 8 ); af.location = 0; af.modifier = 0; af.bitvector = AFF_CHARM; affect_to_char( victim, &af ); act( "Isn't $n just so nice?", ch, NULL, victim, TO_VICT ); if( ch != victim ) send_to_char( "Ok.\n\r", ch ); victim->extract_timer = get_psuedo_level( ch ) / 3; return TRUE; } bool spell_mind_flail( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { int dam; CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( victim == ch ) return FALSE; if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) ) return TRUE; dam = 5 + ( 10 * ( ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) ) ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_know_item( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { OBJ_DATA *ob = ( OBJ_DATA * ) vo; char buf[MAX_STRING_LENGTH]; AFFECT_DATA *paf; xprintf( buf, "Object '%s' is type %s, extra flags %s.\n\rWeight is %d.\n\r", ob->name, item_type_name( ob ), extra_bit_name( ob->extra_flags ), ob->weight ); send_to_char( buf, ch ); switch ( ob->item_type ) { case ITEM_SCROLL: case ITEM_POTION: xprintf( buf, "Level %d spells of:", ob->value[0] ); send_to_char( buf, ch ); if( ob->value[1] >= 0 && ob->value[1] < MAX_SKILL ) { send_to_char( " '", ch ); send_to_char( skill_table[ob->value[1]].name, ch ); send_to_char( "'", ch ); } if( ob->value[2] >= 0 && ob->value[2] < MAX_SKILL ) { send_to_char( " '", ch ); send_to_char( skill_table[ob->value[2]].name, ch ); send_to_char( "'", ch ); } if( ob->value[3] >= 0 && ob->value[3] < MAX_SKILL ) { send_to_char( " '", ch ); send_to_char( skill_table[ob->value[3]].name, ch ); send_to_char( "'", ch ); } send_to_char( ".\n\r", ch ); break; case ITEM_WAND: case ITEM_STAFF: xprintf( buf, "Has %d(%d) charges of level %d", ob->value[1], ob->value[2], ob->value[0] ); send_to_char( buf, ch ); if( ob->value[3] >= 0 && ob->value[3] < MAX_SKILL ) { send_to_char( " '", ch ); send_to_char( skill_table[ob->value[3]].name, ch ); send_to_char( "'", ch ); } send_to_char( ".\n\r", ch ); break; case ITEM_WEAPON: xprintf( buf, " Average damage is %d.\n\r", ( ob->value[1] + ob->value[2] ) / 2 ); send_to_char( buf, ch ); break; case ITEM_ARMOR: xprintf( buf, "Armor class is %d.\n\r", ob->value[0] ); send_to_char( buf, ch ); break; } for( paf = ob->first_apply; paf != NULL; paf = paf->next ) { if( paf->location != APPLY_NONE && paf->modifier != 0 ) { xprintf( buf, "Affects %s by %d.\n\r", affect_loc_name( paf->location ), paf->modifier ); send_to_char( buf, ch ); } } return TRUE; } bool spell_physic_thrust( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { int dam; CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( victim == ch ) return FALSE; if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) ) return TRUE; dam = 5 + ( 20 * ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_physic_crush( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { int dam; CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( victim == ch ) return FALSE; if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) ) return TRUE; dam = get_psuedo_level( ch ) / 2 + ( 30 * ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_ego_whip( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { int dam; CHAR_DATA *victim = ( CHAR_DATA * ) vo; if( victim == ch ) return FALSE; if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) ) return TRUE; dam = 50 + ( 40 * ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) ); if( saves_spell( level, victim ) ) dam /= 2; sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE ); return TRUE; } bool spell_night_vision( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_INFRARED ) || item_has_apply( victim, ITEM_APPLY_INFRA ) ) return ( ch == victim ? FALSE : TRUE ); act( "$n's eyes glow red.\n\r", ch, NULL, NULL, TO_ROOM ); af.type = sn; af.duration = 4 + ( level / 3 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INFRARED; affect_to_char( victim, &af ); send_to_char( "Your eyes glow red.\n\r", victim ); if( ch != victim ) send_to_char( "Ok.\n\r", ch ); return TRUE; } bool spell_stalker( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Fixed problem of stalker not finding victim, and attacking caster, * * thus giving an easy source of xp -S- */ CHAR_DATA *victim; CHAR_DATA *stalker; if( target_name[0] == '\0' ) { send_to_char( "Summon a stalker to hunt who?\n\r", ch ); return FALSE; } victim = get_char_world( ch, target_name ); if( victim == NULL ) { send_to_char( "Target can't be found!\n\r", ch ); return FALSE; } if( ch == victim ) { send_to_char( "That WOULDN'T be wise!\n\r", ch ); return FALSE; } act( "$n calls upon the dark powers to summon forth a Stalker!", ch, NULL, NULL, TO_ROOM ); send_to_char( "You call upon the dark powers to summon forth a Stalker!\n\r", ch ); stalker = create_mobile( get_mob_index( MOB_VNUM_STALKER ) ); char_to_room( stalker, ch->in_room ); act( "$n appears before you suddenly.", stalker, NULL, NULL, TO_ROOM ); stalker->level = victim->level; stalker->max_hit = victim->max_hit; stalker->hit = stalker->max_hit; stalker->exp = victim->level * 10; /* not much exp :P */ if( set_hunt( stalker, ch, victim, NULL, HUNT_MERC, HUNT_CR ) ) act( "$n sniffs the air in search of $s prey.", stalker, NULL, NULL, TO_ROOM ); else { int sn; sn = skill_lookup( "hellspawn" ); if( sn != 0 ) /* Check to be sure... should never == 0 */ ( *skill_table[sn].spell_fun ) ( sn, stalker->level, stalker, ch, NULL ); do_say( stalker, "How dare you waste my time!!" ); act( "$n returns to the dark planes, vanishing suddenly!", stalker, NULL, NULL, TO_ROOM ); /* * char_from_room( stalker ); */ extract_char( stalker, TRUE ); } return TRUE; } bool spell_mystic_armor( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( ch == victim ) { send_to_char( "You are mystically armored, but it suddenly fades away!\n\r", ch ); return FALSE; } if( is_affected( victim, sn ) ) return TRUE; af.type = sn; af.duration = 4 + ( level / 3 ); af.location = APPLY_AC; af.modifier = -10 - get_psuedo_level( ch ) / 8; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n is surrounded by $N's mystic armor.", victim, NULL, ch, TO_ROOM ); act( "$N is surrounded by your mystic armor.", ch, NULL, victim, TO_CHAR ); act( "You are surrounded by $N's mystic armor.", victim, NULL, ch, TO_CHAR ); return TRUE; } bool spell_flare( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { CHAR_DATA *victim = ( CHAR_DATA * ) vo; AFFECT_DATA af; if( IS_AFFECTED( victim, AFF_BLIND ) || saves_spell( level, victim ) ) return TRUE; if( victim == ch ) return FALSE; af.type = sn; af.location = APPLY_HITROLL; af.modifier = level / 4; af.duration = 1 + ( level / 4 ); af.bitvector = AFF_BLIND; affect_to_char( victim, &af ); act( "$n invokes the power of Ra to produce a solar flare which blinds $N!", ch, NULL, victim, TO_NOTVICT ); act( "$N invokes the power of Ra to produce a solar flare. You are BLINDED!", victim, NULL, ch, TO_CHAR ); act( "You invoke the power of Ra to produce a solar flare, which blinds $N!", ch, NULL, victim, TO_CHAR ); return TRUE; } bool spell_travel( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Transfer the player to Midgaard recall */ ROOM_INDEX_DATA *room; if( ch->fighting != NULL ) { send_to_char( "You can't travel when fighting!\n\r", ch ); return FALSE; } if( ( room = get_room_index( 3001 ) ) == NULL ) { send_to_char( "It seems the Midgaard Temple has vanished!\n\r", ch ); return FALSE; } act( "$n is engulfed by a stream of green light!", ch, NULL, NULL, TO_ROOM ); char_from_room( ch ); char_to_room( ch, room ); act( "$n arrives, carried by a stream of green light!", ch, NULL, NULL, TO_ROOM ); do_look( ch, "auto" ); return TRUE; } bool spell_window( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Create a magic window to look into another room */ OBJ_DATA *beacon; OBJ_DATA *ob; if( target_name[0] == '\0' ) { send_to_char( "Form a window to whom?\n\r", ch ); return FALSE; } beacon = get_obj_world( ch, target_name ); if( beacon == NULL || beacon->item_type != ITEM_BEACON ) { send_to_char( "Couldn't find target. Sorry.\n\r", ch ); return FALSE; } if( beacon->in_room == NULL ) { send_to_char( "It seems that someone is carrying it.\n\r", ch ); return FALSE; } if( str_cmp( beacon->owner, ch->name ) ) { send_to_char( "That's not one of YOUR beacons!\n\r", ch ); return FALSE; } act( "$n creates a magic window with a wave of $s hand.", ch, NULL, NULL, TO_ROOM ); send_to_char( "You create a magic window with a wave of your hand.\n\r", ch ); ob = create_object( get_obj_index( OBJ_VNUM_WINDOW ), level ); obj_to_room( ob, ch->in_room ); ob->timer = 1 + ( level / 30 ); ob->value[0] = beacon->in_room->vnum; ob->value[1] = 1; send_to_room( "The beacon suddenly vanishes!\n\r", beacon->in_room ); extract_obj( beacon ); return TRUE; } bool spell_portal( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Create a magic portal to another room */ OBJ_DATA *beacon; OBJ_DATA *ob; if( deathmatch ) { send_to_char( "Not during a @@eDeath Match@@N!!!\n\r", ch ); return FALSE; } if( target_name[0] == '\0' ) { send_to_char( "Form a portal to what?\n\r", ch ); return FALSE; } beacon = get_obj_world( ch, target_name ); if( beacon == NULL || beacon->item_type != ITEM_BEACON ) { send_to_char( "Couldn't find target. Sorry.\n\r", ch ); return FALSE; } if( beacon->in_room == NULL ) { send_to_char( "It seems that someone is carrying it.\n\r", ch ); return FALSE; } if( str_cmp( beacon->owner, ch->name ) ) { send_to_char( "That's not one of YOUR beacons!\n\r", ch ); return FALSE; } ob = create_object( get_obj_index( OBJ_VNUM_PORTAL ), level ); obj_to_room( ob, ch->in_room ); ob->timer = 1 + ( level / 30 ); ob->value[0] = ( beacon->carried_by == NULL ? beacon->in_room->vnum : beacon->carried_by->in_room->vnum ); ob->value[1] = 1; ob->value[2] = 1; act( "$n creates $p with a wave of $s hand.", ch, ob, NULL, TO_ROOM ); act( "You create $p with a wave of your hand.", ch, ob, NULL, TO_CHAR ); ob = create_object( get_obj_index( OBJ_VNUM_PORTAL ), level ); obj_to_room( ob, beacon->in_room ); ob->timer = 1 + ( level / 30 ); ob->value[0] = ch->in_room->vnum; ob->value[1] = 1; ob->value[2] = 1; send_to_room( "The beacon suddenly vanishes!\n\r", beacon->in_room ); send_to_room( "A glowing portal suddenly forms before you!\n\r", ob->in_room ); extract_obj( beacon ); return TRUE; } bool spell_beacon( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj ) { /* * Create a beacon, ready for a portal to 'goto'. * * I owe someone thanks for this, but forgot the name... D'oh. * * How this works: (+ for portals, etc ) * * a) Caster makes beacon: ownership set, obj->name = target_name * * b) Someone goes off with beacon, drops it * * c) Owner can then cast portal spell to it, beacon extracted * * -S- */ char buf[MAX_STRING_LENGTH]; char arg[MAX_STRING_LENGTH]; OBJ_DATA *ob; one_argument( target_name, arg ); ob = get_obj_world( ch, arg ); if( ob != NULL ) { send_to_char( "There is already an object with that keyword.\n\r", ch ); return FALSE; } ob = create_object( get_obj_index( OBJ_VNUM_BEACON ), level ); xprintf( buf, "%s", arg ); free_string( ob->name ); ob->name = str_dup( arg ); xprintf( buf, "%s", ch->name ); free_string( ob->owner ); ob->owner = str_dup( buf ); ob->timer = 20 + (level / 3); obj_to_room( ob, ch->in_room ); act( "$n magically produces $p!", ch, ob, NULL, TO_ROOM ); act( "You magically produce $p!", ch, ob, NULL, TO_CHAR ); return TRUE; }