/**************************************************************************/ // magic.cpp - spells etc /*************************************************************************** * The Dawn of Time v1.69r (c)1997-2004 Michael Garratt * * >> A number of people have contributed to the Dawn codebase, with the * * majority of code written by Michael Garratt - www.dawnoftime.org * * >> To use this source code, you must fully comply with all the licenses * * in licenses.txt... In particular, you may not remove this copyright * * notice. * *************************************************************************** * >> Original Diku Mud copyright (c)1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, & Katja Nyboe. * * >> Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * >> ROM 2.4 is copyright 1993-1995 Russ Taylor and has been brought to * * you by the ROM consortium: Russ Taylor(rtaylor@pacinfo.com), * * Gabrielle Taylor(gtaylor@pacinfo.com) & Brian Moore(rom@rom.efn.org) * * >> Oblivion 1.2 is copyright 1996 Wes Wagner * **************************************************************************/ #include "include.h" // dawn standard includes #include "magic.h" #include "msp.h" #include "ictime.h" // command procedures needed DECLARE_DO_FUN(do_look ); DECLARE_DO_FUN(do_far_scan); DECLARE_DO_FUN(do_bug); char *format_obj_to_char (OBJ_DATA *, char_data *, bool Short);/*act_info.c*/ bool check_skin( char_data *ch, char_data *victim); bool check_strength( int level, char_data *ch, char_data *victim, bool &half ); char *get_weapontype(OBJ_DATA *obj); bool check_social(char_data *ch,char * command, char * argument, bool global); // Local functions void say_spell args(( char_data *ch, int sn, CLASS_CAST_TYPE type ) ); void check_components( char_data *ch, int sn ); // imported functions bool remove_obj args( ( char_data *ch, int iWear, bool fReplace ) ); /**************************************************************************/ // Lookup a skill by name - exact match int skill_exact_lookup( const char *name ) { int sn; for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( IS_NULLSTR(skill_table[sn].name)) break; if ( !str_cmp( name, skill_table[sn].name ) ) return sn; } return -1; } /**************************************************************************/ // Lookup a skill by name. int skill_lookup( const char *name ) { int sn; if(!str_cmp(name, "second")){ name="dual wield"; } sn=skill_exact_lookup(name); if(sn>-1){ return sn; } for ( sn = 0; sn < MAX_SKILL; sn++ ) { if ( IS_NULLSTR(skill_table[sn].name)) break; if ( LOWER(name[0]) == LOWER(skill_table[sn].name[0]) && !str_prefix( name, skill_table[sn].name ) ) return sn; } return -1; } /**************************************************************************/ int find_spell( char_data *ch, const char *name, bool spellonly) { // finds a spell the character can cast if possible int sn, found = -1; int first=0; int last=MAX_SKILL; if(IS_NPC(ch)){ return skill_lookup(name); } if(spellonly){ first=FIRST_SPELL; last=LAST_SPELL+1; } // exact match first for ( sn = first; sn < last; sn++ ){ if (skill_table[sn].name == NULL){ break; } if (!str_cmp(name,skill_table[sn].name)){ if ( found == -1){ found = sn; } if (get_skill(ch,sn) > 0){ return sn; } } } // substring match for ( sn = first; sn < last; sn++ ){ if (skill_table[sn].name == NULL){ break; } if (LOWER(name[0]) == LOWER(skill_table[sn].name[0]) && !str_prefix(name,skill_table[sn].name)){ if ( found == -1){ found = sn; } if (get_skill(ch,sn) > 0){ return sn; } } } return found; } /**************************************************************************/ // Utter mystical words for an sn. void say_spell( char_data *ch, int sn, CLASS_CAST_TYPE type ) { char buf [MSL]; char buf2 [MSL]; char_data *rch; char *pName; int iSyl; int length; struct syl_type { char * old; char * nw; }; static const struct syl_type syl_table[] = { { " ", " " }, { "ar", "abra" }, { "au", "kada" }, { "bless", "fido" }, { "blind", "nose" }, { "bur", "mosa" }, { "cu", "judi" }, { "de", "oculo" }, { "en", "unso" }, { "light", "dies" }, { "lo", "hi" }, { "mor", "zak" }, { "move", "sido" }, { "ness", "lacri" }, { "ning", "illa" }, { "per", "duda" }, { "ra", "gru" }, { "fresh", "ima" }, { "re", "candus" }, { "son", "sabru" }, { "tect", "infra" }, { "tri", "cula" }, { "ven", "nofo" }, { "a", "a" }, { "b", "b" }, { "c", "q" }, { "d", "e" }, { "e", "z" }, { "f", "y" }, { "g", "o" }, { "h", "p" }, { "i", "u" }, { "j", "y" }, { "k", "t" }, { "l", "r" }, { "m", "w" }, { "n", "i" }, { "o", "a" }, { "p", "s" }, { "q", "d" }, { "r", "f" }, { "s", "g" }, { "t", "h" }, { "u", "j" }, { "v", "z" }, { "w", "x" }, { "x", "n" }, { "y", "l" }, { "z", "k" }, { "", "" } }; buf[0] = '\0'; for ( pName = skill_table[sn].name; *pName != '\0'; pName += length ) { for ( iSyl = 0; (length = str_len(syl_table[iSyl].old)) != 0; iSyl++ ) { if ( !str_prefix( syl_table[iSyl].old, pName )) { strcat( buf, syl_table[iSyl].nw ); break; } } if ( length == 0 ) length = 1; } switch (type){ case CCT_MAXCAST: case CCT_NONE: sprintf( buf2, "$n utters the words - THERE IS A BUG, CCT_NONE IN sayspell(), '%s'.", buf ); sprintf( buf, "$n utters the words - THERE IS A BUG, CCT_NONE IN sayspell(), '%s'.", skill_table[sn].name ); break; case CCT_MAGE: sprintf( buf2, "$n utters the words, '%s'.", buf ); sprintf( buf, "$n utters the words, '%s'.", skill_table[sn].name ); break; case CCT_CLERIC: sprintf( buf2, "$n prays the words, '%s'.", buf ); sprintf( buf, "$n prays the words, '%s'.", skill_table[sn].name ); break; case CCT_DRUID: sprintf( buf2, "$n summons the elements of nature using the words, '%s'.", buf ); sprintf( buf, "$n summons the elements of nature using the words, '%s'.", skill_table[sn].name ); break; // Bardic songs won't be encrypted by the syl_table case CCT_BARD: sprintf( buf2, "$n sings the song, '%s'.", skill_table[sn].name ); sprintf( buf, "$n sings the song, '%s'.", skill_table[sn].name ); break; } // MSP Spell Sound if ( !IS_NULLSTR( skill_table[sn].msp_sound )){ msp_to_room(MSPT_SPELL, skill_table[sn].msp_sound, 0, ch, false, true); } for ( rch = ch->in_room->people; rch; rch = rch->next_in_room ) { if ( rch != ch ){ if ( !is_affected(rch, gsn_deafness)) { // imms always get the name of the spell if(IS_IMMORTAL(rch)){ act( buf, ch, NULL, rch, TO_VICT ); continue; } if(IS_NPC(ch)) { if(IS_SET(ch->act,ACT_CLERIC)){ act( class_lookup("cleric")==rch->clss ? buf : buf2, ch, NULL, rch, TO_VICT ); }else if(IS_SET(ch->act,ACT_MAGE)){ act( class_lookup("mage")==rch->clss ? buf : buf2, ch, NULL, rch, TO_VICT ); }else{ act( buf2, ch, NULL, rch, TO_VICT ); } }else{ act( ch->clss==rch->clss || IS_IMMORTAL(rch)? buf : buf2, ch, NULL, rch, TO_VICT ); } } else { if ( !IS_AFFECTED( rch, AFF_BLIND ) || !is_affected( rch, gsn_blindness )){ act( "You see $N's lips moving.", rch, NULL, ch, TO_CHAR ); } } } } return; } /**************************************************************************/ // Compute a saving throw - Negative apply's make saving throw better. // a higher save value, the better for the victim bool saves_spell( int level, char_data *victim, int dam_type ) { int save; save = 50 + ( victim->level - level) * 5 - victim->saving_throw * 2; if (IS_AFFECTED(victim,AFF_BERSERK)) save += victim->level/2; if ( IS_NPC(victim) && IS_SET(victim->act, ACT_IS_UNSEEN)) { return true; } switch(check_immune(victim,dam_type)) { case IS_IMMUNE: return true; case IS_RESISTANT: save *= 2; break; case IS_VULNERABLE: save /= 2; break; } if (!IS_NPC(victim) && class_table[victim->clss].fMana) save = 9 * save / 10; save = URANGE( 5, save, 95 ); return number_percent( ) < save; } /**************************************************************************/ // RT save for dispels bool saves_dispel( int dis_level, int spell_level, int duration) { int save; if (duration == -1) spell_level += 15; // very hard to dispel permanent effects save = 50 + (spell_level - dis_level) * 5; save = URANGE( 5, save, 95 ); return number_percent( ) < save; } /**************************************************************************/ // co-routine for dispel magic and cancellation // return true if successful bool check_dispel( int dis_level, char_data *victim, int sn) { AFFECT_DATA *af, *af_next; int type; bool result=false; SPELL_FUN * spell_fun=NULL; if (count_affected_by_base_spell(victim, sn)>0) { // get the parent spell function if appropriate if(sn>=FIRST_SPELL && sn<=LAST_SPELL){ spell_fun= skill_table[sn].spell_fun; } if(spell_fun==spell_null){ spell_fun=NULL; } for ( af = victim->affected; af; af = af_next ) { af_next=af->next; type=af->type; if( ( spell_fun && type>=FIRST_SPELL && type<=LAST_SPELL && skill_table[type].spell_fun == spell_fun ) || (type == sn) ) { if (!saves_dispel(dis_level,af->level,af->duration)) { affect_remove( victim, af); if ( !IS_NULLSTR(skill_table[type].msg_off) ) { victim->printlnf( "%s", skill_table[type].msg_off ); } result=true; }else{ // weaken the spell slightly af->level--; } } } } return result; } /**************************************************************************/ bool check_component( char_data *ch, int sn ) { OBJ_DATA *obj; if ( IS_NPC( ch )) return true; // mobs don't need components (yet) for ( obj = ch->carrying; obj; obj = obj->next_content ) { if ( obj->item_type == ITEM_COMPONENT && obj->value[1] == sn ) { if ( --obj->value[0] == 0 ) { act ( "$p has been consumed by your magic.", ch, obj, NULL, TO_CHAR ); extract_obj( obj ); } else if ( obj->value[0] < 0 ) { obj->value[0] = -1; } return true; } } if ( !obj ) { ch->println( "You lack the proper ingredient for this spell." ); return false; } return true; } /**************************************************************************/ // The kludgy global is for spells who want more stuff from command line. char *target_name; /**************************************************************************/ void do_newcast( char_data *ch, char *argument, int cast_level, CLASS_CAST_TYPE type ) { char arg1[MIL]; char arg2[MIL]; char_data *victim; OBJ_DATA *obj; EXIT_DATA *pexit; int *pdoor; void *vo; int mana; int sn; int target; int roll; int spell_level; int mana_result; int door; AFFECT_DATA *paf; // For spell grouping // Switched NPC's can cast spells, but others can't. if (IS_UNSWITCHED_MOB(ch)) return; if(!IS_ADMIN( ch ) && IS_OOC( ch )){ ch->println( "You can not use magic in an ooc area." ); return; } if ( IS_SET( ch->in_room->room_flags, ROOM_ANTIMAGIC )) { ch->println( "Your cannot conjure up a spark of magic here." ); return; } // Check to see if ch is charmed and being ordered to cast if ( IS_AFFECTED(ch,AFF_CHARM) && !IS_SET( ch->dyn, DYN_IS_BEING_ORDERED )) { ch->println( "You must wait for your master to tell you to cast a spell." ); return; } target_name = one_argument( argument, arg1 ); one_argument( target_name, arg2 ); if ( IS_NULLSTR(arg1)) { switch (type){ case CCT_MAXCAST: case CCT_NONE: ch->println( "Cast which what where? - THERE IS A BUG, CCT_NONE IN do_newcast()"); ch->println( "please report to the admin!"); break; case CCT_MAGE: ch->println( "Cast which what where?"); break; case CCT_CLERIC: ch->println( "Commune which what where?"); break; case CCT_DRUID: ch->println( "Summon which what where?"); break; case CCT_BARD: ch->println( "Sing which song?" ); break; } return; } REMOVE_BIT( ch->dyn, DYN_SUCCESS_CAST ); // Starts out false // check that it is a spell, and skill is above 0% if ( ( sn = find_spell( ch,arg1, true ) ) < 0 || get_skill(ch,sn) ==0 || !IS_SPELL(sn)) { ch->printlnf( "You don't know any spells of the name '%s'.", arg1 ); return; } // do a level check if they aren't an imm and the level // on the spell is an imm level // a skill of 101 in the skill is a budget hack to make // an acception to this if (!IS_NPC(ch)) { if (( (skill_table[sn].skill_level[ch->clss] >=LEVEL_IMMORTAL || (skill_table[sn].skill_level[ch->clss]==0)) && !IS_IMMORTAL(ch)) && ch->pcdata->learned[sn] !=101) { ch->wrapln("This spell is not castable by your class... " "even though for some reason you have it... It may have been " "removed from your class for game balances purposes... talk to an " "admin to get a refund for on the pracs you have spent on it."); return; } } if ( ch->position < skill_table[sn].minimum_position ){ ch->println( "You can't concentrate enough." ); return; } if ( IS_SET(skill_table[sn].sect_restrict, 1<<ch->in_room->sector_type) ) { ch->printlnf( "You can't seem to cast %s %s.", skill_table[sn].name, sector_desc[ch->in_room->sector_type].name); return; } mana = skill_table[sn].min_mana; if(get_skill(ch,gsn_mana_focusing)) { if( (roll = number_range(1,100)) < get_skill(ch,gsn_mana_focusing)) { mana-=mana*(roll/2)/100; } } /* * Locate targets. */ victim = NULL; obj = NULL; vo = NULL; target = TARGET_NONE; switch ( skill_table[sn].target ) { default: bugf( "Do_cast: bad target for sn %d.", sn ); return; case TAR_IGNORE: // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ) { if ( !check_component( ch, sn )) return; } break; case TAR_MOB_OFFENSIVE: case TAR_CHAR_OFFENSIVE: if ( arg2[0] == '\0' ) { if ( ( victim = ch->fighting ) == NULL ) { ch->println( "Cast the spell on whom?" ); return; } } else { if ( ( victim = get_char_room( ch, target_name ) ) == NULL ) { ch->printlnf( "Can't see any '%s' here.", target_name ); if (ch->desc && ch->desc->repeat>5){ WAIT_STATE( ch, 3 * PULSE_VIOLENCE ); } return; } } // target restriction checks if((IS_NPC(victim) && IS_SET(skill_table[sn].flags,SKFLAGS_NO_NPCTARGET)) ||(!IS_NPC(victim) && IS_SET(skill_table[sn].flags,SKFLAGS_NO_PCTARGET))) { ch->println( "Not on that target." ); return; } // is safe check if ( !IS_NPC(ch) ) { if (is_safe(ch,victim) && victim != ch) { ch->println( "Not on that target." ); return; } } if ( !can_initiate_combat( ch, victim, CIT_GENERAL | CIT_CASTING_SPELL )) return; if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim ) { ch->println( "You can't do that on your own follower." ); return; } vo = (void *) victim; target = TARGET_CHAR; // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ) { if ( !check_component( ch, sn )) return; } break; case TAR_CHAR_DEFENSIVE: if ( arg2[0] == '\0' ) { victim = ch; } else { if ( ( victim = get_char_room( ch, target_name ) ) == NULL ) { ch->printlnf( "You can't see any '%s' here.", target_name ); return; } } // Start Grouping check for (paf = victim->affected; paf; paf=paf->next) for(int i=0; spell_group_flags[i].name; i++) if ( IS_SET(skill_table[sn].spellgroup, spell_group_flags[i].bit) && IS_SET(skill_table[paf->type].spellgroup, spell_group_flags[i].bit) ) { if (victim == ch) ch->println( "But you're already affected by something similar!"); else ch->printlnf( "But %s is already affected by something similar!", victim->short_descr); return; } // End Grouping check vo = (void *) victim; target = TARGET_CHAR; // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ) { if ( !check_component( ch, sn )) return; } break; case TAR_CHAR_SELF: if ( !IS_NULLSTR(arg2) && !str_cmp(target_name, "self") && !is_name( target_name, ch->name ) ) { ch->println( "You cannot cast this spell on another." ); return; } // Start Grouping check for (paf = ch->affected; paf; paf=paf->next) for(int i=0; spell_group_flags[i].name; i++) if ( IS_SET(skill_table[sn].spellgroup, spell_group_flags[i].bit) && IS_SET(skill_table[paf->type].spellgroup, spell_group_flags[i].bit) ) { ch->println( "But you're already affected by something similar!" ); return; } // End Grouping check vo = (void *) ch; target = TARGET_CHAR; // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ) { if ( !check_component( ch, sn )) return; } break; case TAR_OBJ_INV: if ( arg2[0] == '\0' ) { ch->println( "What should the spell be cast upon?" ); return; } if ( ( obj = get_obj_carry( ch, target_name ) ) == NULL ) { ch->printlnf( "You are not carrying any '%s'.", target_name ); return; } vo = (void *) obj; target = TARGET_OBJ; // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ) { if ( !check_component( ch, sn )) return; } break; case TAR_DIRECTION: if (arg2[0] == '\0') { ch->println( "Cast the spell in what direction?" ); return; } door = dir_lookup( arg2); if ( door == -1 ) { ch->printlnf( "'%s' is an invalid direction.", arg2 ); return; } if ( (pexit = ch->in_room->exit[door]) == NULL || pexit->u1.to_room == NULL ) { ch->println( "There is no exit in that direction." ); return; } pdoor = &door; vo = (void *) pdoor; target = TARGET_CHAR; // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ) { if ( !check_component( ch, sn )) return; } break; case TAR_OBJ_MOB_OFF: case TAR_OBJ_CHAR_OFF: if (arg2[0] == '\0') { if ((victim = ch->fighting) == NULL) { ch->println( "Cast the spell on whom or what?" ); return; } target = TARGET_CHAR; } else if ((victim = get_char_room(ch,target_name)) != NULL) { target = TARGET_CHAR; } if (target == TARGET_CHAR) // check the sanity of the attack { // target restriction checks if((IS_NPC(victim) && IS_SET(skill_table[sn].flags,SKFLAGS_NO_NPCTARGET)) ||(!IS_NPC(victim) && IS_SET(skill_table[sn].flags,SKFLAGS_NO_PCTARGET))) { ch->println( "Not on that target." ); return; } // is safe check if(is_safe_spell(ch,victim,false) && victim != ch) { ch->println( "Not on that target." ); return; } if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim ) { ch->println( "You can't do that on your own follower." ); return; } vo = (void *) victim; } else if ((obj = get_obj_here(ch,target_name)) != NULL) { vo = (void *) obj; target = TARGET_OBJ; } else { ch->printlnf( "You don't see any '%s' here.", target_name ); return; } // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ) { if ( !check_component( ch, sn )) return; } break; case TAR_OBJ_CHAR_DEF: if (arg2[0] == '\0') { // Start Grouping check for (paf = ch->affected; paf; paf=paf->next) for(int i=0; spell_group_flags[i].name; i++) if ( IS_SET(skill_table[sn].spellgroup, spell_group_flags[i].bit) && IS_SET(skill_table[paf->type].spellgroup, spell_group_flags[i].bit) ) { ch->println( "But you're already affected by something similar!" ); return; } // End Grouping check vo = (void *) ch; target = TARGET_CHAR; } else if ((victim = get_char_room(ch,target_name)) != NULL) { // Start Grouping check for (paf = victim->affected; paf; paf=paf->next) for(int i=0; spell_group_flags[i].name; i++) if ( IS_SET(skill_table[sn].spellgroup, spell_group_flags[i].bit) && IS_SET(skill_table[paf->type].spellgroup, spell_group_flags[i].bit) ) { ch->printlnf( "But %s is already affected by something similar!", victim->short_descr); return; } //End Grouping check vo = (void *) victim; target = TARGET_CHAR; } else if ((obj = get_obj_carry(ch,target_name)) != NULL) { vo = (void *) obj; target = TARGET_OBJ; } else { ch->printlnf( "You don't see any '%s' here.", target_name ); return; } // Check to see if the spell is component based and if they've got it if ( skill_table[sn].component_based ){ if ( !check_component( ch, sn )){ return; } } break; }// end of spell type switch if ( !IS_NPC(ch) && ch->mana < mana ) { ch->println( "You don't have enough mana." ); return; } if ( str_cmp( skill_table[sn].name, "ventriloquate" ) ) say_spell( ch, sn, type ); WAIT_STATE( ch, skill_table[sn].beats ); // can't spam charming yourself to improve at it if (sn==gsn_charm_person && victim==ch) { if (number_percent( ) > get_skill(ch,sn) ) { ch->mana -= mana / 2; ch->println( "You lost your concentration." ); } else { ch->mana -= mana; ch->println( "You like yourself even better!" ); } return; } if(get_skill(ch,gsn_mana_focusing)) { if( (roll = number_range(1,100)) < get_skill(ch,gsn_mana_focusing)) { check_improve(ch,gsn_mana_focusing, true, 5); } else check_improve(ch,gsn_mana_focusing, false, 5); } if ( number_percent( ) > (get_skill(ch,sn) + ch->modifiers[STAT_SD] - 5)) { ch->mana -= mana / 2; ch->println( "You lost your concentration." ); check_improve(ch,sn,false,1); } else { spell_level=ch->level; // moon casting mods by Kalahn // mage if (HAS_CLASSFLAG(ch, CLASSFLAG_CASTING_AFFECTED_BY_MOON)) { spell_level += weather_info[ch->in_room->sector_type].mage_castmod; if (spell_level<1) spell_level=1; } // spellfilcher at half if (HAS_CLASSFLAG(ch, CLASSFLAG_CASTING_HALFAFFECTED_BY_MOON)) { spell_level += (weather_info[ch->in_room->sector_type].mage_castmod/2); if (spell_level<1) spell_level=1; } if(get_skill(ch,gsn_sorcery)) { if( (roll = number_range(1,100)) < get_skill(ch,gsn_sorcery)) { spell_level+=roll/5; check_improve(ch,gsn_sorcery, true, 5); } else check_improve(ch,gsn_sorcery, false, 5); } if ( IS_SET(skill_table[sn].sect_dampen, 1<<ch->in_room->sector_type) ) spell_level -= number_range(1,20); else if ( IS_SET(skill_table[sn].sect_enhance, 1<<ch->in_room->sector_type) ) spell_level += number_range(1,10); // cast_level override if casted from do_castatlevel if (cast_level) spell_level=cast_level; if (!skill_table[sn].spell_fun){ ch->printlnf( "'%s' is not a spell!", skill_table[sn].name); return; } // spell cast on barbarian turns into a spell_fear_magic instead. if( victim && HAS_CLASSFLAG(victim, CLASSFLAG_MAGIC_ANTIPATHY) && number_range(1,3)==1 && IS_SET(skill_table[sn].flags, SKFLAGS_MAGICAL_ANTIPATHY) && !victim->fighting) { ch->printlnf( "Your spell has set %s into a maddening frenzy!", victim->short_descr); sn = gsn_fear_magic; } SET_BIT( ch->dyn, DYN_SUCCESS_CAST ); if (IS_NPC(ch) || class_table[ch->clss].fMana) // clss has spells mana_result = (*skill_table[sn].spell_fun) ( sn, spell_level, ch, vo,target); else mana_result = (*skill_table[sn].spell_fun) (sn, spell_level, ch, vo,target); switch( mana_result ) { case NO_MANA: mana = 0; break; case HALF_MANA: if ( mana > 0 ) mana /= 2; break; case DOUBLE_MANA: if ( mana > 0 ) mana *= 2; break; case ALL_MANA: mana = ch->mana; default: break; } ch->mana -= mana; if (!IS_NPC(ch)) { // record when the spell was last used //ch->pcdata->last_used[sn]= current_time; } check_improve(ch,sn,true,1); } if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE || (skill_table[sn].target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR) || (skill_table[sn].target == TAR_OBJ_MOB_OFF && target == TARGET_CHAR && IS_NPC(victim)) || (skill_table[sn].target == TAR_MOB_OFFENSIVE && IS_NPC(victim))) && ch && ch->in_room && victim != ch && victim->master != ch) { char_data *vch; char_data *vch_next; for ( vch = ch->in_room->people; vch; vch = vch_next ) { vch_next = vch->next_in_room; if ( victim == vch && victim->fighting == NULL ) { multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } if (skill_table[sn].target == TAR_MOB_OFFENSIVE && !IS_NPC(victim) && ch!=victim) { ch->pksafe=0; if (ch->pknorecall<5) ch->pknorecall=5; } return; } /**************************************************************************/ void do_summon( char_data *ch, char *argument ) { if(!IS_NPC(ch) && (TRUE_CH(ch)->level<LEVEL_IMMORTAL) ){ if(class_table[ch->clss].class_cast_type==CCT_NONE){ ch->println( "What would you know about summoning nature?" ); return; } if(class_table[ch->clss].class_cast_type!=CCT_DRUID){ ch->println( "Try cast or commune." ); return; } } do_newcast( ch, argument, 0, CCT_DRUID); } /**************************************************************************/ void do_commune( char_data *ch, char *argument ) { if(!IS_NPC(ch) && (TRUE_CH(ch)->level<LEVEL_IMMORTAL) ){ if(class_table[ch->clss].class_cast_type==CCT_NONE){ ch->println( "What would you know about praying?" ); return; } if(class_table[ch->clss].class_cast_type!=CCT_CLERIC){ ch->println( "Try cast or summon." ); return; } } do_newcast( ch, argument, 0, CCT_CLERIC); } /**************************************************************************/ void do_sing( char_data *ch, char *argument ) { if(!IS_NPC(ch) && (TRUE_CH(ch)->level<LEVEL_IMMORTAL) ) { if ( class_table[ch->clss].class_cast_type != CCT_BARD ) { // default to the sing social check_social( ch, "sing", argument, false ); return; } } do_newcast( ch, argument, 0, CCT_BARD); } /**************************************************************************/ void do_cast( char_data *ch, char *argument ) { if(!IS_NPC(ch) && (TRUE_CH(ch)->level<LEVEL_IMMORTAL) ){ if(class_table[ch->clss].class_cast_type==CCT_NONE){ if(GAMESETTING5(GAMESET5_DEDICATED_PKILL_STYLE_MUD)){ do_newcast( ch, argument, 0, CCT_MAGE); }else{ ch->println( "What would you know about magic?" ); } return; } if(class_table[ch->clss].class_cast_type!=CCT_MAGE){ ch->println( "Try commune or summon." ); return; } } // mobs with the cleric bit dont cast spells, they 'pray' them if(IS_NPC(ch) && IS_SET(ch->act,ACT_CLERIC)){ do_newcast( ch, argument, 0, CCT_CLERIC); return; } do_newcast( ch, argument, 0, CCT_MAGE); } /**************************************************************************/ void do_cast_redirect( char_data *ch, char *argument ) { if(class_table[ch->clss].class_cast_type==CCT_CLERIC){ do_commune(ch,argument); return; } if(class_table[ch->clss].class_cast_type==CCT_DRUID){ do_summon(ch,argument); return; } do_cast(ch,argument); } /**************************************************************************/ void do_castatlevel( char_data *ch, char *argument) { char arg[MIL]; int max_level; if (!IS_UNSWITCHED_MOB(ch)) max_level=ch->level*3; else max_level=TRUE_CH(ch)->level; if (max_level >= MAX_LEVEL*3){ max_level = MAX_LEVEL*6; } if ( IS_SET( ch->in_room->room_flags, ROOM_ANTIMAGIC )) { ch->println( "You cannot conjure up a spark of magic here." ); return; } argument = one_argument( argument, arg ); if ( arg[0] == '\0' || argument[0] == '\0' ) { ch->println( "Castatlevel what?" ); return; } if (is_number(arg)) { int new_level = atoi(arg); if ((new_level<=max_level) && (new_level>0)) { ch->printlnf( "ATLEVELCAST %d BEGIN.", new_level); do_newcast( ch, argument, new_level, CCT_MAGE ); ch->printlnf( "ATLEVELCAST %d FINISHED.", new_level); return; } else // not high enough trust { ch->printlnf( "Level must be between 1 and %d.", max_level); return; } } ch->println( "Level must be a valid number." ); return; } /**************************************************************************/ // Cast spells at targets using a magical object. void obj_cast_spell( int sn, int level, char_data *ch, char_data *victim, OBJ_DATA *obj ) { void *vo; int target = TARGET_NONE; if ( sn <= 0 ) return; if ( sn >= MAX_SKILL || skill_table[sn].spell_fun == 0 ) { bugf( "Obj_cast_spell: bad sn %d.", sn ); return; } switch ( skill_table[sn].target ) { default: bugf( "Obj_cast_spell: bad target for sn %d.", sn ); return; case TAR_IGNORE: vo = NULL; break; case TAR_CHAR_OFFENSIVE: case TAR_MOB_OFFENSIVE: if ( victim == NULL ) victim = ch->fighting; if ( victim == NULL ) { ch->println( "You can't do that." ); return; } if (is_safe(ch,victim) && ch != victim) { ch->println( "Something isn't right..." ); return; } vo = (void *) victim; target = TARGET_CHAR; break; case TAR_CHAR_DEFENSIVE: case TAR_CHAR_SELF: if ( victim == NULL ){ victim = ch; } vo = (void *) victim; target = TARGET_CHAR; break; case TAR_OBJ_INV: if ( obj == NULL ) { ch->println( "You can't do that." ); return; } vo = (void *) obj; target = TARGET_OBJ; break; case TAR_OBJ_CHAR_OFF: if ( victim == NULL && obj == NULL) if (ch->fighting != NULL) victim = ch->fighting; else { ch->println( "You can't do that." ); return; } if (victim != NULL) { if (is_safe_spell(ch,victim,false) && ch != victim) { ch->println( "Something isn't right..." ); return; } vo = (void *) victim; target = TARGET_CHAR; } else { vo = (void *) obj; target = TARGET_OBJ; } break; case TAR_OBJ_CHAR_DEF: if (victim == NULL && obj == NULL) { vo = (void *) ch; target = TARGET_CHAR; } else if (victim != NULL) { vo = (void *) victim; target = TARGET_CHAR; } else { vo = (void *) obj; target = TARGET_OBJ; } break; } target_name = ""; (*skill_table[sn].spell_fun) ( sn, level, ch, vo,target); if ( (skill_table[sn].target == TAR_CHAR_OFFENSIVE || (skill_table[sn].target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) && victim != ch && victim->master != ch ) { char_data *vch; char_data *vch_next; for ( vch = ch->in_room->people; vch; vch = vch_next ) { vch_next = vch->next_in_room; if ( victim == vch && victim->fighting == NULL ) { multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } return; } /**************************************************************************/ // Spell functions. /**************************************************************************/ /**************************************************************************/ SPRESULT spell_acid_blast( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; int dam; dam = dice( level, 10 ); if ( saves_spell( level, victim, DAMTYPE(sn))) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_armor( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) ) { if (victim == ch) ch->println( "You are already armored." ); else act("$N is already armored.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.modifier = -20; af.location = APPLY_AC; af.bitvector = 0; affect_to_char( victim, &af ); victim->println( "You feel someone protecting you." ); if ( ch != victim ) act("$N is protected by your magic.",ch,NULL,victim,TO_CHAR); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_bless( int sn, int level, char_data *ch, void *vo, int target) { char_data *victim; OBJ_DATA *obj; AFFECT_DATA af; // deal with the object case first if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (IS_OBJ_STAT(obj,OBJEXTRA_BLESS)) { act("$p is already blessed.",ch,obj,NULL,TO_CHAR); return HALF_MANA; } if (IS_OBJ_STAT(obj,OBJEXTRA_EVIL)) { AFFECT_DATA *paf; paf = affect_find(obj->affected,gsn_curse); if (!saves_dispel(level,paf != NULL ? paf->level : obj->level,0)) { if (paf != NULL) affect_remove_obj(obj,paf); act("$p glows a pale blue.",ch,obj,NULL,TO_ALL); REMOVE_BIT(obj->extra_flags,OBJEXTRA_EVIL); return FULL_MANA; } else { act("The evil of $p is too powerful for you to overcome.", ch,obj,NULL,TO_CHAR); return FULL_MANA; } } af.where = WHERE_OBJEXTRA; af.type = sn; af.level = level; af.duration = 6 + level; af.location = APPLY_SAVES; af.modifier = -1; af.bitvector= OBJEXTRA_BLESS; affect_to_obj(obj,&af); act("$p glows with a holy aura.",ch,obj,NULL,TO_ALL); return FULL_MANA; } // character target victim = (char_data *) vo; if(is_affected( victim, gsn_curse )){ if( check_dispel( level, victim, gsn_curse )){ act( "Your magic unravels a spell on $N.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; }else{ ch->println("You failed."); return FULL_MANA; } } if(is_affected( victim, sn )){ if (victim == ch){ ch->println( "You are already blessed." ); }else{ act("$N already has divine favor.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 6+level; af.location = APPLY_HITROLL; af.modifier = level / 8; af.bitvector = 0; affect_to_char( victim, &af ); af.location = APPLY_SAVES; af.modifier = 0 - level / 8; affect_to_char( victim, &af ); victim->println( "You feel righteous." ); if ( ch != victim ) act("You grant $N the favor of your god.",ch,NULL,victim,TO_CHAR); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_blindness( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_BLIND)) { ch->printlnf( "%s already appears to be blinded.", PERS(victim, ch)); return HALF_MANA; } if (saves_spell(level,victim,DAMTYPE(sn))) { ch->printlnf( "%s seems unaffected.", PERS(victim, ch) ); return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.location = APPLY_HITROLL; af.modifier = -4; af.duration = 1+level; af.bitvector = AFF_BLIND; affect_to_char( victim, &af ); victim->println( "You are blinded!" ); act("$n appears to be blinded.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_burning_hands(int sn,int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; static const sh_int dam_each[] = { 0, 0, 0, 0, 0, 14, 17, 20, 23, 26, 29, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48 }; int dam; level = UMIN(level, (int)sizeof(dam_each)/(int)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, DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_call_lightning( int sn, int level,char_data *ch,void *,int ) { char_data *vch; char_data *vch_next; int dam; if ( !IS_OUTSIDE(ch) ) { ch->println( "You must be out of doors." ); return NO_MANA; } if ( ch->in_room->sector_type == SECT_CAVE ) { ch->println( "You cannot cast this spell here." ); return NO_MANA; } if ( weather_info[ch->in_room->sector_type].sky < SKY_RAINING ) { ch->println( "You need bad weather." ); return HALF_MANA; } dam = dice(level/2, 8); ch->println( "Lightning from the sky strikes your foes!" ); act( "$n calls upon the lightning to strike $s foes!", ch, NULL, NULL, TO_ROOM ); for ( vch = ch->in_room->people; vch; vch = vch_next ) { vch_next=vch->next_in_room; 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) ) ) damage_spell( ch, vch, saves_spell( level, vch, DAMTYPE( sn )) ? dam / 2 : dam, sn, DAMTYPE(sn), true); continue; } if ( vch->in_room->area == ch->in_room->area && IS_OUTSIDE(vch) && vch->in_room->sector_type != SECT_CAVE && IS_AWAKE(vch) ) vch->println( "Lightning flashes in the sky." ); } return FULL_MANA; } /**************************************************************************/ // RT calm spell stops all fighting in the room SPRESULT spell_calm( int sn, int level, char_data *ch, void *,int ) { char_data *vch; int mlevel = 0; int count = 0; int high_level = 0; int chance; AFFECT_DATA af; /* get sum of all mobile levels in the room */ for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (vch->position == POS_FIGHTING) { count++; if (IS_NPC(vch)) mlevel += vch->level; else mlevel += vch->level/2; high_level = UMAX(high_level,vch->level); } } /* compute chance of stopping combat */ chance = 4 * level - high_level + 2 * count; if ( IS_IMMORTAL( ch )) /* always works */ mlevel = 0; if ( number_range( 0, chance ) >= mlevel ) /* hard to stop large fights */ { for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room ) { if ( IS_NPC( vch ) && ( IS_SET( vch->imm_flags, IMM_MAGIC ) || IS_SET( vch->act, ACT_UNDEAD ))) return FULL_MANA; if ( IS_AFFECTED( vch, AFF_CALM ) || IS_AFFECTED( vch, AFF_BERSERK ) || is_affected( vch, gsn_frenzy )) return FULL_MANA; vch->println( "A wave of calm passes over you." ); if (vch->fighting || vch->position == POS_FIGHTING ) stop_fighting( vch, false ); af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level/4; af.location = APPLY_HITROLL; if (!IS_NPC(vch)) af.modifier = -5; else af.modifier = -2; af.bitvector = AFF_CALM; affect_to_char(vch,&af); af.location = APPLY_DAMROLL; affect_to_char(vch,&af); } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cancellation( int , int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; char_data *roomchar; bool found = false; level += 2; if ((!IS_NPC(ch) && IS_NPC(victim) && !(IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) ) || (IS_NPC(ch) && !IS_NPC(victim)) ) { ch->println( "You failed, try dispel magic." ); return HALF_MANA; } // unlike dispel magic, the victim gets NO save // begin running through the spells if ( IS_SET( ch->in_room->affected_by, ROOMAFF_UTTERDARK )) { ch->println( "The darkness around you disappears." ); act( "The darkness around you disappears.", ch, NULL, NULL, TO_ROOM ); REMOVE_BIT( ch->in_room->affected_by, ROOMAFF_UTTERDARK ); found = true; } if (check_dispel(level,victim, gsn_regeneration )) found = true; if (check_dispel(level,victim, gsn_resist_poison )) found = true; if (check_dispel(level,victim, gsn_poison_immunity )) found = true; if (check_dispel(level,victim, gsn_prismatic_spray )) found = true; if (check_dispel(level,victim, gsn_illusions_grandeur )) found = true; if (check_dispel(level,victim, gsn_protection_fire )) found = true; if (check_dispel(level,victim, gsn_protection_cold )) found = true; if (check_dispel(level,victim, gsn_protection_lightning )) found = true; if (check_dispel(level,victim, gsn_holy_aura )) found = true; if (check_dispel(level,victim, gsn_true_sight )) found = true; if (check_dispel(level,victim, gsn_barkskin )) found = true; if (check_dispel(level,victim, gsn_magic_resistance )) found = true; if (check_dispel(level,victim, gsn_fire_shield )) found = true; if (check_dispel(level,victim, gsn_chill_shield )) found = true; if (check_dispel(level,victim, gsn_animal_essence)) found = true; if (check_dispel(level,victim, gsn_armor )) found = true; if (check_dispel(level, victim, gsn_bless )) found = true; if (check_dispel(level,victim, gsn_blindness )) { found = true; act("$n is no longer blinded.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim, gsn_calm )) { found = true; act("$n no longer looks so peaceful...",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim, gsn_change_sex )) { found = true; act("$n looks more like $mself again.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim, gsn_charm_person)) { found = true; act("$n regains $s free will.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim, gsn_chill_touch )) { found = true; act("$n looks warmer.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim, gsn_curse )) found = true; if (check_dispel(level,victim, gsn_detect_evil )) found = true; if (check_dispel(level,victim, gsn_detect_good )) found = true; if (check_dispel(level,victim, gsn_detect_hidden )) found = true; if (check_dispel(level,victim, gsn_detect_invis )) found = true; if (check_dispel(level,victim, gsn_detect_magic )) found = true; if (check_dispel(level,victim, gsn_faerie_fire )) { act("$n's outline fades.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_fly )) { act("$n falls to the ground!",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_frenzy )) { act("$n no longer looks so wild.",victim,NULL,NULL,TO_ROOM);; found = true; } if (check_dispel(level,victim, gsn_giant_strength )) { act("$n no longer looks so mighty.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_haste )) { act("$n is no longer moving so quickly.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_infravision )) found = true; if (check_dispel(level,victim, gsn_invisibility )) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_mass_invis )) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_pass_door )) found = true; if (check_dispel(level,victim, gsn_protection_evil )) found = true; if (check_dispel(level,victim, gsn_protection_good )) found = true; if (check_dispel(level,victim, gsn_rage )) found = true; if (check_dispel(level,victim, gsn_sanctuary )) { act("The white aura around $n's body vanishes.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_shield )) { act("The shield protecting $n vanishes.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_sleep )) found = true; if (check_dispel(level,victim, gsn_slow )) { act("$n is no longer moving so slowly.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_stone_skin )) { act("$n's skin regains its normal texture.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_weaken )) { act("$n looks stronger.",victim,NULL,NULL,TO_ROOM); found = true; } // Cancelation of the vanish skill. for ( roomchar = ch->in_room->people; roomchar != NULL; roomchar = roomchar->next_in_room ) { if ( IS_AFFECTED2(roomchar, AFF2_VANISH)) { affect_strip ( roomchar, gsn_vanish); REMOVE_BIT( roomchar->affected_by2, AFF2_VANISH ); act( "A swirl of dust reveals $n.", roomchar, NULL, NULL, TO_ROOM ); roomchar->println( "You have been revealed." ); found = true; } } if (!found) { ch->println( "Spell failed." ); return HALF_MANA; } ch->println( "Ok." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cause_light( int sn, int level, char_data *ch, void *vo,int ) { damage_spell( ch, (char_data *) vo, dice(1, 8) + level / 3, sn, DAMTYPE( sn ),true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cause_critical(int sn,int level,char_data *ch,void *vo,int ) { damage_spell( ch, (char_data *) vo, dice(3, 8) + level - 6, sn, DAMTYPE( sn ), true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cause_serious(int sn,int level,char_data *ch,void *vo,int ) { damage_spell( ch, (char_data *) vo, dice(2, 8) + level / 2, sn, DAMTYPE( sn ), true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_chain_lightning(int sn,int level,char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; char_data *tmp_vict,*last_vict,*next_vict; bool found; int dam; // first strike act("A lightning bolt leaps from $n's hand and arcs to $N.", ch,NULL,victim,TO_ROOM); act("A lightning bolt leaps from your hand and arcs to $N.", ch,NULL,victim,TO_CHAR); act("A lightning bolt leaps from $n's hand and hits you!", ch,NULL,victim,TO_VICT); dam = dice(level,5); if (saves_spell(level,victim, DAMTYPE(sn))){ dam /= 3; } damage_spell(ch,victim,dam,sn,DAMTYPE(sn),true); last_vict = victim; level -= 4; // decrement damage // new targets while (level > 0) { found = false; for (tmp_vict = ch->in_room->people; tmp_vict != NULL; tmp_vict = next_vict) { next_vict = tmp_vict->next_in_room; if (!is_safe_spell(ch,tmp_vict,true) && tmp_vict != last_vict ) { found = true; last_vict = tmp_vict; act("The bolt arcs to $n!",tmp_vict,NULL,NULL,TO_ROOM); act("The bolt hits you!",tmp_vict,NULL,NULL,TO_CHAR); dam = dice(level,5); if (saves_spell(level,tmp_vict,DAMTYPE(sn))){ dam /= 3; } damage_spell(ch,tmp_vict,dam,sn,DAMTYPE(sn),true); level -= 4; // decrement damage } } // end target searching loop if (!found) // no target found, hit the caster { if (ch == NULL) return FULL_MANA; if (last_vict == ch) // no double hits { act("The bolt seems to have fizzled out.",ch,NULL,NULL,TO_ROOM); act("The bolt grounds out through your body.",ch,NULL,NULL,TO_CHAR); return FULL_MANA; } last_vict = ch; act("The bolt arcs to $n...whoops!",ch,NULL,NULL,TO_ROOM); ch->println( "You are struck by your own lightning!" ); dam = dice(level,6); if (saves_spell(level,ch,DAMTYPE(sn))){ dam /= 3; } damage_spell(ch,ch,dam,sn,DAMTYPE(sn),true); level-= 4; // decrement damage if (ch==NULL || ch->in_room==NULL) { return FULL_MANA; } } // now go back and find more targets } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_change_sex( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( is_affected( victim, sn )) { if (victim == ch) ch->println( "You've already been changed." ); else act("$N has already had $s(?) sex changed.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if (saves_spell(level , victim,DAMTYPE(sn))) return FULL_MANA; af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 2 * level; af.location = APPLY_SEX; do { af.modifier = number_range( 0, 2 ) - victim->sex; } while ( af.modifier == 0 ); af.bitvector = 0; affect_to_char( victim, &af ); victim->println( "You feel different." ); act("$n doesn't look like $mself anymore...",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_charm_person( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if (is_safe(ch,victim)) { ch->printlnf( "Your spell doesnt appear to have any affect on %s.", PERS(victim, ch)); return HALF_MANA; } if ( victim == ch ) { ch->println( "You like yourself even better!" ); return HALF_MANA; } if ( IS_AFFECTED(victim, AFF_CHARM) || IS_AFFECTED(ch, AFF_CHARM) || level < victim->level || IS_SET(victim->imm_flags,IMM_CHARM) || victim->modifiers[STAT_PR]>number_range(0,40) || saves_spell( level, victim, DAMTYPE(sn) ) || (!IS_NPC(victim) && !GAMESETTING2(GAMESET2_NOCHARM_HAS_NOAFFECT) && HAS_CONFIG(victim,CONFIG_NOCHARM) ) ){ ch->println( "You failed." ); return FULL_MANA; } if (!IS_NPC(victim) && IS_SET(victim->in_room->room_flags,ROOM_LAW)) { ch->println( "The mayor does not allow charming in the city limits." ); return HALF_MANA; } if ( victim->master ) { stop_follower( victim ); } add_follower( victim, ch ); victim->leader = ch; af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = number_fuzzy( level / 4 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_CHARM; affect_to_char( victim, &af ); act( "Isn't $n just so nice?", ch, NULL, victim, TO_VICT ); if ( ch != victim ) { act("$N looks at you with adoring eyes.",ch,NULL,victim,TO_CHAR); } if(IS_NPC(victim)) { REMOVE_BIT(victim->act, ACT_AGGRESSIVE); } // stop those who are charmed from logging out if (!IS_NPC(victim) && ch!=victim) { ch->pksafe=0; ch->pknorecall= UMAX(ch->pknorecall,2); ch->pknoquit = UMAX(ch->pknorecall,7); if (!IS_NPC(ch)) { victim->pknorecall= UMAX(victim->pknorecall,4); victim->pknoquit=UMAX(victim->pknoquit,10); } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_chill_touch( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; int dam; dam = dice(level/2, 2); if ( !saves_spell( level, victim,DAMTYPE(sn))) { act("$n turns blue and shivers.",victim,NULL,NULL,TO_ROOM); af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 6; af.location = APPLY_ST; af.modifier = -5; af.bitvector = 0; affect_join( victim, &af ); } else { dam /= 2; } damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_colour_spray( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam = dice(level/3, 4)+40; if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam /= 2; else spell_blindness( gsn_blindness, level/2,ch,(void *) victim,TARGET_CHAR); damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_continual_light(int,int ,char_data *ch,void *,int ) { OBJ_DATA *light; if(!IS_NULLSTR(target_name)) // do a glow on some object { light = get_obj_carry(ch,target_name); if (light == NULL) { ch->printlnf( "You don't see any '%s' here.", target_name ); return NO_MANA; } if (IS_OBJ_STAT(light,OBJEXTRA_GLOW)) { act("$p is already glowing.",ch,light,NULL,TO_CHAR); return NO_MANA; } SET_BIT(light->extra_flags,OBJEXTRA_GLOW); act("$p glows with a white light.",ch,light,NULL,TO_ALL); return FULL_MANA; } light = create_object( get_obj_index( OBJ_VNUM_LIGHT_BALL )); obj_to_room( light, ch->in_room ); act( "$n twiddles $s thumbs and $p appears.", ch, light, NULL, TO_ROOM ); act( "You twiddle your thumbs and $p appears.", ch, light, NULL, TO_CHAR ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_control_weather(int ,int level,char_data *ch,void *,int ) { if ( !str_cmp( target_name, "worse" ) ) weather_info[ch->in_room->sector_type].change += dice( level / 3, 4 ); else if ( !str_cmp( target_name, "better" ) ) weather_info[ch->in_room->sector_type].change -= dice( level / 3, 4 ); else { ch->println( "Do you want it to get better or worse?" ); return NO_MANA; } ch->println( "Ok." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_create_food2( int , int level, char_data *ch, void *,int ) { OBJ_DATA *mushroom; mushroom = create_object( get_obj_index( OBJ_VNUM_MUSHROOM )); mushroom->value[0] = number_fuzzy(level); mushroom->value[1] = number_fuzzy(level)*2; mushroom->timer = (ch->level*2)+10; obj_to_room( mushroom, ch->in_room ); if( ch->in_room->sector_type==SECT_AIR || IS_WATER_SECTOR( ch->in_room->sector_type )){ act( "$p suddenly appears.", ch, mushroom, NULL, TO_ROOM ); act( "$p suddenly appears.", ch, mushroom, NULL, TO_CHAR ); }else{ act( "$p suddenly appears to grow from the ground.", ch, mushroom, NULL, TO_ROOM ); act( "$p suddenly appears to grow from the ground.", ch, mushroom, NULL, TO_CHAR ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_create_food( int , int level, char_data *ch, void *,int ) { OBJ_DATA *fooditem; int foodvnum; char buf[MSL]; foodvnum = race_table[ch->race]->food_vnum; if ( foodvnum == 0 ) foodvnum = OBJ_VNUM_MUSHROOM; if ( get_obj_index( foodvnum ) == NULL ) { bugf("Vnum %d not found for spell_create_food!", foodvnum ); // do an autonote sprintf( buf, "Vnum `Y%d`x not found for race `Y%s`x.`1" "Please create item at next possible convenience.`1", foodvnum, race_table[ch->race]->name); autonote(NOTE_SNOTE, "spell_create_food()", "Create food", "realm", buf, true); // default it to a known item so we don't go BOOM foodvnum = OBJ_VNUM_MUSHROOM; } fooditem = create_object( get_obj_index( foodvnum )); fooditem->value[0] = number_fuzzy(level); fooditem->value[1] = number_fuzzy(level)*2; fooditem->timer = (ch->level*2)+10; obj_to_room( fooditem, ch->in_room ); act( "$p suddenly appears.", ch, fooditem, NULL, TO_ROOM ); act( "$p suddenly appears.", ch, fooditem, NULL, TO_CHAR ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_create_rose( int , int , char_data *ch, void *,int ) { OBJ_DATA *rose; if (get_obj_index(OBJ_VNUM_ROSE)) { rose = create_object(get_obj_index(OBJ_VNUM_ROSE)); act("$n has created a beautiful red rose.",ch,rose,NULL,TO_ROOM); ch->println( "You create a beautiful red rose." ); obj_to_char(rose,ch); }else{ ch->println( "BUG: No available rose object in spell_create_rose - please report!" ); return NO_MANA; } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_create_spring(int ,int level,char_data *ch,void *,int ) { OBJ_DATA *spring; if ( ch->in_room->sector_type == SECT_AIR ) { ch->println( "You cannot create a spring in the middle of the air." ); return HALF_MANA; } if ( IS_WATER_SECTOR( ch->in_room->sector_type )) { ch->println( "You cannot create a spring in water." ); return HALF_MANA; } spring = create_object( get_obj_index( OBJ_VNUM_SPRING )); spring->timer = number_fuzzy(level); obj_to_room( spring, ch->in_room ); act( "$p flows from the ground.", ch, spring, NULL, TO_ROOM ); act( "$p flows from the ground.", ch, spring, NULL, TO_CHAR ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_create_water( int , int level, char_data *ch, void *vo,int ) { OBJ_DATA *obj = (OBJ_DATA *) vo; int water; if ( obj->item_type != ITEM_DRINK_CON ) { ch->println( "It is unable to hold water." ); return NO_MANA; } if ( obj->value[2] != LIQ_WATER && obj->value[1] != 0 ) { ch->println( "It contains some other liquid." ); return HALF_MANA; } water = UMIN( level * (weather_info[ch->in_room->sector_type].sky >= SKY_RAINING ? 4 : 2), obj->value[0] - obj->value[1] ); if ( water > 0 ) { obj->value[2] = LIQ_WATER; obj->value[1] += water; if ( !is_name( "water", obj->name ) ) { char buf[MSL]; sprintf( buf, "%s water", obj->name ); free_string( obj->name ); obj->name = str_dup( buf ); } act( "$p is filled.", ch, obj, NULL, TO_CHAR ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cure_blindness(int ,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; if ( !is_affected( victim, gsn_blindness ) ) { if (victim == ch){ ch->println( "You aren't blind." ); }else{ act("$N doesn't appear to be blinded.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } if (check_dispel(level,victim,gsn_blindness)) { victim->println( "Your vision returns!" ); act("$n is no longer blinded.",victim,NULL,NULL,TO_ROOM); }else{ ch->println("Spell failed."); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cure_critical( int , int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int heal = dice(level/4+1, 2); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); victim->println( "You feel better!" ); if ( ch != victim ){ ch->println( "Ok." ); } return FULL_MANA; } /**************************************************************************/ // RT added to cure plague SPRESULT spell_cure_disease( int , int level, char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; if ( !is_affected( victim, gsn_plague ) ){ if (victim == ch){ ch->println( "You aren't ill." ); }else{ act("$N doesn't appear to be diseased.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } if (check_dispel(level,victim,gsn_plague)) { victim->println( "Your sores vanish." ); act("$n looks relieved as $s sores vanish.",victim,NULL,NULL,TO_ROOM); } else ch->println("Spell failed."); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cure_light( int , int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int heal = dice(level/12+1, 2); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); victim->println( "You feel better!" ); if ( ch != victim ){ ch->println( "Ok." ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cure_poison( int , int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; if ( !is_affected( victim, gsn_poison ) ) { if (victim == ch){ ch->println( "You aren't poisoned." ); }else{ act("$N doesn't appear to be poisoned.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } if (check_dispel(level,victim,gsn_poison)) { victim->println( "A warm feeling runs through your body." ); act("$n looks much better.",victim,NULL,NULL,TO_ROOM); } else ch->println("Spell failed."); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_cure_serious( int , int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int heal = dice(level/8+1, 2); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); victim->println( "You feel better!" ); if ( ch != victim ){ ch->println( "Ok." ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_curse( int sn, int level, char_data *ch, void *vo,int target ) { char_data *victim; OBJ_DATA *obj; AFFECT_DATA af; // deal with the object curses first if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (IS_OBJ_STAT(obj,OBJEXTRA_EVIL)) { act("$p is already filled with evil.",ch,obj,NULL,TO_CHAR); return HALF_MANA; } if (IS_OBJ_STAT(obj,OBJEXTRA_BLESS)) { AFFECT_DATA *paf; paf = affect_find(obj->affected, gsn_bless ); if (!saves_dispel(level,paf != NULL ? paf->level : obj->level,0)) { if (paf != NULL) affect_remove_obj(obj,paf); act("$p glows with a red aura.",ch,obj,NULL,TO_ALL); REMOVE_BIT(obj->extra_flags,OBJEXTRA_BLESS); return FULL_MANA; } else { act("The holy aura of $p is too powerful for you to overcome.",ch,obj,NULL,TO_CHAR); return FULL_MANA; } } af.where = WHERE_OBJEXTRA; af.type = sn; af.level = level; af.duration = 2 * level; af.location = APPLY_SAVES; af.modifier = +1; af.bitvector = OBJEXTRA_EVIL; affect_to_obj(obj,&af); act("$p glows with a malevolent aura.",ch,obj,NULL,TO_ALL); return FULL_MANA; } // character curses victim = (char_data *) vo; if( is_affected( victim, gsn_bless )) if( check_dispel( level, victim, gsn_bless )) { act( "Your magic unravels a spell on $N.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; } else { ch->println( "You failed." ); return FULL_MANA; } if(IS_AFFECTED(victim,AFF_CURSE)) { act("$N already looks very uncomfortable.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if(saves_spell(level,victim,DAMTYPE(sn))){ ch->println( "Your spell doesnt appear to have much affect." ); return FULL_MANA; } if(HAS_CLASSFLAG(victim, CLASSFLAG_CURSE_IMMUNITY)) // fails if paladin { ch->printlnf( "Your spell doesnt appear to have any affect on %s.", PERS(victim, ch) ); return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level/2 + (number_fuzzy(3)*2); af.location = APPLY_HITROLL; af.modifier = -1 * (level / 8); af.bitvector = AFF_CURSE; affect_to_char( victim, &af ); af.location = APPLY_SAVES; af.modifier = level / 8; affect_to_char( victim, &af ); victim->println( "You feel unclean." ); if ( ch != victim ) { act("$N looks very uncomfortable.",ch,NULL,victim,TO_CHAR); // stop those who are slept from logging out if (!IS_NPC(ch)) victim->pknoquit=UMAX(victim->pknoquit,10); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_detect_evil( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_EVIL) ) { if (victim == ch){ ch->println( "You can already sense evil." ); }else{ act("$N can already detect evil.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_EVIL; affect_to_char( victim, &af ); victim->println( "Your eyes tingle." ); if ( ch != victim ){ ch->println( "Ok." ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_detect_good( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_GOOD) ) { if (victim == ch){ ch->println( "You can already sense good." ); }else{ act("$N can already detect good.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_GOOD; affect_to_char( victim, &af ); victim->println( "Your eyes tingle." ); if ( ch != victim ) ch->println( "Ok." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_detect_hidden(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_HIDDEN) ) { if (victim == ch){ ch->println( "You are already as alert as you can be." ); }else{ act("$N can already sense hidden lifeforms.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_DETECT_HIDDEN; affect_to_char( victim, &af ); victim->println( "Your awareness improves." ); if ( ch != victim ){ ch->println( "Ok." ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_detect_invis( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_INVIS) ) { if (victim == ch){ ch->println( "You can already see invisible." ); }else{ act("$N can already see invisible things.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_INVIS; affect_to_char( victim, &af ); victim->println( "Your eyes tingle." ); if ( ch != victim ){ ch->println( "Ok." ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_detect_magic( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_MAGIC) ) { if (victim == ch){ ch->println( "You can already sense magical auras." ); }else{ act("$N can already detect magic.",ch,NULL,victim,TO_CHAR); } return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_MAGIC; affect_to_char( victim, &af ); victim->println( "Your eyes tingle." ); if ( ch != victim ){ ch->println( "Ok." ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_detect_poison( int , int , char_data *ch, void *vo,int ) { OBJ_DATA *obj = (OBJ_DATA *) vo; if ( obj->item_type == ITEM_DRINK_CON || obj->item_type == ITEM_FOOD ) { if ( obj->value[3] != 0 ){ ch->println( "You smell poisonous fumes." ); }else{ ch->println( "It looks delicious." ); } }else{ ch->println( "It doesn't look poisoned." ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_dispel_evil( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam; if ( !IS_NPC(ch) && IS_EVIL(ch) ) victim = ch; if ( IS_GOOD(victim) ) { act( "$N appears to be protected.", ch, NULL, victim, TO_ROOM ); return FULL_MANA; } if ( IS_NEUTRAL(victim) ) { act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; } if (victim->hit > (ch->level * 4)) dam = dice( level, 4 ); else dam = UMAX(victim->hit, dice(level,4)); if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /***************************************************************************/ SPRESULT spell_dispel_good( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam; if ( !IS_NPC(ch) && IS_GOOD(ch) ) victim = ch; if ( IS_EVIL(victim) ) { act( "$N is protected by $S evil.", ch, NULL, victim, TO_ROOM ); return FULL_MANA; } if ( IS_NEUTRAL(victim) ) { act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; } if (victim->hit > (ch->level * 4)) dam = dice( level, 4 ); else dam = UMAX(victim->hit, dice(level,4)); if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn) ,true); return FULL_MANA; } /***************************************************************************/ // modified for enhanced use SPRESULT spell_dispel_magic( int sn , int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; bool found = false; if (saves_spell(level, victim,DAMTYPE(sn))) { victim->println( "You feel a brief tingling sensation." ); ch->println( "You failed." ); return FULL_MANA; } // begin running through the spells found = check_dispel(level,victim,gsn_regeneration); found = check_dispel(level,victim,gsn_resist_poison); found = check_dispel(level,victim,gsn_poison_immunity); found = check_dispel(level,victim,gsn_prismatic_spray); found = check_dispel(level,victim,gsn_illusions_grandeur); found = check_dispel(level,victim,gsn_protection_fire); found = check_dispel(level,victim,gsn_protection_cold); found = check_dispel(level,victim,gsn_protection_acid); found = check_dispel(level,victim,gsn_protection_lightning); found = check_dispel(level,victim,gsn_holy_aura); found = check_dispel(level,victim,gsn_unholy_aura); found = check_dispel(level,victim,gsn_true_sight); found = check_dispel(level,victim,gsn_barkskin); found = check_dispel(level,victim,gsn_magic_resistance); found = check_dispel(level,victim,gsn_fire_shield); found = check_dispel(level,victim,gsn_chill_shield); found = check_dispel(level,victim,gsn_animal_essence); found = check_dispel(level,victim,gsn_armor); found = check_dispel(level,victim,gsn_bless); if (check_dispel(level,victim,gsn_blindness )) { found = true; act("$n is no longer blinded.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,gsn_calm)) { found = true; act("$n no longer looks so peaceful...",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim, gsn_change_sex )) { found = true; act("$n looks more like $mself again.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,gsn_charm_person)) { found = true; act("$n regains $s free will.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim,gsn_chill_touch)) { found = true; act("$n looks warmer.",victim,NULL,NULL,TO_ROOM); } if (check_dispel(level,victim, gsn_curse )) found = true; if (check_dispel(level,victim,gsn_detect_evil)) found = true; if (check_dispel(level,victim,gsn_detect_scry )) found = true; if (check_dispel(level,victim,gsn_detect_good)) found = true; if (check_dispel(level,victim,gsn_detect_hidden)) found = true; if (check_dispel(level,victim,gsn_detect_invis)) found = true; if (check_dispel(level,victim,gsn_detect_magic)) found = true; if (check_dispel(level,victim, gsn_faerie_fire )) { act("$n's outline fades.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_fly )) { act("$n falls to the ground!",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_frenzy )) { act("$n no longer looks so wild.",victim,NULL,NULL,TO_ROOM);; found = true; } if (check_dispel(level,victim, gsn_giant_strength )) { act("$n no longer looks so mighty.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_haste )) { act("$n is no longer moving so quickly.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim,gsn_infravision)) found = true; if (check_dispel(level,victim, gsn_invisibility )) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim,gsn_mass_invis)) { act("$n fades into existance.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim,gsn_pass_door)) found = true; if (check_dispel(level,victim,gsn_protection_evil)) found = true; if (check_dispel(level,victim,gsn_protection_good)) found = true; if (check_dispel(level,victim,gsn_rage)) found = true; if (check_dispel(level,victim, gsn_sanctuary )) { act("The white aura around $n's body vanishes.",victim,NULL,NULL,TO_ROOM); found = true; } if (IS_AFFECTED(victim,AFF_SANCTUARY) && !saves_dispel(level, victim->level,-1) && !is_affected(victim, gsn_sanctuary )) { REMOVE_BIT(victim->affected_by,AFF_SANCTUARY); act("The white aura around $n's body vanishes.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim,gsn_shield)) { act("The shield protecting $n vanishes.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim,gsn_sleep)) found = true; if (check_dispel(level,victim, gsn_slow )) { act("$n is no longer moving so slowly.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim,gsn_stone_skin)) { act("$n's skin regains its normal texture.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim, gsn_weaken )) { act("$n looks stronger.",victim,NULL,NULL,TO_ROOM); found = true; } if (check_dispel(level,victim,gsn_wind_shield)) { act("The wind around $n's body dies down.",victim,NULL,NULL,TO_ROOM); found = true; } if (found) ch->println( "Ok." ); else { ch->println("Spell failed."); return HALF_MANA; } return FULL_MANA; } /***************************************************************************/ SPRESULT spell_earthquake( int sn, int level, char_data *ch, void *,int ) { char_data *vch; char_data *vch_next; ch->println( "The earth trembles beneath your feet!" ); act( "$n makes the earth tremble and shiver.", ch, NULL, NULL, TO_ROOM ); for ( vch = ch->in_room->people; vch; vch = vch_next ) { vch_next=vch->next_in_room; if ( vch->in_room == NULL ) continue; if ( vch->in_room == ch->in_room ) { if ( vch != ch && !is_safe_spell(ch,vch,true)) if (IS_AFFECTED(vch,AFF_FLYING)) damage_spell(ch,vch,0,sn,DAMTYPE(sn),true); else damage_spell( ch,vch,level + dice(2, 8), sn, DAMTYPE(sn),true); continue; } if ( vch->in_room->area == ch->in_room->area ){ vch->println( "The earth trembles and shivers." ); } } return FULL_MANA; } /***************************************************************************/ SPRESULT spell_enchant_armor( int sn, int level, char_data *ch, void *vo,int ) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; int result, fail; int added; bool ac_found = false; /* checks if enchant can be done */ if (obj->item_type != ITEM_ARMOR) { ch->printf( "That isn't an armor.\r\n" ); return NO_MANA; } if (obj->wear_loc != -1) { ch->printf( "The item must be carried to be enchanted.\r\n" ); return NO_MANA; } fail = 25; // base 25% chance of failure // find the current bonuses - affect success for (paf=OBJECT_AFFECTS(obj); paf; paf=paf->next ) { if ( paf->location == APPLY_AC ) { if (paf->duration == -1) // can't add to a perm armour enchant { ch->printf( "%s starts to pulsate then it dissolves before your eyes!!!\r\n", format_obj_to_char(obj, ch, true)); extract_obj(obj); return FULL_MANA; } ac_found = true; fail += 5 * paf->modifier * paf->modifier; } else { fail += 20; } } // apply other modifiers fail -= level; if (IS_OBJ_STAT(obj,OBJEXTRA_BLESS)) fail -= 15; if (IS_OBJ_STAT(obj,OBJEXTRA_GLOW)) fail -= 5; fail = URANGE(5,fail,85); result = number_percent(); // the moment of truth if (result < (fail / 5)) // item destroyed { act("$p flares blindingly... and evaporates!",ch,obj,NULL,TO_CHAR); act("$p flares blindingly... and evaporates!",ch,obj,NULL,TO_ROOM); extract_obj(obj); return FULL_MANA; } if (result < (fail / 3)) // item disenchanted { AFFECT_DATA *paf_next; act("$p glows brightly, then fades...oops.",ch,obj,NULL,TO_CHAR); act("$p glows brightly, then fades.",ch,obj,NULL,TO_ROOM); // free all affects for (paf = obj->affected; paf; paf = paf_next) { paf_next = paf->next; free_affect(paf); } obj->affected = NULL; obj->no_affects = true; // flag the object as no_affects so // the olc template's affects arent used. // clear all flags obj->extra_flags = 0; return FULL_MANA; } if ( result <= fail ) // failed, no bad result { ch->printf( "Nothing seemed to happen.\r\n" ); return FULL_MANA; } // **** ALL SUCCESSFUL ENCHANTS BELOW HERE **** // now setup all the enchants: // - if it enchants, weren't stored on the object, copy the enchants // from the object vnums enchants. affects_from_template_to_obj(obj); if (result <= (90 - level/5)) // success! { act("$p shimmers with a golden aura.",ch,obj,NULL,TO_CHAR); act("$p shimmers with a golden aura.",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags, OBJEXTRA_MAGIC); added = -1; }else{ // exceptional enchant act("$p glows a brillant gold!",ch,obj,NULL,TO_CHAR); act("$p glows a brillant gold!",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags,OBJEXTRA_MAGIC); SET_BIT(obj->extra_flags,OBJEXTRA_GLOW); added = -2; } // now add the new armour enchantment if (ac_found){ // if there is already an enchant on it for ( paf = obj->affected; paf != NULL; paf = paf->next) { if ( paf->location == APPLY_AC) { paf->type = sn; paf->modifier += added; if (ch->level>paf->level) paf->level = ch->level; } } }else{ // add a new armour affect at the head of the affected list paf = new_affect(); paf->where = WHERE_OBJEXTRA; paf->type = sn; paf->level = ch->level; paf->duration = level*20; paf->location = APPLY_AC; paf->modifier = added; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } return FULL_MANA; } /***************************************************************************/ SPRESULT spell_enchant_weapon(int sn,int level, char_data *ch, void *vo,int ) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; int result, fail; int added; bool hit_found = false, dam_found = false; // do standard checks - if spell can be cast if (obj->item_type != ITEM_WEAPON) { ch->printf( "That isn't a weapon.\r\n" ); return NO_MANA; } if (obj->wear_loc != -1) { ch->printf( "The item must be carried to be enchanted.\r\n" ); return NO_MANA; } fail = 25; // base 25% chance of failure // find the current bonuses - affect success for (paf=OBJECT_AFFECTS(obj); paf; paf=paf->next ) { if ( paf->location == APPLY_HITROLL ){ hit_found = true; fail += 2 * paf->modifier * paf->modifier; if (paf->duration == -1) // can't add to a perm weapon enchant { ch->printf( "%s starts to pulsate then it dissolves before your eyes!!!", capitalize(format_obj_to_char(obj, ch, true))); extract_obj(obj); return FULL_MANA; } }else if (paf->location == APPLY_DAMROLL ){ dam_found = true; fail += 2 * paf->modifier * paf->modifier; if (paf->duration == -1) // can't add to a perm weapon enchant { ch->printf( "%s starts to pulsate then it dissolves before your eyes!!!\r\n", format_obj_to_char(obj, ch, true)); extract_obj(obj); return FULL_MANA; } }else{ fail += 20; } } // apply other modifiers fail -= 3 * level/2; if (IS_OBJ_STAT(obj,OBJEXTRA_BLESS)){ fail -= 15; }if (IS_OBJ_STAT(obj,OBJEXTRA_GLOW)){ fail -= 5; } fail = URANGE(5,fail,95); result = number_percent(); // the moment of truth if (result < (fail / 5)){ // item destroyed act("$p shivers violently and explodes!",ch,obj,NULL,TO_CHAR); act("$p shivers violently and explodes!",ch,obj,NULL,TO_ROOM); extract_obj(obj); return FULL_MANA; } if (result < (fail / 2)){ // item disenchanted AFFECT_DATA *paf_next; act("$p glows brightly, then fades...oops.",ch,obj,NULL,TO_CHAR); act("$p glows brightly, then fades.",ch,obj,NULL,TO_ROOM); // free all affects for (paf = obj->affected; paf; paf = paf_next) { paf_next = paf->next; free_affect(paf); } obj->affected = NULL; obj->no_affects = true; // flag the object as no_affects so // the olc template's affects arent used. // clear all flags obj->extra_flags = 0; return FULL_MANA; } if ( result <= fail ) // failed, no bad result { ch->printf( "Nothing seemed to happen.\r\n" ); return FULL_MANA; } // **** ALL SUCCESSFUL ENCHANTS BELOW HERE **** // now setup all the enchants: // - if it enchants, weren't stored on the object, copy the enchants // from the object vnums enchants. affects_from_template_to_obj(obj); if (result <= (100 - level/5)){ // success! act("$p glows blue.",ch,obj,NULL,TO_CHAR); act("$p glows blue.",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags, OBJEXTRA_MAGIC); added = 1; }else{ // exceptional enchant act("$p glows a brillant blue!",ch,obj,NULL,TO_CHAR); act("$p glows a brillant blue!",ch,obj,NULL,TO_ROOM); SET_BIT(obj->extra_flags,OBJEXTRA_MAGIC); SET_BIT(obj->extra_flags,OBJEXTRA_GLOW); added = 2; } // now add the enchantments if (dam_found){ for ( paf = obj->affected; paf != NULL; paf = paf->next) { if ( paf->location == APPLY_DAMROLL) { paf->type = sn; paf->modifier += added; if (ch->level>paf->level) // up the level if caster is higher paf->level = ch->level; if (paf->modifier > 4 && (number_range(1,100)<95)) SET_BIT(obj->extra_flags,OBJEXTRA_HUM); } } }else{ // add a new damroll affect paf = new_affect(); paf->where = WHERE_OBJEXTRA; paf->type = sn; paf->level = ch->level; paf->duration = level * 20; paf->location = APPLY_DAMROLL; paf->modifier = added; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } if (hit_found){ for ( paf = obj->affected; paf != NULL; paf = paf->next) { if ( paf->location == APPLY_HITROLL) { paf->type = sn; paf->modifier += added; paf->level = UMAX(paf->level,level)/2; if (paf->modifier > 4){ SET_BIT(obj->extra_flags,OBJEXTRA_HUM); } } } }else{ // add a new affect paf = new_affect(); paf->type = sn; paf->level = ch->level; paf->duration = level * 20; paf->location = APPLY_HITROLL; paf->modifier = added; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } return FULL_MANA; } /**************************************************************************/ // Drain XP, MANA, HP from victim - Caster gains HP. SPRESULT spell_energy_drain( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam; int temp_hps; if ( saves_spell( level, victim,DAMTYPE(sn))) { victim->printf( "You feel a momentary chill.\r\n" ); ch->printf( "Your spell doesnt appear to have much affect.\r\n" ); return FULL_MANA; } if ( victim->level <= 2 ) dam = ch->hit + 1; else dam = dice(1, level/4); if (damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true)) { gain_exp( victim, 0 - number_range( level/2, level) ); victim->mana /= 2; victim->move /= 2; victim->printf( "You feel your life slipping away!\r\n" ); temp_hps=victim->hit; if(victim->hit<-10) victim->hit=-10; // give caster some HP back if ((temp_hps-victim->hit)>0) { ch->hit+= (temp_hps-victim->hit); ch->printf( "Wow....what a rush!\r\n" ); } else { ch->printf( "They look drained.\r\n" ); } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_fireball( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam; dam = dice(level, 6)+10; if ( saves_spell( level, victim, DAMTYPE(sn))) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_fireproof(int sn, int level, char_data *ch, void *vo,int ) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA af; if (IS_OBJ_STAT(obj,OBJEXTRA_BURN_PROOF)) { act("$p is already protected from burning.",ch,obj,NULL,TO_CHAR); return HALF_MANA; } af.where = WHERE_OBJEXTRA; af.type = sn; af.level = level; af.duration = number_fuzzy(level / 4); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = OBJEXTRA_BURN_PROOF; affect_to_obj(obj,&af); act("You protect $p from fire.",ch,obj,NULL,TO_CHAR); act("$p is surrounded by a protective aura.",ch,obj,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_flamestrike( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam; dam = dice(6 + level / 2, 8); if ( saves_spell( level, victim,DAMTYPE(sn))) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_frostball ( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; int dam; dam = dice( level, 9 ); if ( saves_spell( level, victim, DAMTYPE(sn))) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn), true ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_faerie_fire( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) ) { ch->printf( "They are already aglow.\r\n" ); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level/3 + number_fuzzy(3)*3; af.location = APPLY_AC; af.modifier = 2 * level; af.bitvector = AFF_FAERIE_FIRE; affect_to_char( victim, &af ); victim->printf( "You are surrounded by a pink outline.\r\n" ); act( "$n is surrounded by a pink outline.", victim, NULL, NULL, TO_ROOM ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_faerie_fog( int sn, int level, char_data *ch, void *,int ) { char_data *ich; long tempflag; bool changed= false; act( "$n conjures a cloud of purple smoke.", ch, NULL, NULL, TO_ROOM ); ch->printf( "You conjure a cloud of purple smoke.\r\n" ); for ( ich = ch->in_room->people; ich != NULL; ich = ich->next_in_room ) { if (INVIS_LEVEL(ich)> 0) continue; if ( ich == ch || saves_spell( level, ich,DAMTYPE(sn)) ) continue; tempflag=ich->affected_by; if (is_affected( ich, gsn_invisibility )) { affect_strip ( ich, gsn_invisibility ); changed = true; } if (is_affected( ich, gsn_mass_invis)) { affect_strip ( ich, gsn_mass_invis); changed = true; } if (is_affected( ich, gsn_sneak)) { affect_strip ( ich, gsn_sneak); changed = true; } if (IS_AFFECTED2( ich, AFF2_VANISH)) { affect_strip ( ich, gsn_vanish); changed = true; } REMOVE_BIT( ich->affected_by, AFF_HIDE ); REMOVE_BIT( ich->affected_by, AFF_INVISIBLE ); REMOVE_BIT( ich->affected_by, AFF_SNEAK ); REMOVE_BIT( ich->affected_by2, AFF2_VANISH ); if (ich->affected_by!=tempflag || changed) { act( "$n is revealed!", ich, NULL, NULL, TO_ROOM ); ich->printf( "You are revealed!\r\n" ); } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_floating_disc( int , int level,char_data *ch,void *,int ) { OBJ_DATA *disc, *floating; floating = get_eq_char(ch,WEAR_FLOAT); if (floating != NULL && IS_OBJ_STAT(floating,OBJEXTRA_NOREMOVE)) { act("You can't remove $p.",ch,floating,NULL,TO_CHAR); return NO_MANA; } disc = create_object(get_obj_index(OBJ_VNUM_DISC)); disc->value[0] = ch->level * 10; // 10 lbs per level capacity disc->value[3] = ch->level * 5; // 5 lbs per level max per item disc->timer = ch->level * 2 - number_range(0,level / 2); act("$n has created a floating black disc.",ch,NULL,NULL,TO_ROOM); ch->printf( "You create a floating disc.\r\n" ); obj_to_char(disc,ch); wear_obj(ch,disc,true, false); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_fly( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_SET( ch->in_room->room_flags, ROOM_NOFLY )) { ch->println( "The powerful winds prevent you from taking to air." ); return NO_MANA; } if ( IS_AFFECTED(victim, AFF_FLYING) ) { if (victim == ch) ch->printf( "You are already airborne.\r\n" ); else act("$N doesn't need your help to fly.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level + 3; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_FLYING; affect_to_char( victim, &af ); victim->println( "Your feet rise off the ground." ); act( "$n's feet rise off the ground.", victim, NULL, NULL, TO_ROOM ); return FULL_MANA; } /**************************************************************************/ // RT clerical berserking spell SPRESULT spell_frenzy(int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if (is_affected(victim,sn) || IS_AFFECTED(victim,AFF_BERSERK)) { if (victim == ch) ch->printf( "You are already in a frenzy.\r\n" ); else act("$N is already in a frenzy.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if (is_affected(victim,gsn_calm)) { if (victim == ch) ch->printf( "Why don't you just relax for a while?\r\n" ); else act("$N doesn't look like $e wants to fight anymore.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if ((IS_GOOD(ch) && !IS_GOOD(victim)) || (IS_NEUTRAL(ch) && !IS_NEUTRAL(victim)) || (IS_EVIL(ch) && !IS_EVIL(victim))) { act("Your god doesn't seem to like $N",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level / 3; af.modifier = level / 6; af.bitvector = 0; af.location = APPLY_HITROLL; affect_to_char(victim,&af); af.location = APPLY_DAMROLL; affect_to_char(victim,&af); af.modifier = 10 * (level / 12); af.location = APPLY_AC; affect_to_char(victim,&af); victim->printf( "You are filled with holy wrath!\r\n" ); act("$n gets a wild look in $s eyes!",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_gate( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; bool gate_pet; if (( victim = get_char_icworld( ch, target_name ) ) == NULL || victim == ch || victim->in_room == NULL || !can_see_room(ch,victim->in_room) || IS_SET(victim->in_room->room_flags, ROOM_SAFE) || IS_SET(victim->in_room->room_flags, ROOM_PRIVATE) || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) || IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(victim->in_room->room_flags, ROOM_NOSCRY) || IS_SET(victim->in_room->room_flags, ROOM_ANTIMAGIC) || IS_SET(victim->in_room->area->area_flags, AREA_NOSCRY) || IS_SET(victim->in_room->area->area_flags, AREA_NOGATEINTO) || IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL) // NOT trust || (IS_NPC(victim) && IS_SET(victim->imm_flags,IMM_SUMMON)) || (IS_NPC(victim) && saves_spell( level, victim,DAMTYPE(sn))) || (!IS_NPC(victim) && saves_spell( level, victim, DAMTYPE(sn)))) { ch->println( "You failed." ); return FULL_MANA; } if ( ch->in_room->area->continent != victim->in_room->area->continent ) { ch->println( "The spell cannot span such a great distance." ); return FULL_MANA; } if(ch->pet && ch->in_room == ch->pet->in_room){ gate_pet = true; }else{ gate_pet = false; } act("$n steps through a gate and vanishes.",ch,NULL,NULL,TO_ROOM); ch->printf( "You step through a gate and vanish.\r\n" ); char_from_room(ch); char_to_room(ch,victim->in_room); act("$n has arrived through a gate.",ch,NULL,NULL,TO_ROOM); do_look(ch,"auto"); /* * If someone is following the char, these triggers get activated * for the followers before the char, but it's safer this way... */ if ( IS_NPC( ch ) && HAS_TRIGGER( ch, TRIG_ENTRY ) ){ mp_percent_trigger( ch, NULL, NULL, NULL, TRIG_ENTRY ); } if ( !IS_NPC( ch ) ){ mp_greet_trigger( ch ); } if (gate_pet) { act("$n steps through a gate and vanishes.",ch->pet,NULL,NULL,TO_ROOM); ch->pet->printf( "You step through a gate and vanish.\r\n" ); char_from_room(ch->pet); char_to_room(ch->pet,victim->in_room); act("$n has arrived through a gate.",ch->pet,NULL,NULL,TO_ROOM); do_look(ch->pet,"auto"); /* * If someone is following the char, these triggers get activated * for the followers before the char, but it's safer this way... */ if (ch->pet) { if ( IS_NPC( ch->pet) && HAS_TRIGGER( ch->pet, TRIG_ENTRY ) ){ mp_percent_trigger( ch->pet, NULL, NULL, NULL, TRIG_ENTRY ); } if ( !IS_NPC( ch->pet) ){ mp_greet_trigger( ch->pet); } } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_giant_strength(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; bool half = false; if(check_strength(level, ch, victim, half)) return FULL_MANA; if(half) return HALF_MANA; af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_ST; af.modifier = 1 + level/5; af.bitvector = 0; affect_to_char( victim, &af ); victim->printf( "Your muscles surge with heightened power!\r\n" ); act("$n's muscles surge with heightened power.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_harm( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam; dam = UMAX( 20, victim->hit - dice(1,4) ); if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam = UMIN( 50, dam / 2 ); dam = UMIN( 100, dam ); damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /**************************************************************************/ // RT haste spell SPRESULT spell_haste( int sn, int level, char_data *ch, void *vo,int) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) || IS_AFFECTED(victim,AFF_HASTE) || IS_SET(victim->off_flags,OFF_FAST)) { if (victim == ch) ch->printf( "You can't move any faster!\r\n" ); else act("$N is already moving as fast as $E can.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if (IS_AFFECTED(victim,AFF_SLOW)) { if (!check_dispel(level,victim, gsn_slow )) { if (victim != ch) ch->println("Spell failed."); victim->printf( "You feel momentarily faster.\r\n" ); return FULL_MANA; } act("$n is moving less slowly.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; if (victim == ch){ af.duration = level/2; }else{ af.duration = level/4; } af.location = APPLY_QU; af.modifier = 1 + level/5; af.bitvector = AFF_HASTE; affect_to_char( victim, &af ); victim->printf( "You feel yourself moving more quickly.\r\n" ); act("$n is moving more quickly.",victim,NULL,NULL,TO_ROOM); if ( ch != victim ) ch->println( "Ok." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_heal( int , int , char_data *ch, void *vo,int) { char_data *victim = (char_data *) vo; victim->hit = UMIN( victim->hit + game_settings->max_hp_from_heal_spell, victim->max_hit ); update_pos( victim ); victim->printf( "A warm feeling fills your body.\r\n" ); if ( ch != victim ) ch->println( "Ok." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_heat_metal( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; OBJ_DATA *obj_lose, *obj_next; int dam = 0; bool fail = true; if (!saves_spell(level + 2,victim,DAMTYPE(sn)) && !IS_SET(victim->imm_flags,IMM_FIRE)) { for ( obj_lose = victim->carrying; obj_lose != NULL; obj_lose = obj_next) { obj_next = obj_lose->next_content; if ( number_range(1,2 * level) > obj_lose->level && !saves_spell(level,victim,DAMTYPE(sn)) && !IS_OBJ_STAT(obj_lose,OBJEXTRA_NONMETAL) && !IS_OBJ_STAT(obj_lose,OBJEXTRA_BURN_PROOF)) { switch ( obj_lose->item_type ) { case ITEM_ARMOR: if (obj_lose->wear_loc != -1) /* remove the item */ { if (can_drop_obj(victim,obj_lose) && (obj_lose->weight / 10) < number_range(1,ch->modifiers[STAT_QU]) && remove_obj( victim, obj_lose->wear_loc, true )) { act("$n yelps and throws $p to the ground!",victim,obj_lose,NULL,TO_ROOM); act("You remove and drop $p before it burns you.",victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 3); obj_from_char(obj_lose); obj_to_room(obj_lose, victim->in_room); fail = false; } else /* stuck on the body! ouch! */ { act("Your skin is seared by $p!",victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level)); fail = false; } } else /* drop it if we can */ { if (can_drop_obj(victim,obj_lose)) { act("$n yelps and throws $p to the ground!",victim,obj_lose,NULL,TO_ROOM); act("You and drop $p before it burns you.",victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 6); obj_from_char(obj_lose); obj_to_room(obj_lose, victim->in_room); fail = false; } else /* cannot drop */ { act("Your skin is seared by $p!",victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 2); fail = false; } } break; case ITEM_WEAPON: if (obj_lose->wear_loc != -1) /* try to drop it */ { if (IS_WEAPON_STAT(obj_lose,WEAPON_FLAMING)) continue; if (can_drop_obj(victim,obj_lose) && remove_obj(victim,obj_lose->wear_loc,true)) { act("$n is burned by $p, and throws it to the ground.",victim,obj_lose,NULL,TO_ROOM); victim->printf( "You throw your red-hot weapon to the ground!\r\n" ); dam += 1; obj_from_char(obj_lose); obj_to_room(obj_lose,victim->in_room); fail = false; } else /* YOWCH! */ { victim->printf( "Your weapon sears your flesh!\r\n" ); dam += number_range(1,obj_lose->level); fail = false; } } else /* drop it if we can */ { if (can_drop_obj(victim,obj_lose)) { act("$n throws a burning hot $p to the ground!",victim,obj_lose,NULL,TO_ROOM); act("You and drop $p before it burns you.",victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 6); obj_from_char(obj_lose); obj_to_room(obj_lose, victim->in_room); fail = false; } else /* cannot drop */ { act("Your skin is seared by $p!",victim,obj_lose,NULL,TO_CHAR); dam += (number_range(1,obj_lose->level) / 2); fail = false; } } break; } } } } if (fail) { ch->printf( "Your spell had no effect.\r\n" ); victim->printf( "You feel momentarily warmer.\r\n" ); } else /* damage! */ { if (saves_spell(level,victim,DAMTYPE(sn))) dam = 2 * dam / 3; damage_spell(ch,victim,dam,sn,DAMTYPE(sn),true); } return FULL_MANA; } /**************************************************************************/ // RT really nasty high-level attack spell SPRESULT spell_holy_word(int sn, int level, char_data *ch, void *,int ) { char_data *vch; char_data *vch_next; int dam; int bless_num, curse_num, frenzy_num; bless_num = gsn_bless; curse_num = gsn_curse; frenzy_num = gsn_frenzy; act("$n utters a word of divine power!",ch,NULL,NULL,TO_ROOM); ch->printf( "You utter a word of divine power.\r\n" ); for ( vch = ch->in_room->people; vch != NULL; vch = vch_next ) { vch_next = vch->next_in_room; if ((IS_GOOD(ch) && IS_GOOD(vch)) || (IS_EVIL(ch) && IS_EVIL(vch)) || (IS_NEUTRAL(ch) && IS_NEUTRAL(vch))) { vch->printf( "You feel full more powerful.\r\n" ); spell_frenzy(frenzy_num,level,ch,(void *) vch,TARGET_CHAR); spell_bless(bless_num,level,ch,(void *) vch,TARGET_CHAR); } else if ((IS_GOOD(ch) && IS_EVIL(vch)) || (IS_EVIL(ch) && IS_GOOD(vch))) { if (!is_safe_spell(ch,vch,true)) { spell_curse(curse_num,level,ch,(void *) vch,TARGET_CHAR); vch->printf( "You are struck down!\r\n" ); dam = dice(level,12); damage_spell(ch,vch,dam,sn,DAMTYPE(sn),true); } } else if (IS_NEUTRAL(vch)) { if (!is_safe_spell(ch,vch,true)) { spell_curse(curse_num,level/2,ch,(void *) vch,TARGET_CHAR); vch->printf( "You are struck down!\r\n" ); dam = dice(level,10); damage_spell(ch,vch,dam,sn,DAMTYPE(sn),true); } } } ch->printf( "You feel drained.\r\n" ); ch->move = 0; ch->hit /= 2; return FULL_MANA; } /**************************************************************************/ SPRESULT spell_identify( int, int, char_data *ch, void *vo, int ) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf=NULL; // Herb check instant crap out if ( obj->item_type == ITEM_HERB ) { ch->printf( "Your spell fizzles.\r\n" ); return NO_MANA; } ch->printf( "Object '%s' is type %s,\r\n" "extra flags %s.\r\n" "extra2 flags %s.\r\n" "Weight is %0.1f lbs, value is %d, level is %d.\r\n", obj->name, item_type_name( obj ), extra_bit_name( obj->extra_flags ), extra2_bit_name( obj->extra2_flags ), ((double)obj->weight) / 10, obj->cost, obj->level ); switch ( obj->item_type ) { case ITEM_SCROLL: case ITEM_POTION: case ITEM_PILL: ch->printf( "Level %d spells of:", obj->value[0] ); if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL ) { ch->printf( " '%s'", skill_table[obj->value[1]].name ); } if ( obj->value[2] >= 0 && obj->value[2] < MAX_SKILL ) { ch->printf( " '%s'", skill_table[obj->value[2]].name ); } if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL ) { ch->printf( " '%s'", skill_table[obj->value[3]].name ); } if (obj->value[4] >= 0 && obj->value[4] < MAX_SKILL) { ch->printf( " '%s'", skill_table[obj->value[4]].name ); } ch->printf( ".\r\n" ); break; case ITEM_WAND: case ITEM_STAFF: ch->printf( "Has %d charges of level %d", obj->value[2], obj->value[0] ); if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL ) { ch->printf( " '%s'", skill_table[obj->value[3]].name ); } ch->printf( ".\r\n" ); break; case ITEM_DRINK_CON: ch->printf( "It holds %s-colored %s.\r\n", liq_table[obj->value[2]].liq_color, liq_table[obj->value[2]].liq_name); break; case ITEM_CAULDRON: case ITEM_CONTAINER: case ITEM_FLASK: case ITEM_MORTAR: ch->printlnf( "Maximum combined weight: %d lbs, Capacity for an individual item: %d lbs.", obj->value[0], obj->value[3]); ch->printlnf( "Flags: %s.", cont_bit_name(obj->value[1])); if (obj->value[4] != 100){ ch->printf( "Weight multiplier: %d%%\r\n", obj->value[4]); } break; case ITEM_WEAPON: { ch->printf( "Weapon type is %s.\r\n", get_weapontype( obj )); ch->printf("Damage is %dd%d (average %d).\r\n", obj->value[1],obj->value[2], (1 + obj->value[2]) * obj->value[1] / 2); if (obj->value[4]) // weapon flags { ch->printf("Weapons flags: %s\r\n",weapon_bit_name(obj->value[4])); } } break; case ITEM_COMPONENT: if ( obj->value[0] < 0 ) { ch->printf( "Has unlimited charges for the spell" ); } else { ch->printf( "Can be used %d more times for the spell", obj->value[0] ); } if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL ) { ch->printf( " '%s'", skill_table[obj->value[1]].name ); } ch->printf( ".\r\n" ); break; case ITEM_ARMOR: ch->printf( "Armor class is %d pierce, %d bash, %d slash, and %d vs. magic.\r\n", obj->value[0], obj->value[1], obj->value[2], obj->value[3] ); break; } for ( paf = OBJECT_AFFECTS(obj); paf; paf = paf->next ) { if ( paf->location != APPLY_NONE && paf->modifier != 0 ) { if(paf->duration > -1){ ch->printf( "Affects %s by %d for %d hour%s.%s\r\n", affect_loc_name( paf->location ), paf->modifier, paf->duration, paf->duration==1?"":"s", (paf->level>ch->level?" (above your level)":"")); }else{ ch->printf( "Affects %s by %d.%s\r\n", affect_loc_name( paf->location ), paf->modifier, (paf->level>ch->level?" (above your level)":"")); } if (paf->bitvector) { ch->printlnf( "%s", to_affect_string( paf, obj->level )); } } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_infravision( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_INFRARED) ) { if (victim == ch) ch->printf( "You can already see in the dark.\r\n" ); else act("$N already has infravision.\r\n",ch,NULL,victim,TO_CHAR); return HALF_MANA; } act( "$n's eyes glow red.\r\n", ch, NULL, NULL, TO_ROOM ); af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 2 * level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INFRARED; affect_to_char( victim, &af ); victim->printf( "Your eyes glow red.\r\n" ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_invisibility( int sn, int level, char_data *ch, void *vo,int target ) { char_data *victim; OBJ_DATA *obj; AFFECT_DATA af; /* object invisibility */ if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (IS_OBJ_STAT(obj,OBJEXTRA_INVIS)) { act("$p is already invisible.",ch,obj,NULL,TO_CHAR); return HALF_MANA; } af.where = WHERE_OBJEXTRA; af.type = sn; af.level = level; af.duration = level + 12; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = OBJEXTRA_INVIS; affect_to_obj(obj,&af); act("$p fades out of sight.",ch,obj,NULL,TO_ALL); return FULL_MANA; } /* character invisibility */ victim = (char_data *) vo; if ( IS_AFFECTED(victim, AFF_INVISIBLE )) { ch->printf( "They are already invisible.\r\n" ); return HALF_MANA; } act( "$n fades out of existence.", victim, NULL, NULL, TO_ROOM ); af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level + 12; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INVISIBLE; affect_to_char( victim, &af ); victim->printf( "You fade out of existence.\r\n" ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_know_alignment(int ,int ,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; if(IS_ICIMMORTAL(victim)){ ch->printf( "You really aren't sure about %s.\r\n", PERS(victim, ch)); return DOUBLE_MANA; }; switch (victim->tendency) { case -3: ch->printf( "%s is very chaotic ", PERS(victim, ch)); break; case -2: ch->printf( "%s is fairly chaotic ", PERS(victim, ch)); break; case -1: ch->printf( "%s has chaotic tendencies ", PERS(victim, ch)); break; case 0: ch->printf( "%s is balanced ", PERS(victim, ch)); break; case 1: ch->printf( "%s has lawful tendencies ", PERS(victim, ch)); break; case 2: ch->printf( "%s is quite lawful ", PERS(victim, ch)); break; case 3: ch->printf( "%s is extremely lawful ", PERS(victim, ch)); break; } switch (victim->alliance) { case -3: ch->printf( "and is completely aligned with evil.\r\n"); break; case -2: ch->printf( "with many attachments to the dark forces.\r\n"); break; case -1: ch->printf( "and some alliance with evil.\r\n"); break; case 0: ch->printf( "and indifferent.\r\n"); break; case 1: ch->printf( "with good tendencies.\r\n"); break; case 2: ch->printf( "and has definite attachments to good.\r\n"); break; case 3: ch->printf( "and a champion of the divine.\r\n"); break; } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_lightning_bolt(int sn,int level,char_data *ch,void *vo,int) { char_data *victim = (char_data *) vo; int dam; dam = dice(level,6); if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_locate_object( int , int level, char_data *ch, void *,int ) { char buf[MIL]; BUFFER *buffer; OBJ_DATA *obj; OBJ_DATA *in_obj; bool found; int number = 0, max_found; found = false; number = 0; max_found = IS_IMMORTAL(ch) ? 200 : 2 * level; buffer = new_buf(); for ( obj = object_list; obj != NULL; obj = obj->next ) { if ( !can_see_obj( ch, obj ) || !is_name( target_name, obj->name ) || IS_OBJ_STAT(obj,OBJEXTRA_NOLOCATE) || number_percent() > 2 * level || ch->level < obj->level) continue; found = true; number++; for ( in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj ); if ( in_obj->carried_by != NULL && can_see(ch,in_obj->carried_by)) { sprintf( buf, "one is carried by %s\r\n", PERS(in_obj->carried_by, ch) ); } else { if (IS_IMMORTAL(ch) && in_obj->in_room != NULL) sprintf( buf, "one is in %s [Room %d]\r\n",in_obj->in_room->name, in_obj->in_room->vnum); else sprintf( buf, "one is in %s\r\n", in_obj->in_room == NULL ? "somewhere" : in_obj->in_room->name ); } buf[0] = UPPER(buf[0]); add_buf(buffer,buf); if (number >= max_found) break; } if ( !found ) ch->printf( "Nothing like that in heaven or earth.\r\n" ); else ch->sendpage(buf_string(buffer)); free_buf(buffer); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_magic_missile( int sn, int level, char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; int dam; dam = level/4+2; if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_mass_healing(int , int level, char_data *ch, void *, int ) { char_data *gch; int heal_num, refresh_num; heal_num = gsn_heal; refresh_num = gsn_refresh; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ((IS_NPC(ch) && IS_NPC(gch)) || (!IS_NPC(ch) && !IS_NPC(gch))) { spell_heal(heal_num,level,ch,(void *) gch,TARGET_CHAR); spell_refresh(refresh_num,level,ch,(void *) gch,TARGET_CHAR); } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_mass_invis( int sn, int level, char_data *ch, void *, int ) { AFFECT_DATA af; char_data *gch; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( !is_same_group( gch, ch ) || IS_AFFECTED(gch, AFF_INVISIBLE) ) continue; act( "$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM ); gch->printf( "You slowly fade out of existence.\r\n" ); af.where = WHERE_AFFECTS; af.type = sn; af.level = level/2; af.duration = 24; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INVISIBLE; affect_to_char( gch, &af ); } ch->println( "Ok." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_null( int, int , char_data *ch, void *, int ) { ch->printf( "That's not a spell!\r\n" ); return NO_MANA; } /**************************************************************************/ SPRESULT spell_pass_door( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_PASS_DOOR) ) { if (victim == ch) ch->printf( "You are already out of phase.\r\n" ); else act("$N is already shifted out of phase.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = number_fuzzy( level / 4 ); af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_PASS_DOOR; affect_to_char( victim, &af ); act( "$n turns translucent.", victim, NULL, NULL, TO_ROOM ); victim->printf( "You turn translucent.\r\n" ); return FULL_MANA; } /**************************************************************************/ // RT plague spell, very nasty SPRESULT spell_plague( int sn, int level, char_data *ch, void *vo, int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if (saves_spell(level,victim,DAMTYPE(sn)) || (IS_NPC(victim) && IS_SET(victim->act,ACT_UNDEAD)) || HAS_CLASSFLAG(victim, CLASSFLAG_PLAGUE_IMMUNITY)) { if (ch == victim){ ch->printf( "You feel momentarily ill, but it passes.\r\n" ); }else{ act("$N seems to be unaffected.",ch,NULL,victim,TO_CHAR); } return FULL_MANA; } if ( IS_ICIMMORTAL(victim)){ act( "$n doesn't appear to be even slightly affected by your magic.", victim, NULL, NULL, TO_ROOM ); return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level * 3/4; af.duration = level; af.location = APPLY_ST; af.modifier = -10; af.bitvector = AFF_PLAGUE; affect_join(victim,&af); victim->printf( "You scream in agony as plague sores erupt from your skin.\r\n" ); act("$n screams in agony as plague sores erupt from $s skin.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_poison( int sn, int level, char_data *ch, void *vo, int target ) { char_data *victim; OBJ_DATA *obj; AFFECT_DATA af; if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if (obj->item_type == ITEM_FOOD || obj->item_type == ITEM_DRINK_CON) { obj->value[3] = 1; act("$p is infused with poisonous vapors.",ch,obj,NULL,TO_ALL); return FULL_MANA; } if (obj->item_type == ITEM_WEAPON) { if (IS_WEAPON_STAT(obj,WEAPON_FLAMING) || IS_WEAPON_STAT(obj,WEAPON_FROST) || IS_WEAPON_STAT(obj,WEAPON_VAMPIRIC) || IS_WEAPON_STAT(obj,WEAPON_SHOCKING) || IS_WEAPON_STAT(obj,WEAPON_HOLY)) { act("You can't seem to envenom $p.",ch,obj,NULL,TO_CHAR); return FULL_MANA; } if (IS_WEAPON_STAT(obj,WEAPON_POISON)) { act("$p is already envenomed.",ch,obj,NULL,TO_CHAR); return HALF_MANA; } af.where = WHERE_WEAPON; af.type = sn; af.level = level / 2; af.duration = level/8; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = WEAPON_POISON; affect_to_obj(obj,&af); act("$p is coated with deadly venom.",ch,obj,NULL,TO_ALL); return FULL_MANA; } act("You can't poison $p.",ch,obj,NULL,TO_CHAR); return NO_MANA; } victim = (char_data *) vo; if ( saves_spell( level, victim,DAMTYPE(sn)) || HAS_CLASSFLAG(victim, CLASSFLAG_POISON_IMMUNITY)) { act("$n turns slightly green, but it passes.",victim,NULL,NULL,TO_ROOM); victim->printf( "You feel momentarily ill, but it passes.\r\n" ); return FULL_MANA; } if ( IS_ICIMMORTAL(victim)){ act( "$n doesn't appear to be even slightly affected by your magic.", victim, NULL, NULL, TO_ROOM ); return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = (level/2); af.location = APPLY_ST; af.modifier = -4; af.bitvector = AFF_POISON; affect_join( victim, &af ); victim->printf( "You feel very sick.\r\n" ); act("$n looks very ill.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_protection_evil(int sn,int level,char_data *ch,void *vo, int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_PROTECT_EVIL) || IS_AFFECTED(victim, AFF_PROTECT_GOOD)) { if (victim == ch) ch->printf( "You are already protected.\r\n" ); else act("$N is already protected.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_SAVES; af.modifier = -1; af.bitvector = AFF_PROTECT_EVIL; affect_to_char( victim, &af ); victim->printf( "You feel holy and pure.\r\n" ); if ( ch != victim ) act("$N is protected from evil.",ch,NULL,victim,TO_CHAR); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_protection_good(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_PROTECT_GOOD) || IS_AFFECTED(victim, AFF_PROTECT_EVIL)) { if (victim == ch) ch->printf( "You are already protected.\r\n" ); else act("$N is already protected.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_SAVES; af.modifier = -1; af.bitvector = AFF_PROTECT_GOOD; affect_to_char( victim, &af ); victim->printf( "You feel aligned with darkness.\r\n" ); if ( ch != victim ) act("$N is protected from good.",ch,NULL,victim,TO_CHAR); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_ray_of_truth (int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam; if (IS_EVIL(ch) ) { victim = ch; ch->printf( "The energy explodes inside you!\r\n" ); } if (victim != ch) { act("$n raises $s hand, and a blinding ray of light shoots forth!",ch,NULL,NULL,TO_ROOM); ch->printf( "You raise your hand and a blinding ray of light shoots forth!\r\n" ); } if (IS_GOOD(victim)) { act("$n seems unharmed by the light.",victim,NULL,victim,TO_ROOM); victim->printf( "The light seems powerless to affect you.\r\n" ); return FULL_MANA; } dam = dice( level, 12 ) / abs(4+victim->alliance); if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); spell_blindness(gsn_blindness, 3 * level / 4, ch, (void *) victim,TARGET_CHAR); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_recharge( int , int level, char_data *ch, void *vo,int ) { OBJ_DATA *obj = (OBJ_DATA *) vo; int chance, percent; if (obj->item_type != ITEM_WAND && obj->item_type != ITEM_STAFF) { ch->printf( "That item does not carry charges.\r\n" ); return NO_MANA; } if (obj->value[3] >= 3 * level / 2) { ch->printf( "Your skills are not great enough for that.\r\n" ); return FULL_MANA; } if (obj->value[1] == 0) { ch->printf( "That item has already been recharged once.\r\n" ); return HALF_MANA; } chance = 40 + 2 * level; chance -= obj->value[3]; /* harder to do high-level spells */ chance -= (obj->value[1] - obj->value[2]) * (obj->value[1] - obj->value[2]); chance = UMAX(level/2,chance); percent = number_percent(); if (percent < chance / 2) { act("$p glows softly.",ch,obj,NULL,TO_CHAR); act("$p glows softly.",ch,obj,NULL,TO_ROOM); obj->value[2] = UMAX(obj->value[1],obj->value[2]); obj->value[1] = 0; return FULL_MANA; } else if (percent <= chance) { int chargeback,chargemax; act("$p glows softly.",ch,obj,NULL,TO_CHAR); act("$p glows softly.",ch,obj,NULL,TO_CHAR); chargemax = obj->value[1] - obj->value[2]; if (chargemax > 0) chargeback = UMAX(1,chargemax * percent / 100); else chargeback = 0; obj->value[2] += chargeback; obj->value[1] = 0; return FULL_MANA; } else if (percent <= UMIN(95, 3 * chance / 2)) { ch->printf( "Nothing seemed to happen.\r\n" ); if (obj->value[1] > 1) obj->value[1]--; return FULL_MANA; } else /* whoops! */ { act("$p glows brightly and explodes!",ch,obj,NULL,TO_CHAR); act("$p glows brightly and explodes!",ch,obj,NULL,TO_ROOM); extract_obj(obj); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_refresh( int , int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; victim->move = UMIN( victim->move + level, victim->max_move ); if(!IS_NPC(victim) && victim->pcdata->tired!=-1) { victim->pcdata->tired-=level/25+2; if(victim->pcdata->tired<0) victim->pcdata->tired=0; } if (victim->max_move == victim->move) victim->printf( "You feel fully refreshed!\r\n" ); else victim->printf( "You feel less tired.\r\n" ); if ( ch != victim ) ch->println( "Ok." ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_remove_curse( int , int level, char_data *ch, void *vo,int target) { char_data *victim; OBJ_DATA *obj; bool found = false; // do object cases first if (target == TARGET_OBJ) { obj = (OBJ_DATA *) vo; if(obj==NULL) return NO_MANA; if (IS_OBJ_STAT(obj,OBJEXTRA_NODROP) || IS_OBJ_STAT(obj,OBJEXTRA_NOREMOVE)) { if (!IS_OBJ_STAT(obj,OBJEXTRA_NOUNCURSE) && !saves_dispel(level *2,obj->level,0)) { REMOVE_BIT(obj->extra_flags,OBJEXTRA_NODROP); REMOVE_BIT(obj->extra_flags,OBJEXTRA_NOREMOVE); act("$p glows blue.",ch,obj,NULL,TO_ALL); return FULL_MANA; } act("The curse on $p is beyond your power.",ch,obj,NULL,TO_CHAR); return FULL_MANA; } act("$p is not cursed.",ch,obj,NULL,TO_CHAR); return HALF_MANA; } /* characters */ victim = (char_data *) vo; if (!is_affected(victim, gsn_curse) || check_dispel(level,victim,gsn_curse)) { victim->printf( "You feel better.\r\n" ); act("$n looks more relaxed.",victim,NULL,NULL,TO_ROOM); for (obj = victim->carrying; (obj != NULL && !found); obj = obj->next_content) { if ((IS_OBJ_STAT(obj,OBJEXTRA_NODROP) || IS_OBJ_STAT(obj,OBJEXTRA_NOREMOVE)) && !IS_OBJ_STAT(obj,OBJEXTRA_NOUNCURSE)) { // attempt to remove curse if (!saves_dispel(IS_HEALER(ch)?level*3:level/2,obj->level*3,0)) { found = true; REMOVE_BIT(obj->extra_flags,OBJEXTRA_NODROP); REMOVE_BIT(obj->extra_flags,OBJEXTRA_NOREMOVE); act("Your $p glows blue.",victim,obj,NULL,TO_CHAR); act("$n's $p glows blue.",victim,obj,NULL,TO_ROOM); } } } } else { ch->printf( "It doesn't appear your magic has had any affect.\r\n" ); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_sanctuary( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_SANCTUARY )) { if (victim == ch) ch->printf( "You are already in sanctuary.\r\n" ); else act("$N is already in sanctuary.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; if ( IS_IMMORTAL( ch )) af.duration = level / 6; else af.duration = 1 + level / 12; 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 ); victim->printf( "You are surrounded by a white aura.\r\n" ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_shield( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) ) { if (victim == ch) ch->printf( "You are already shielded from harm.\r\n" ); else act("$N is already protected by a shield.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if ( is_affected( victim, gsn_oak_shield )) { if (victim == ch) ch->printf( "You are already protected by a shielding spell.\r\n" ); else act("$N is already protected by a shielding spell.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = 8 + level; 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 ); victim->printf( "You are surrounded by a force shield.\r\n" ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_shocking_grasp(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; int dam; dam = dice(level/4,2)+20; if ( saves_spell( level, victim,DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn),true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_sleep( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( IS_SET( victim->imm_flags, IMM_SLEEP ) || IS_ICIMMORTAL(victim)){ act( "$n doesn't appear to be even slightly affected by your magic.", victim, NULL, NULL, TO_ROOM ); return FULL_MANA; } if ( IS_AFFECTED(victim, AFF_SLEEP) || ( IS_NPC(victim) && IS_SET(victim->act,ACT_UNDEAD)) || ( level + 2) < victim->level ) { ch->println( "You failed." ); return FULL_MANA; } if(saves_spell( level-4, victim,DAMTYPE(sn)) ) { ch->println( "You failed." ); // stop cheaters that panic logging out straight away if (!IS_NPC(victim) && victim!=ch) { victim->pknoquit=UMAX(victim->pknoquit,2); } if (!IS_NPC(ch) && !IS_NPC(victim) && victim!=ch) { ch->pksafe=0; ch->pknorecall= UMAX(ch->pknorecall,2); ch->pknoquit = UMAX(ch->pknorecall,7); } return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = number_fuzzy(level); if(IS_NPC(victim)) af.duration = 4 + (level/2); else af.duration = 2 + (level/9); // duration reduced af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; affect_join( victim, &af ); if ( IS_AWAKE(victim)) { victim->printf( "You feel very sleepy ..... zzzzzz.\r\n" ); act( "$n goes to sleep.", victim, NULL, NULL, TO_ROOM ); victim->position = POS_SLEEPING; // stop those who are slept from logging out if (!IS_NPC(victim) && victim!=ch) { ch->pksafe=0; ch->pknorecall= UMAX(ch->pknorecall,2); ch->pknoquit = UMAX(ch->pknorecall,7); if (!IS_NPC(ch)) { victim->pknoquit=UMAX(victim->pknoquit,10); } } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_slow( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) || IS_AFFECTED(victim,AFF_SLOW)) { if (victim == ch) ch->printf( "You can't move any slower!\r\n" ); else act("$N can't get any slower than that.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if (saves_spell(level,victim,DAMTYPE(sn)) || IS_SET(victim->imm_flags,IMM_MAGIC)) { if (victim != ch) ch->printf( "Nothing seemed to happen.\r\n" ); victim->printf( "You feel momentarily lethargic.\r\n" ); return FULL_MANA; } if (IS_AFFECTED(victim,AFF_HASTE)) { if (!check_dispel(level,victim, gsn_haste )) { if (victim != ch) { ch->println("Spell failed."); return FULL_MANA; } } act("$n is moving less quickly.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level/2; af.location = APPLY_QU; af.modifier = -1 - level/5; af.bitvector = AFF_SLOW; affect_to_char( victim, &af ); victim->printf( "You feel yourself slowing d o w n...\r\n" ); act("$n starts to move in slow motion.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_stone_skin( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if(check_skin( ch, victim )) return HALF_MANA; af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level; 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 ); victim->printf( "Your skin turns to stone.\r\n" ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_summon( int sn, int level, char_data *ch, void *,int ) { char_data *victim; if ( ( victim = get_char_icworld( ch, target_name ) ) == NULL || victim == ch || victim->in_room == NULL || IS_SET(ch->in_room->room_flags, ROOM_SAFE) || IS_SET(victim->in_room->room_flags, ROOM_SAFE) || IS_SET(victim->in_room->room_flags, ROOM_PRIVATE) || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) || IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(victim->in_room->room_flags, ROOM_NOSCRY) || IS_SET(victim->in_room->area->area_flags, AREA_NOSCRY) || IS_SET(ch->in_room->area->area_flags, AREA_NOSUMMONINTO) || (IS_NPC(victim) && IS_SET(victim->act,ACT_AGGRESSIVE)) || victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL) || victim->fighting != NULL || (IS_NPC(victim) && IS_SET(victim->imm_flags,IMM_SUMMON)) || (IS_NPC(victim) && victim->pIndexData->pShop != NULL) || (!IS_NPC(victim) && IS_SET(victim->act,PLR_NOSUMMON)) || (IS_NPC(victim) && saves_spell( level, victim,DAMTYPE(sn))) || (IS_SET(victim->form, FORM_MOUNTABLE) // can't summon mounts to inside && IS_SET(ch->in_room->room_flags, ROOM_INDOORS)) || (IS_NPC(victim) && IS_SET(victim->act,ACT_AGGRESSIVE)) ) { ch->println( "You failed." ); return FULL_MANA; } // no charming in aggy mobs if(IS_NPC(victim)){ REMOVE_BIT(victim->affected_by, ACT_AGGRESSIVE); } act( "$n disappears suddenly.", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, ch->in_room ); act( "$n arrives suddenly.", victim, NULL, NULL, TO_ROOM ); act( "$n has summoned you!", ch, NULL, victim, TO_VICT ); do_look( victim, "auto" ); /* * If someone is following the char, these triggers get activated * for the followers before the char, but it's safer this way... */ if ( IS_NPC( victim) && HAS_TRIGGER( victim, TRIG_ENTRY ) ) mp_percent_trigger( victim, NULL, NULL, NULL, TRIG_ENTRY ); if ( !IS_NPC( victim )) mp_greet_trigger( victim ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_teleport( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; ROOM_INDEX_DATA *pRoomIndex; if ( victim->in_room == NULL || IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL) || ( victim != ch && IS_SET(victim->imm_flags,IMM_SUMMON)) || ( !IS_NPC(ch) && victim->fighting != NULL ) || ( victim != ch && ( saves_spell( level - 5, victim,DAMTYPE(sn))))) { ch->println( "You failed." ); return FULL_MANA; } pRoomIndex = get_random_room(victim); if (victim != ch) victim->printf( "You have been teleported!\r\n" ); act( "$n vanishes!", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, pRoomIndex ); act( "$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM ); do_look( victim, "auto" ); /* * If someone is following the char, these triggers get activated * for the followers before the char, but it's safer this way... */ if ( IS_NPC( victim) && HAS_TRIGGER( victim, TRIG_ENTRY )) mp_percent_trigger( victim, NULL, NULL, NULL, TRIG_ENTRY ); if ( !IS_NPC( victim )) mp_greet_trigger( victim ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_ventriloquate( int sn, int level, char_data *ch,void *,int ) { char buf1[MSL]; char buf2[MSL]; char speaker[MIL]; char_data *vch; target_name = one_argument( target_name, speaker ); sprintf( buf1, "%s says '%s'.", speaker, target_name ); sprintf( buf2, "Someone makes %s say '%s'.", speaker, target_name ); buf1[0] = UPPER(buf1[0]); for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room ) { if (IS_AWAKE(vch) && !is_affected(vch, gsn_deafness)) { if ( !is_name( speaker, vch->name )) vch->printf( "%s\r\n", saves_spell(level,vch,DAMTYPE(sn)) ? buf2 : buf1 ); } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_weaken( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; AFFECT_DATA af; if( is_affected( victim, gsn_giant_strength )) if( check_dispel( level, victim, gsn_giant_strength )) { act( "Your magic unravels a spell on $N.", ch, NULL, victim, TO_CHAR ); return FULL_MANA; } else { ch->println( "You failed." ); return FULL_MANA; } if ( is_affected( victim, sn ) ) { act("$N already looks tired and weak.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } if (saves_spell( level, victim,DAMTYPE(sn)) ) { ch->printf( "Your spell doesnt appear to have much affect.\r\n" ); return FULL_MANA; } af.where = WHERE_AFFECTS; af.type = sn; af.level = level; af.duration = level / 2; af.location = APPLY_ST; af.modifier = -1 * (level / 3); af.bitvector = AFF_WEAKEN; affect_to_char( victim, &af ); victim->printf( "You feel your strength slip away.\r\n" ); act("$n looks tired and weak.",victim,NULL,NULL,TO_ROOM); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_word_of_recall( int, int, char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; ROOM_INDEX_DATA *location = NULL; if(IS_NPC(victim)){ return NO_MANA; } // class recall spot first, then race // recall_vnum = pc_race_table[ch->race].recall_room; if ( class_table[victim->clss].recall) { location = get_room_index( class_table[victim->clss].recall ); // Class } else // Class recall room non-existant, check race room { location = get_room_index( race_table[victim->race]->recall_room); // Race } if ( location == NULL ) { victim->println( "You are completely lost." ); return NO_MANA; } if (IS_SET(victim->in_room->room_flags,ROOM_NO_RECALL) || IS_SET(victim->in_room->room_flags, ROOM_ANTIMAGIC) || IS_AFFECTED(victim,AFF_CURSE)) { victim->println( "Spell failed." ); return FULL_MANA; } if (victim->fighting != NULL) stop_fighting(victim,true); // Stop negative moves characters from defrauding the system if (ch->move>0 && IS_IC(ch)) ch->move /= 2; act("$n disappears.",victim,NULL,NULL,TO_ROOM); char_from_room(victim); char_to_room(victim,location); act("$n appears in the room.",victim,NULL,NULL,TO_ROOM); do_look(victim,"auto"); return FULL_MANA; } /**************************************************************************/ // NPC spells. SPRESULT spell_acid_breath( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; int dam,hp_dam,dice_dam,hpch; act("$n spits acid at $N.",ch,NULL,victim,TO_NOTVICT); act("$n spits a stream of corrosive acid at you.",ch,NULL,victim,TO_VICT); act("You spit acid at $N.",ch,NULL,victim,TO_CHAR); hpch = UMAX(12,ch->hit); hp_dam = number_range(hpch/11 + 1, hpch/6); dice_dam = dice(level,16); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); if (saves_spell(level,victim,DAMTYPE(sn))) { acid_effect(victim,level/2,dam/4,TARGET_CHAR); damage_spell(ch,victim,dam/2,sn,DAMTYPE(sn),true); } else { acid_effect(victim,level,dam,TARGET_CHAR); damage_spell(ch,victim,dam,sn,DAMTYPE(sn),true); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_fire_breath( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; char_data *vch, *vch_next; int dam,hp_dam,dice_dam; int hpch; act("$n breathes forth a cone of fire.",ch,NULL,victim,TO_NOTVICT); act("$n breathes a cone of hot fire over you!",ch,NULL,victim,TO_VICT); act("You breath forth a cone of fire.",ch,NULL,NULL,TO_CHAR); hpch = UMAX( 10, ch->hit ); hp_dam = number_range( hpch/9+1, hpch/5 ); dice_dam = dice(level,20); dam = UMAX(hp_dam + dice_dam /10, dice_dam + hp_dam / 10); fire_effect(victim->in_room,level,dam/2,TARGET_ROOM); for (vch = victim->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch,vch,true) || (IS_NPC(vch) && IS_NPC(ch) && (ch->fighting != vch || vch->fighting != ch))) continue; if (vch == victim) /* full damage */ { if (saves_spell(level,vch,DAMTYPE(sn))) { fire_effect(vch,level/2,dam/4,TARGET_CHAR); damage_spell(ch,vch,dam/2,sn,DAMTYPE(sn),true); } else { fire_effect(vch,level,dam,TARGET_CHAR); damage_spell(ch,vch,dam,sn,DAMTYPE(sn),true); } } else /* partial damage */ { if (saves_spell(level - 2,vch,DAMTYPE(sn))) { fire_effect(vch,level/4,dam/8,TARGET_CHAR); damage_spell(ch,vch,dam/4,sn,DAMTYPE(sn),true); } else { fire_effect(vch,level/2,dam/4,TARGET_CHAR); damage_spell(ch,vch,dam/2,sn,DAMTYPE(sn),true); } } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_frost_breath( int sn, int level, char_data *ch, void *vo,int ) { char_data *victim = (char_data *) vo; char_data *vch, *vch_next; int dam,hp_dam,dice_dam, hpch; act("$n breathes out a freezing cone of frost!",ch,NULL,victim,TO_NOTVICT); act("$n breathes a freezing cone of frost over you!",ch,NULL,victim,TO_VICT); act("You breath out a cone of frost.",ch,NULL,NULL,TO_CHAR); hpch = UMAX(12,ch->hit); hp_dam = number_range(hpch/11 + 1, hpch/6); dice_dam = dice(level,16); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); cold_effect(victim->in_room,level,dam/2,TARGET_ROOM); for (vch = victim->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch,vch,true) || (IS_NPC(vch) && IS_NPC(ch) && (ch->fighting != vch || vch->fighting != ch))) continue; if (vch == victim) /* full damage */ { if (saves_spell(level,vch,DAMTYPE(sn))) { cold_effect(vch,level/2,dam/4,TARGET_CHAR); damage_spell(ch,vch,dam/2,sn,DAMTYPE(sn),true); } else { cold_effect(vch,level,dam,TARGET_CHAR); damage_spell(ch,vch,dam,sn,DAMTYPE(sn),true); } } else { if (saves_spell(level - 2,vch,DAMTYPE(sn))) { cold_effect(vch,level/4,dam/8,TARGET_CHAR); damage_spell(ch,vch,dam/4,sn,DAMTYPE(sn),true); } else { cold_effect(vch,level/2,dam/4,TARGET_CHAR); damage_spell(ch,vch,dam/2,sn,DAMTYPE(sn),true); } } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_gas_breath( int sn, int level, char_data *ch, void *,int ) { char_data *vch; char_data *vch_next; int dam,hp_dam,dice_dam,hpch; act("$n breathes out a cloud of hot poisonous gas!",ch,NULL,NULL,TO_ROOM); act("You breath out a cloud of hot poisonous gas.",ch,NULL,NULL,TO_CHAR); hpch = UMAX(16,ch->hit); hp_dam = number_range(hpch/15+1,8); dice_dam = dice(level,12); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); poison_effect(ch->in_room,level,dam,TARGET_ROOM); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if (is_safe_spell(ch,vch,true) || (IS_NPC(ch) && IS_NPC(vch) && (ch->fighting == vch || vch->fighting == ch))) continue; if (check_immune(vch,DAMTYPE(sn))==IS_IMMUNE || HAS_CLASSFLAG(vch, CLASSFLAG_POISON_IMMUNITY)) { vch->wrapln("The heat of the gas burns at your skin." " You feel momentarily ill, but it passes."); damage_spell(ch,vch,dam/4,sn,DAMTYPE(sn),true); } else if (saves_spell(level,vch,DAMTYPE(sn))) { poison_effect(vch,level/2,dam/4,TARGET_CHAR); damage_spell(ch,vch,dam/2,sn,DAMTYPE(sn),true); } else { poison_effect(vch,level,dam,TARGET_CHAR); damage_spell(ch,vch,dam,sn,DAMTYPE(sn),true); } } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_lightning_breath(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; int dam,hp_dam,dice_dam,hpch; act("$n breathes a bolt of lightning at $N.",ch,NULL,victim,TO_NOTVICT); act("$n breathes a bolt of lightning at you!",ch,NULL,victim,TO_VICT); act("You breathe a bolt of lightning at $N.",ch,NULL,victim,TO_CHAR); hpch = UMAX(10,ch->hit); hp_dam = number_range(hpch/9+1,hpch/5); dice_dam = dice(level,20); dam = UMAX(hp_dam + dice_dam/10,dice_dam + hp_dam/10); if (saves_spell(level,victim,DAMTYPE(sn))) { shock_effect(victim,level/2,dam/4,TARGET_CHAR); damage_spell(ch,victim,dam/2,sn,DAMTYPE(sn),true); } else { shock_effect(victim,level,dam,TARGET_CHAR); damage_spell(ch,victim,dam,sn,DAMTYPE(sn),true); } return FULL_MANA; } /**************************************************************************/ // Spells for mega1.are from Glop/Erkenbrand. SPRESULT spell_general_purpose(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; int dam; dam = number_range( 25, 100 ); if ( saves_spell( level, victim, DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn) ,true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_high_explosive(int sn,int level,char_data *ch,void *vo,int ) { char_data *victim = (char_data *) vo; int dam; dam = number_range( 30, 120 ); if ( saves_spell( level, victim, DAMTYPE(sn)) ) dam /= 2; damage_spell( ch, victim, dam, sn, DAMTYPE(sn) ,true); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_farsight( int , int , char_data *ch, void *,int ) { if (IS_AFFECTED(ch,AFF_BLIND)) { ch->printf( "Maybe it would help if you could see?\r\n" ); return HALF_MANA; } do_far_scan(ch,target_name); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_portal( int sn, int level, char_data *ch, void *,int ) { char_data *victim; OBJ_DATA *portal, *stone; if ((victim = get_char_world( ch, target_name ) ) == NULL || victim == ch || victim->in_room == NULL || !can_see_room(ch,victim->in_room) || IS_SET(victim->in_room->room_flags, ROOM_SAFE) || IS_SET(victim->in_room->room_flags, ROOM_PRIVATE) || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) || IS_SET(victim->in_room->room_flags, ROOM_ANTIMAGIC) || IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL) || IS_SET(victim->in_room->area->area_flags, AREA_NOPORTALINTO) || IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= LEVEL_HERO) /* NOT trust */ || (IS_NPC(victim) && saves_spell( level, victim,DAMTYPE(sn)) ) || (is_clan(victim) && !is_same_clan(ch,victim))) { ch->println( "You failed." ); return FULL_MANA; } stone = get_eq_char(ch,WEAR_HOLD); if (!IS_IMMORTAL(ch) && (stone == NULL || stone->item_type != ITEM_WARP_STONE)) { ch->println( "You lack the proper component for this spell." ); return NO_MANA; } if (stone != NULL && stone->item_type == ITEM_WARP_STONE) { act("You draw upon the power of $p.",ch,stone,NULL,TO_CHAR); act("It flares brightly and vanishes!",ch,stone,NULL,TO_CHAR); extract_obj(stone); } portal = create_object(get_obj_index(OBJ_VNUM_PORTAL)); portal->timer = 2 + level / 25; portal->value[3] = victim->in_room->vnum; // portals aren't opaque - Kal August 98 SET_BIT(portal->value[2],GATE_OPAQUE); obj_to_room(portal,ch->in_room); act("$p rises up from the ground.",ch,portal,NULL,TO_ROOM); act("$p rises up before you.",ch,portal,NULL,TO_CHAR); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_nexus( int sn, int level, char_data *ch, void *, int) { char_data *victim; OBJ_DATA *portal, *stone; ROOM_INDEX_DATA *from_room; ROOM_INDEX_DATA *to_room=NULL; from_room = ch->in_room; if ((victim = get_char_world( ch, target_name ) ) == NULL || victim == ch || (to_room = victim->in_room) == NULL || !can_see_room(ch,to_room) || !can_see_room(ch,from_room) || IS_SET(from_room->room_flags,ROOM_SAFE) || IS_SET(from_room->room_flags,ROOM_NO_RECALL) || IS_SET(to_room->room_flags, ROOM_SAFE) || IS_SET(to_room->room_flags, ROOM_ANTIMAGIC) || IS_SET(to_room->room_flags, ROOM_PRIVATE) || IS_SET(to_room->room_flags, ROOM_SOLITARY) || IS_SET(to_room->room_flags, ROOM_NO_RECALL) || IS_SET(to_room->area->area_flags, AREA_NOPORTALINTO) || victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= LEVEL_HERO) /* NOT trust */ || (saves_spell( level, victim,DAMTYPE(sn)) ) ) { ch->println( "You failed." ); return FULL_MANA; } stone = get_eq_char(ch,WEAR_HOLD); if (!IS_IMMORTAL(ch) && (stone == NULL || stone->item_type != ITEM_WARP_STONE)) { ch->println( "You lack the proper component for this spell." ); return NO_MANA; } if (stone != NULL && stone->item_type == ITEM_WARP_STONE) { act("You draw upon the power of $p.",ch,stone,NULL,TO_CHAR); act("It flares brightly and vanishes!",ch,stone,NULL,TO_CHAR); extract_obj(stone); } // portal one portal = create_object(get_obj_index(OBJ_VNUM_PORTAL)); portal->timer = 1 + level / 10; portal->value[3] = to_room->vnum; obj_to_room(portal,from_room); act("$p rises up from the ground.",ch,portal,NULL,TO_ROOM); act("$p rises up before you.",ch,portal,NULL,TO_CHAR); // no second portal if rooms are the same if (to_room == from_room) return HALF_MANA; // portal two portal = create_object(get_obj_index(OBJ_VNUM_PORTAL)); portal->timer = 1 + level/10; portal->value[3] = from_room->vnum; obj_to_room(portal,to_room); if (to_room->people != NULL) { act("$p rises up from the ground.",to_room->people,portal,NULL,TO_ROOM); act("$p rises up from the ground.",to_room->people,portal,NULL,TO_CHAR); } return FULL_MANA; } /**************************************************************************/ SPRESULT spell_mute( int sn, int level, char_data *ch, void *vo, int) { char_data* victim = (char_data*) vo; AFFECT_DATA af; if ( IS_AFFECTED2(victim, AFF2_MUTE) ) { ch->printlnf("%s is already silenced.", PERS(victim, ch)); return HALF_MANA; } if ( saves_spell(level,victim,DAMTYPE(sn)) ) { ch->println("You failed."); return HALF_MANA; } af.where = WHERE_AFFECTS2; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF2_MUTE; affect_to_char( victim, &af ); act( "You have silenced $N!", ch, NULL, victim, TO_CHAR ); act( "$n has silenced you!", ch, NULL, victim, TO_VICT ); act( "$n has silenced $N!", ch, NULL, victim, TO_NOTVICT ); return FULL_MANA; } /**************************************************************************/ SPRESULT spell_possession( int sn, int level, char_data *ch, void *vo, int) { char_data* victim = (char_data*) vo; AFFECT_DATA af; if ( IS_AFFECTED2(victim, AFF2_POSSESSION) ) { if (victim == ch){ ch->println("You are already inhabited by a spirit."); return NO_MANA; }else{ act("$N is already inhabited by a spirit.",ch,NULL,victim,TO_CHAR); return HALF_MANA; } } af.where = WHERE_AFFECTS2; af.type = sn; af.level = level; af.duration = level / 6; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF2_POSSESSION; affect_to_char( victim, &af ); act( "$n looks stronger and mightier as a spirit of a dead warrior inhabits his body.", victim, NULL, NULL, TO_ROOM ); victim->println("You suddenly gain the insights of a warrior of old."); return FULL_MANA; } /**************************************************************************/