/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * _/ _/_/_/ _/ _/ _/ ACK! MUD is modified * * _/_/ _/ _/ _/ _/ Merc2.0/2.1/2.2 code * * _/ _/ _/ _/_/ _/ (c)Stephen Dooley 1994 * * _/_/_/_/ _/ _/ _/ "This mud has not been * * _/ _/ _/_/_/ _/ _/ _/ tested on animals." * * * * * * 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- */ #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" 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; if ( obj==NULL ) { act( "A bolt of lightning flies from $n's finger!", ch, NULL, NULL, TO_ROOM ); send_to_char( "A bolt of lightning flies from your finger!", ch ); } else { act( "A bolt of lightning flies from $p!", ch, obj, NULL, TO_ROOM ); act( "A bolt of lightning flies from $p!", ch, obj, NULL, TO_CHAR ); } act( "$n is struck by the lightning bolt!!", victim, NULL, NULL, TO_ROOM ); send_to_char( "You are struck by the lightning bolt!!", victim ); damage( ch, victim, dam, -1 ); 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; sprintf( 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; sprintf( 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++ ) { if ( obj == NULL ) { act( "$n fires a magical dart which hits $M!", ch, NULL, victim, TO_NOTVICT ); act( "$N fires a magical dart, which hits you!", victim, NULL, ch, TO_CHAR ); act( "You fire a magical dart, which hits $N!", ch, NULL, victim, TO_CHAR ); } else { act( "A magical dart flies from $p, hitting $n!", victim, obj, NULL, TO_ROOM ); act( "A magical dart flies from $p, hitting you!", victim, obj, NULL, TO_CHAR ); } } damage( ch, victim, dam*cnt, -1 ); 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; 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; if ( obj==NULL ) { act( "$n discharges a powerful electrical shock into $N!", ch, NULL, victim, TO_NOTVICT ); act( "$n discharges a powerful electrical shock into you!", ch, NULL, victim, TO_VICT ); act( "You discharge a powerful electrical shock into $N!", ch, NULL, victim, TO_CHAR ); } else { act( "$n receives a powerful electrical shock from $p!", victim, obj, NULL, TO_ROOM ); act( "You receive a powerful electrical shock from $p!", victim, obj, NULL, TO_ROOM ); } damage( ch, victim, dam, -1 ); 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; 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 ); sprintf( 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 ); sprintf( buf1, "%s says '%s'.\n\r", speaker, target_name ); sprintf( 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_warcry( int sn, int level, CHAR_DATA *ch, void *vo, OBJ_DATA *obj ) /* --Stephen * FIXME: make this a warrior skill, check for bless. */ { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( victim->position == POS_FIGHTING || is_affected( victim, sn ) ) return FALSE; af.type = sn; af.duration = 4+level; af.location = APPLY_HITROLL; af.modifier = level / 16; af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = 0 - level / 16; affect_to_char( victim, &af ); send_to_char( "You feel righteous.\n\r", victim ); if ( ch != victim ) send_to_char( "Ok.\n\r", ch ); 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: act( "$p fumes and dissolves!", victim, obj_lose, NULL, TO_CHAR ); 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; damage( ch, victim, dam, sn ); 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 ); 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; damage( ch, victim, dam, sn ); 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 ); 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; damage( ch, victim, dam, sn ); 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; damage( ch, vch, dam, sn ); } } 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; damage( ch, victim, dam, sn ); 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; act( "The Dark Powers of the HellSpawn strike $n!!", victim, NULL, NULL, TO_ROOM ); send_to_char( "The Dark Powers of the HellSpawn strike you!!\n\r", victim ); damage( ch, victim, dam, -1 ); 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; char *plane; char *engulf; char msg[255]; char msg2[255]; char msg3[255]; char msg4[255]; if ( level<= 8 ) { lvl = 4; plane="Fire"; engulf="Flames"; } else if ( level<= 17 ) { lvl = 13; plane="Sun"; engulf="a Heat Ray"; } else if ( level<= 26 ) { lvl = 22; plane="Magma"; engulf="Lava"; } else if ( level<= 35 ) { lvl = 31; plane="Radiance"; engulf="Light"; } else if ( level<= 44 ) { lvl = 40; plane="Lightning"; engulf="Lightning"; } else if ( level<= 53 ) { lvl = 49; plane="Salt"; engulf="Dehydration"; } else if ( level<= 62 ) { lvl = 58; plane="Ash"; engulf="Cold"; } else if ( level<= 71 ) { lvl = 67; plane="Positive"; engulf="Energy"; } else { lvl = 80; plane="Negative"; engulf="Energy"; } dam = dice( 6, lvl / 2 ); if ( saves_spell( level, victim ) ) dam /= 2; if ( obj == NULL ) { sprintf( msg, "You summon %s from the %s plane!!\n\r", engulf, plane ); sprintf( msg2, "$n summons %s from the %s plane!!", engulf, plane ); send_to_char( msg, ch ); act( msg2, ch, NULL, NULL, TO_ROOM ); } else { sprintf( msg, "$p calls %s from the %s plane!", engulf, plane ); act( msg, ch, obj, NULL, TO_ROOM ); act( msg, ch, obj, NULL, TO_CHAR ); } sprintf( msg3, "You are struck by %s!!!!! Ouch!\n\r", engulf ); sprintf( msg4, "$N is struck down by %s!", engulf ); send_to_char( msg3, victim ); act( msg4, ch, NULL, victim, TO_NOTVICT ); damage( ch, victim, dam, -1 ); 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; 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( 0, 2*level ); dam = number_range(4, 8) * ( level / 8 ); if ( ch->move == 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 ); act( "$n's static discharge makes $N shake and shudder!", ch, NULL, victim, TO_NOTVICT ); act( "Your static discharge makes $N shake and shudder!", ch, NULL, victim, TO_CHAR ); act( "$N's static discharge makes you shake and shudder!", victim, NULL, ch, TO_CHAR ); damage( ch, victim, dam, -1 ); 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 ); damage( ch, victim, dam, -1 ); 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 ); damage( ch, vch, (level/2) + dice(6, 10), -1 ); } 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( 2, level ); 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 ); damage( ch, vch, dam, -1 ); /* -1 means no dammage message */ 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 { /* oh dear */ 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 ); damage( ch, ch, dam, sn ); } 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, 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 ); damage( ch, victim, dam, -1 ); /* -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 ); damage( ch, victim, (level/2), -1); /* -1 = no dam message */ spell_blindness( skill_lookup( "blindness"), level, ch, vo, obj ); 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; if ( obj == NULL ) { act( "$n attacks $N with a Mind Bolt!", ch, NULL, victim, TO_NOTVICT ); act( "You attack $N with a Mind Bolt!", ch, NULL, victim, TO_CHAR ); act( "$n attacks you with a Mind Bolt!", ch, NULL, victim, TO_VICT ); } else { act( "$p strikes $n with a Mind Bolt!", victim, obj, NULL, TO_ROOM ); act( "$p strikes you with a Mind Bolt!", victim, obj, NULL, TO_CHAR ); } cnt = 1 + ( level >= 20 ) + ( level >= 35 ) + ( level >= 50 ) + ( ch->level >= 65 ); for ( foo = 0; foo < cnt; foo++) { dam = ( cnt * ( level / 3 ) ); if ( saves_spell( level, victim ) ) dam /= 2; act( "$n shakes and shudders!", victim, NULL, NULL, TO_ROOM ); act( "You shake and shudder!", victim, NULL, ch, TO_CHAR ); } 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) ) ) { act( "$n rolls on the floor, twitching in agony!", vch, NULL, NULL, TO_ROOM ); act( "You roll on the floor, twitching in agony!", vch, NULL, NULL, TO_CHAR ); damage( ch, vch, (level) + dice(6, 10), -1 ); } 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 = 1; 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 = 1; affect_to_char( victim, &af ); af.location = APPLY_AC; af.modifier = -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; 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; sprintf( 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; sprintf( 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_WIELD, TRUE ) ) { blade = create_object( get_obj_index( OBJ_VNUM_FIREBLADE ), level ); obj_to_char(blade,ch); equip_char( ch, blade, WEAR_WIELD ); 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 + ( 5 * ( level>20) + (level>=40) + (level>=60) + (level>-80) ); if ( saves_spell( level, victim ) ) dam /= 2; if ( obj == NULL ) { act( "$n mind flails $N!", ch, NULL, victim, TO_NOTVICT ); act( "$N mind flails you!", victim, NULL, ch, TO_CHAR ); act( "You mind flail $N!", ch, NULL, victim, TO_CHAR ); } else { act( "$p mind flails $n!", victim, obj, NULL, TO_ROOM ); act( "$p mind flails you!", victim, obj, NULL, TO_ROOM ); } damage( ch, victim, dam, -1 ); 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; sprintf( 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: sprintf( 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: sprintf( 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: sprintf( buf, " Average damage is %d.\n\r", ( ob->value[1] + ob->value[2] ) / 2 ); send_to_char( buf, ch ); break; case ITEM_ARMOR: sprintf( 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 ) { sprintf( 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 + ( 6 * ( level>20) + (level>=40) + (level>=60) + (level>-80) ); if ( saves_spell( level, victim ) ) dam /= 2; act( "$n psychic thrusts $N!", ch, NULL, victim, TO_NOTVICT ); act( "$N psychic thrusts you!", victim, NULL, ch, TO_CHAR ); act( "You psychic thrust $N!", ch, NULL, victim, TO_CHAR ); damage( ch, victim, dam, -1 ); 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 = 20 + ( 7 * ( level>20) + (level>=40) + (level>=60) + (level>-80) ); if ( saves_spell( level, victim ) ) dam /= 2; act( "$n psychic crushes $N!", ch, NULL, victim, TO_NOTVICT ); act( "$N psychic crushes you!", victim, NULL, ch, TO_CHAR ); act( "You psychic crush $N!", ch, NULL, victim, TO_CHAR ); damage( ch, victim, dam, -1 ); 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 + ( 13 * ( level>20) + (level>=40) + (level>=60) + (level>-80) ); if ( saves_spell( level, victim ) ) dam /= 2; act( "$n ego whips $N!", ch, NULL, victim, TO_NOTVICT ); act( "$N ego whips you!", victim, NULL, ch, TO_CHAR ); act( "You ego whip $N!", ch, NULL, victim, TO_CHAR ); damage( ch, victim, dam, -1 ); 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 armoured, 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; af.bitvector = 0; affect_to_char( victim, &af ); act( "$n is surrounded by $N's mystic armour.", victim, NULL, ch, TO_ROOM ); act( "$N is surrounded by your mystic armour.", ch, NULL, victim, TO_CHAR ); act( "You are surrounded by $N's mystic armour.", 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 = -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 ); sprintf( buf, "%s", arg ); free_string( ob->name ); ob->name = str_dup( arg ); sprintf( buf, "%s", ch->name ); free_string( ob->owner ); ob->owner = str_dup( buf ); ob->timer = number_range( 30, 45 ); 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; }