/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Envy Diku Mud, you must comply with * * the original Diku license in 'license.doc', the Merc license in * * 'license.txt', as well as the Envy license in 'license.nvy'. * * In particular, you may not remove either of these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * * * * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * * * * Code Adapted and Improved by Abandoned Realms Mud * * and Aabahran: The Forsaken Lands Mud by Virigoth * * * * Continued Production of this code is available at www.flcodebase.com * ***************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "cabal.h" #include "magic.h" #include "recycle.h" #include "interp.h" #include "jail.h" const struct warlord_type warlord_table[] = { { "cure blindness" }, { "cure disease" }, { "cure poison" }, { "know alignment" }, { "refresh" }, { "remove curse" }, { "word of recall" }, { "cancellation" }, { "doppelganger" }, { "slow" }, { NULL } }; char *target_name; extern bool is_sheathed(CHAR_DATA* ch); bool check_spellblast( CHAR_DATA* ch, CHAR_DATA* victim, int sn, int cost, int level ); //blademaster snakespeed check for spell counter, ch is caster, victim the blademaster bool snakespeedCheck(CHAR_DATA* ch, CHAR_DATA* victim){ OBJ_DATA* obj; int sn = skill_lookup("snakespeed"); int ini_dam, dam; if (ch == NULL || victim == NULL) return FALSE; ini_dam = dam = dice(6, 6) + number_range(victim->level, 2 * victim->level); if (victim->fighting != NULL) return FALSE; else if (IS_IMMORTAL(ch)) return FALSE; else if (IS_NPC(ch) && ch->hit < ch->max_hit / 2) return FALSE; else if (IS_NPC(ch) && ch->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD) return FALSE; else if (IS_NPC(ch) && ch->pIndexData->vnum == MOB_VNUM_HOUND) return FALSE; else if ( (obj = has_twohanded(victim)) == NULL) return FALSE; else if (!can_see(victim, ch) && !is_affected(victim, gsn_battlefocus)){ return FALSE; } else if (!monk_good(victim, WEAR_HANDS)) return FALSE; else if (number_percent() > get_skill(victim, sn)){ check_improve(victim, sn, FALSE, 10); return FALSE; } else if (victim->position < POS_STANDING && victim->position > POS_STUNNED){ const int gsn_vigil = skill_lookup("vigil"); //blademaster vigil if (!IS_AFFECTED(victim, AFF_SLEEP) && number_percent() < get_skill(victim, gsn_vigil)){ send_to_char("You sense an impeding attack!\n\r", victim); act("$n springs up suddenly $s weapons flashing in a deadly arc!", victim, NULL, NULL, TO_ROOM); check_improve(victim, gsn_vigil, TRUE, 30); dam = 3 * dam / 2; do_wake(victim, ""); } else return FALSE; } check_improve(victim, sn, TRUE, 5); act("With the speed of a serpent you strike and interrupt $N!",victim,NULL,ch,TO_CHAR); act("With the speed of a serpent $n strikes and interrupts $N!",victim,NULL,ch,TO_NOTVICT); act("With the speed of a serpent $n strikes and interrupts you!",victim,NULL,ch,TO_VICT); damage(victim, ch, dam, sn, attack_table[obj->value[3]].damage, TRUE ); return TRUE; } int PRESPELL_CHECK(CHAR_DATA* ch, char* argument, int* sn, int* cost, int* lag, int* lvl) { //includes all updates before mana and lag is set. CHAR_DATA* vch = ch; AFFECT_DATA* paf; AFFECT_DATA* paf_next; int fSuccess = TRUE; int result = 0; if (skill_table[*sn].spell_type != SPELL_MALEDICTIVE){ int old_lvl = *lvl; run_effect_update(ch, sn, lvl, gen_mana_charge, cost, lag, TRUE, EFF_UPDATE_PRESPELL); /* non afflictive spells do not have their levels changed */ if (skill_table[*sn].spell_type != SPELL_AFFLICTIVE) *lvl = old_lvl; } for (paf = vch->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; //we only run the update once per effect. if (paf_next != NULL) { if (paf->type == paf_next->type) { continue; } } //SPECIAL GENS HERE if (paf->type == gen_mana_charge) { continue; } if (IS_GEN(paf->type)) { if ((result = run_effect_update(ch, sn, lvl, paf->type, cost, lag, TRUE, EFF_UPDATE_PRESPELL)) != TRUE) { if (result == -1) { return -1; } else { fSuccess = result; } } } } *lag = *lag * (100 + ch->aff_mod[MOD_WAIT_STATE]) / 100; return fSuccess; }//and PRESPELL int POSTSPELL_CHECK(CHAR_DATA* ch, char* argument, int sn, int cost, int lag) { CHAR_DATA* vch = ch; AFFECT_DATA* paf; AFFECT_DATA* paf_next; int fSuccess = TRUE; int result = 0; run_effect_update(ch, NULL, NULL, gen_mana_charge, &cost, &lag, TRUE, EFF_UPDATE_POSTSPELL); for (paf = vch->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; //we only run the update once per effect. if (paf_next != NULL) { if (paf->type == paf_next->type) { continue; } } //SPECIAL GENS HERE if (paf->type == gen_mana_charge) { continue; } if (IS_GEN(paf->type)) { if ((result = run_effect_update(ch, &sn, NULL, paf->type, &cost, &lag, TRUE, EFF_UPDATE_POSTSPELL)) != TRUE) { if (result == -1) { return -1; } else { fSuccess = result; } } } } return fSuccess; }//end post spell /* Viri: Calculates the amount of exp. gained for casting a spell */ int spell_expgain(int sn, int skill, int level){ int min = skill_table[sn].min_mana / 8; int max = skill_table[sn].min_mana / 4; int val = 0; if (skill < 2 || skill > 99 || level > 38) return 0; min = UMAX(1, min); max = UMAX(1, max); val = number_range(min, max); /* adjust for level */ val = val / UMAX(1, (level - 30) / 2); return val; } void m_yell( CHAR_DATA *ch, CHAR_DATA *vch, bool force ) { char buf[MSL]; if (((ch->fighting != vch && vch->fighting != ch && ch != vch) || force) && (!IS_NPC(ch) || ch->master != NULL )) { if (!IS_NPC(vch)) { sprintf(buf,"`&%s attacked %s at %d``", ch->name, vch->name,ch->in_room->vnum); log_string(buf); wiznet(buf,NULL,NULL,WIZ_FIGHTING,0,0); continuum(vch, CONTINUUM_ATTACK); /* MURDER CRIME CHECK */ if (ch->in_room && is_crime(ch->in_room, CRIME_MURDER, vch)){ set_crime(ch, vch, ch->in_room->area, CRIME_MURDER); } /* ATTACKING JUSTICE MOBS IN LAWFUL AREA IS ALWYAS A CRIME */ else if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_JUSTICE) && IS_AREA(ch->in_room->area, AREA_LAWFUL)){ set_crime(ch, vch, ch->in_room->area, CRIME_MURDER); } if (!can_see(vch, ch)) sprintf(buf,"Help someone is attacking me!"); else sprintf(buf, "Die! %s, you sorcerous dog!",PERS(ch,vch)); j_yell(vch, buf); /* CONTINENCY */ check_contingency(ch, NULL, CONT_ATTACK); check_contingency(vch, NULL, CONT_ATTACKED); }//END PC else { bool fCrime = FALSE; /* ASSAULT CRIME CHECK */ if (ch->in_room && is_crime(ch->in_room, CRIME_ASSAULT, vch)){ fCrime = TRUE; set_crime(ch, vch, ch->in_room->area, CRIME_ASSAULT); } /* ATTACKING JUSTICE MOBS IN LAWFUL AREA IS ALWYAS A CRIME */ else if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_JUSTICE) && IS_AREA(ch->in_room->area, AREA_LAWFUL)){ set_crime(ch, vch, ch->in_room->area, CRIME_MURDER); fCrime = TRUE; } if (IS_SET(vch->off_flags,GUILD_GUARD) && vch->pCabal && IS_CABAL(vch->pCabal, CABAL_JUSTICE)){ sprintf(buf, "%s: Alert! The jail is being attacked!", ch->in_room->area->name); cabal_echo_flag( CABAL_JUSTICE, buf ); sprintf(buf, "Alert! The jail is being attacked by %s!",PERS(ch,vch)); } else if (IS_SET(vch->off_flags,GUILD_GUARD)) sprintf(buf, "Alert! The guild is being attacked by %s!",PERS(ch,vch)); else if (!can_see(vch, ch)) sprintf(buf,"Help someone is attacking me!"); else sprintf(buf, "Die! %s, you sorcerous dog!",PERS(ch,vch)); if (vch->hit > 0 && (fCrime || IS_SET(vch->off_flags,GUILD_GUARD)) ) { REMOVE_BIT(vch->comm,COMM_NOYELL); REMOVE_BIT(vch->comm,COMM_NOCHANNELS); j_yell(vch, buf); SET_BIT(vch->comm,COMM_NOYELL); SET_BIT(vch->comm,COMM_NOCHANNELS); } } }//END NPC } int skill_lookup( const char *name ) { int sn; for ( sn = 0; sn < (MAX_SKILL + MAX_EFFECTS); sn++ ) { if (IS_GEN(sn)) { if ( effect_table[GN_POS(sn)].name == NULL ) { break; } if ( LOWER(name[0]) == LOWER(effect_table[GN_POS(sn)].name[0]) && !str_prefix( name, effect_table[GN_POS(sn)].name ) ) { return sn; } } else { if ( skill_table[sn].name == NULL ) { continue; } if ( LOWER(name[0]) == LOWER(skill_table[sn].name[0]) && !str_prefix( name, skill_table[sn].name ) ) { return sn; } } }//end for return -1; } int find_spell( CHAR_DATA *ch, const char *name ) { int sn, found = -1; if (IS_NPC(ch)) return skill_lookup(name); for ( sn = 0; sn < MAX_SKILL; 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 (ch->level >= sklevel(ch,sn) && get_skill(ch,sn) > 0) return sn; } } return found; } int slot_lookup( int slot ) { /* extern bool fBootDb; int sn; if ( slot <= 0 ) return -1; for ( sn = 0; sn < MAX_SKILL; sn++ ) if ( slot == skill_table[sn].slot ) return sn; if ( fBootDb ) { bug( "Slot_lookup: bad slot %d.", slot ); abort( ); } */ return slot; } void say_spell( CHAR_DATA *ch, int sn ) { char buf [MSL], buf2 [MSL]; CHAR_DATA *rch; char *pName; int iSyl, length; struct syl_type { char * old; char * new; }; static const struct syl_type syl_table[] = { { " ", " " }, { "ar", "abra" }, { "au", "kada" }, { "bless", "fido" }, { "blind", "nose" }, { "bur", "mosa" }, { "cu", "judi" }, { "de", "oculo" }, { "en", "unso" }, { "light", "dies" }, { "lo", "hi" }, { "mor", "zak" }, { "move", "sido" }, { "ness", "lacri" }, { "ning", "illa" }, { "per", "duda" }, { "ra", "gru" }, { "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 = strlen(syl_table[iSyl].old)) != 0; iSyl++ ) if ( !str_prefix( syl_table[iSyl].old, pName ) ) { strcat( buf, syl_table[iSyl].new ); break; } if ( length == 0 ) length = 1; } sprintf( buf2, "$n utters the words, '%s'.", buf ); sprintf( buf, "$n utters the words, '%s'.", skill_table[sn].name ); for ( rch = ch->in_room->people; rch; rch = rch->next_in_room ) if ( rch != ch ) act(((!IS_NPC(rch) && ch->class==rch->class) || is_affected(rch, gsn_com_lan)) ? buf : buf2,ch, NULL, rch, TO_VICT ); } int calc_saves(int level, CHAR_DATA* victim, int dam_type, int spell_type ){ int save; if (IS_NPC(victim)){ save = 40 - victim->savingspell; save += (( victim->level - level) * 5); } else{ save = 40 - victim->savingspell; save += (( victim->level - level) * 3); } if (IS_AFFECTED(victim,AFF_BERSERK) || IS_AFFECTED2(victim,AFF_RAGE)) save += victim->level/10; if (spell_type == SPELL_MALEDICTIVE){ save -= victim->savingmaled; save += get_curr_stat(victim,STAT_CON) - 19; } else if (spell_type == SPELL_AFFLICTIVE){ save -= victim->savingaffl; save += get_curr_stat(victim,STAT_STR) - 19; } else{ save -= victim->savingmental; save += get_curr_stat(victim,STAT_INT) - 19; } if (is_affected(victim,gsn_buddha) && (dam_type == DAM_MENTAL || dam_type == DAM_DISEASE || dam_type == DAM_POISON)){ save += 10; } switch(check_immune(victim,dam_type, TRUE)){ case IS_IMMUNE: return 999; case IS_RESISTANT: save += 15; break; case IS_VULNERABLE: save -= 15; break; } save += (get_curr_stat(victim,STAT_LUCK) - 16); save = URANGE( 5, save, 95 ); return (save); } bool saves_spell( int level, CHAR_DATA *victim, int dam_type, int spell_type ) { int save = calc_saves(level, victim, dam_type, spell_type ); if (spell_type == -1) return FALSE; if (!IS_NPC(victim) && IS_SET(victim->act2,PLR_GIMP)) return FALSE; return number_percent( ) < save; } bool saves_dispel( int dis_level, int spell_level, int duration) { int save; if (duration == -1) return TRUE; save = 50 + (spell_level - dis_level) * 5; save = URANGE( 5, save, 95 ); return number_percent( ) < save; } bool check_dispel( int dis_level, CHAR_DATA *victim, int sn){ AFFECT_DATA *af; for ( af = victim->affected; af != NULL; af = af->next ){ if ( af->type == sn ){ if (dis_level == -99 || !saves_dispel(dis_level,af->level,af->duration)){ if (sn == gsn_duplicate){ if (IS_NPC(victim) && IS_SET(victim->act2,ACT_DUPLICATE)){ act("$n is dispelled.",victim,NULL,NULL,TO_ROOM); char_from_room(victim); extract_char(victim,TRUE); return TRUE; } else return FALSE; } affect_strip(victim,sn); if(!IS_GEN(sn)){ act_new(skill_table[sn].msg_off, victim, NULL, NULL, TO_CHAR, POS_DEAD); act(skill_table[sn].msg_off2, victim, NULL, NULL, TO_ROOM); } return TRUE; } else af->level -= 1; } } return FALSE; } ///////////////// //spell_lvl_mod// ///////////////// //Factors class modifires into the spell power //as much as I would like a bit more fine control //of the bonuses, teh cleanes way to do this //is to give lvl bonus to the spell. inline int spell_lvl_mod(CHAR_DATA* ch, int spell_number) { int lvl_mod = 0; int level = 0; int af_mod = 0; if (ch->class == class_lookup("vampire") && !str_cmp(skill_table[spell_number].name, "energy drain") ) { level = UMIN(ch->level, sizeof(energy_drain_bonus)/sizeof(energy_drain_bonus[0]) - 1); lvl_mod += UMAX(0, energy_drain_bonus[level]); } if (skill_table[spell_number].spell_type == SPELL_MALEDICTION){ if ( ch->class != class_lookup("shaman")) lvl_mod -= 3; } else if (spell_number == gsn_dispel_magic || spell_number == gsn_ecstacy || spell_number == gsn_sleep) lvl_mod -= 3; /* Tattoos */ if (ch->tattoo == deity_lookup("knowledge")){ if (skill_table[spell_number].spell_type != SPELL_MALEDICTION) lvl_mod += 1; } /* check effects */ af_mod += UMIN(2, ch->aff_mod[MOD_SPELL_LEVEL]); if (skill_table[spell_number].spell_type == SPELL_AFFLICTIVE) af_mod += UMIN(2, ch->aff_mod[MOD_AFFL_LEVEL]); if (skill_table[spell_number].spell_type == SPELL_MENTAL) af_mod += UMIN(2, ch->aff_mod[MOD_MENTAL_LEVEL]); if (skill_table[spell_number].spell_type == SPELL_MALEDICTION) af_mod += UMIN(2, ch->aff_mod[MOD_MALED_LEVEL]); lvl_mod += UMIN(3, af_mod); //RETURN FINAL SPELL LVL return ch->level + lvl_mod; }//END spell_lvl_mod ////////////// //_mana_cost// ///////////// //_mana_cost will replace above function as ssoon as I can //confirm that it will not affect anything else. //Calculates cost of a spell, talking into effect any race/ //class modifiers. inline int _mana_cost(CHAR_DATA* ch, int spell_number) { int mana, mana_mod=0, skill; //We set the modifer now depending on the class/race //In the future if there are multiple additions here //Then an LUT will have to be setup. //First calculate true cost so it can be factored into calculations below //if needed. if (ch->level +2 == sklevel(ch, spell_number)) mana = 50; else mana = UMAX(skill_table[spell_number].min_mana, 100/(2 + ch->level - sklevel(ch, spell_number))); //NOW calculate the bonus/penalty. if (ch->class == class_lookup("vampire") && !str_cmp(skill_table[spell_number].name, "energy drain") ) mana_mod += -10; else if (ch->class == class_lookup("vampire") && !str_cmp(skill_table[spell_number].name, "vampiric touch") ) mana_mod += -10; else if (ch->class == class_lookup("dark-knight") && spell_number == gsn_poison ) mana_mod += +5; else if (ch->class == class_lookup("dark-knight") && spell_number == gsn_plague ) mana_mod += +10; else if (ch->class == class_lookup("shaman") && spell_number == gsn_plague ) mana_mod += -5; else if (ch->class == class_lookup("shaman") && spell_number == gsn_blindness ) mana_mod += -10; else if (ch->class == class_lookup("shaman") && spell_number == gsn_poison ) mana_mod += -10; //OTHER BONUSES /* Tattoos */ if (ch->tattoo == deity_lookup("knowledge")) mana_mod += -mana / 4; if (is_affected(ch, gsn_corrupt)) mana_mod += 5 + mana / 3; if (is_affected(ch, gsn_ocularis)) mana_mod += mana / 4; /* vortex tap */ if ( (skill = get_skill(ch, gsn_ancient_lore)) > 1){ mana_mod -=( skill * 33 * (mana + mana_mod) / 10000); } mana_mod = mana_mod * (100 + ch->aff_mod[MOD_SPELL_COST]) / 100; //RETURN THE FINAL MANA COST. return (UMAX(1, mana+mana_mod)); } void cast_new( CHAR_DATA *ch, char *argument, bool iscommune, bool fIgnorePos ) { CHAR_DATA *victim = NULL; OBJ_DATA *obj = NULL; AFFECT_DATA* paf; char arg1[MIL], arg2[MIL]; int spell_lag = 0; int spell_lvl = 0; int skill = 0; void *vo = NULL; bool fyell = FALSE, syell = TRUE, havepower = TRUE; int mana, sn, target = TARGET_NONE, door, concen; if (ch->in_room == NULL){ bug( "cast_new: mob not in room.", 0 ); return; } if (IS_GAME(ch, GAME_NOSPELLS)) havepower = FALSE; else if (ch->pCabal && ch->class != gcn_blademaster && IS_CABAL(ch->pCabal, CABAL_NOMAGIC)) havepower = FALSE; if (!IS_NPC(ch) && !IS_IMMORTAL(ch) && !havepower){ send_to_char("You have lost your powers!\n\r",ch); return; } else if (is_affected(ch, gsn_forget)){ send_to_char("You seemed to have forgotten all your spells.\n\r",ch); return; } else if (is_affected(ch, gsn_headbutt)){ send_to_char("Your head is still spinning, you can't focus enough.\n\r",ch); return; } else if (!IS_IMMORTAL(ch) && IS_SET(ch->in_room->room_flags2,ROOM_NO_MAGIC)){ send_to_char("Something is interfering with your casting abilities.\n\r",ch); return; } else if (vamp_day_check(ch)){ send_to_char("You lack the power.\n\r",ch); return; } /* cost of spell for corrupt is increased in _mana_cost */ if (is_affected(ch, gsn_corrupt)) send_to_char("Your mind is taxed as you overcome influence of Chaos around you.\n\r", ch); target_name = one_argument( argument, arg1 ); one_argument( target_name, arg2 ); if ( arg1[0] == '\0' ){ send_to_char( "Cast which what where?\n\r", ch ); return; } else if ((sn = find_spell(ch,arg1)) < 1 || skill_table[sn].spell_fun == spell_null || ((skill = get_skill(ch,sn)) < 1 && !IS_NPC(ch)) ){ send_to_char( "You don't know any spells of that name.\n\r", ch ); return; } else if (skill < 2 ){ send_to_char("You lack the skill neccessary.\n\r", ch); return; } else if ( !fIgnorePos && ch->position < skill_table[sn].minimum_position ){ send_to_char( "You can't concentrate enough.\n\r", ch ); return; } else if (!fIgnorePos && IS_GNBIT(sn, GN_NOCAST)){ send_to_char("This spell cannot be cast this way.\n\r", ch); return; } /* mental knife prevents beneficial spells */ else if (IS_GNBIT(sn, GN_BEN) && is_affected(ch, gsn_mental_knife) ){ send_to_char("Your mind flares with pain and you abort your efforts.\n\r", ch); return; } //calculate the new manacost factoring in the race/class bonuses. mana = _mana_cost(ch, sn); switch ( skill_table[sn].target ){ default: bug( "Do_cast: bad target for sn %d.", sn ); return; case TAR_IGNORE: if ( arg2[0] == '\0' && sn == 59) { send_to_char("Locate what?\n\r",ch); return; } if (IS_AFFECTED2(ch,AFF_SHADOWFORM) && sn == 43) { send_to_char("You cannot affect others in your ethereal state.\n\r",ch); return; } if (IS_AFFECTED2(ch,AFF_TREEFORM)) { send_to_char("You cannot do this in your treeformed state.\n\r",ch); return; } break; case TAR_CHAR_OFFENSIVE: if ( arg2[0] == '\0' ) { if ( ( victim = ch->fighting ) == NULL ) { send_to_char( "Cast the spell on whom?\n\r", ch ); return; } } else if ( ( victim = get_char_room( ch, NULL, target_name ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if (IS_AFFECTED2(ch,AFF_SHADOWFORM) && victim != ch) { send_to_char("You cannot affect others in your ethereal state.\n\r",ch); return; } if (IS_AFFECTED2(ch,AFF_TREEFORM) && victim != ch) { send_to_char("You cannot affect others in your treeformed state.\n\r",ch); return; } if (is_safe(ch,victim) && victim != ch) { sendf(ch, "Not on %s.\n\r",PERS(victim,ch)); return; } if (is_sheathed(ch)){ send_to_char("Your weapons are sheathed!\n\r", ch); return; } if ( !IS_NPC(ch) && victim == ch && sn != 76 && sn != 150 && ch->pcdata->learned[sn] > 0)// && !(IS_IMMORTAL (ch))) { send_to_char("Hurting yourself doesn't help.\n\r",ch); if (!is_affected(ch, gsn_nolearn)){ AFFECT_DATA af; af.type = gsn_nolearn; af.level = 60; af.duration = 0; af.where = TO_NONE; af.bitvector = 0; af.location = APPLY_NONE; af.modifier = 0; affect_to_char(victim, &af); ch->mana /= 2; } } vo = (void *) victim; target = TARGET_CHAR; break; case TAR_CHAR_DEFENSIVE: if ( arg2[0] == '\0' ) victim = ch; else if ( ( victim = get_char_room( ch, NULL, target_name ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if (IS_AFFECTED2(ch,AFF_SHADOWFORM) && victim != ch) { send_to_char("You cannot affect others in your ethereal state.\n\r",ch); return; } if (IS_AFFECTED2(ch,AFF_TREEFORM) && victim != ch) { send_to_char("You cannot affect others in your treeformed state.\n\r", ch); return; } vo = (void *) victim; if (skill_table[sn].spell_type == SPELL_PROTECTIVE) { if (!is_same_group && (victim->level > ch->level + 9 || victim->level < ch->level -9)) { send_to_char("You cannot cast this spell on that person.\n\r",ch); return; } if ((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_GOOD(victim) && IS_EVIL(ch))) { send_to_char("Why would you help that person?\n\r",ch); return; } } if (skill_table[sn].spell_type == SPELL_CURATIVE) { if (!IS_NPC(victim) && !is_same_group(ch,victim) && is_fight_delay(victim,40) && (victim->level > ch->level + 9 || victim->level < ch->level -9)) { send_to_char("You cannot cast this spell on that person yet.\n\r",ch); return; } if ((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_GOOD(victim) && IS_EVIL(ch))) { send_to_char("Why would you help that person?\n\r",ch); return; } } if (skill_table[sn].spell_type == SPELL_RESTORATIVE) { if (!IS_NPC(victim) && !is_same_group(ch,victim) && is_fight_delay(victim,40) && (victim->level > ch->level + 9 || victim->level < ch->level -9)) { send_to_char("You cannot cast this spell on that person.\n\r",ch); return; } } target = TARGET_CHAR; break; case TAR_CHAR_SELF: if ( arg2[0] != '\0' && !is_name( target_name, ch->name ) ) { send_to_char( "You cannot cast this spell on another.\n\r", ch ); return; } vo = (void *) ch; break; case TAR_OBJ_WORN: if ( arg2[0] == '\0' ) { send_to_char( "What should the spell be cast upon?\n\r", ch ); return; } if ( ( obj = get_obj_wear( ch, target_name, ch) ) == NULL ) { send_to_char( "You are not wearing that.\n\r", ch ); return; } vo = (void *) obj; target = TARGET_OBJ; break; case TAR_OBJ_INV: if ( arg2[0] == '\0' ) { send_to_char( "What should the spell be cast upon?\n\r", ch ); return; } if ( ( obj = get_obj_carry( ch, target_name, ch ) ) == NULL ) { send_to_char( "That item is not on your person.\n\r", ch ); return; } vo = (void *) obj; target = TARGET_OBJ; break; case TAR_OBJ_ROOM: if ( arg2[0] == '\0' ) { send_to_char( "What should the spell be cast upon?\n\r", ch ); return; } if ( ( obj = get_obj_list( ch, arg2, ch->in_room->contents ) ) == NULL ) { send_to_char( "You can't find it.\n\r", ch ); return; } vo = (void *) obj; target = TARGET_OBJ; break; case TAR_DOOR: if ( arg2[0] == '\0' ) { send_to_char( "What should the spell be cast upon?\n\r", ch ); return; } door = find_door(ch,arg2); vo = (void *) door; target = TARGET_DOOR; break; case TAR_OBJ_CHAR_OFF: if (arg2[0] == '\0') { if ((victim = ch->fighting) == NULL) { send_to_char("Cast the spell on whom or what?\n\r",ch); return; } target = TARGET_CHAR; } else if ((victim = get_char_room(ch, NULL, target_name)) != NULL) target = TARGET_CHAR; if (IS_AFFECTED2(ch,AFF_SHADOWFORM) && victim != ch) { send_to_char("You cannot affect others in your ethereal state.\n\r",ch); return; } if (IS_AFFECTED2(ch,AFF_TREEFORM) && victim != ch) { send_to_char("You cannot affect others in your treeformed state.\n\r",ch); return; } if (target == TARGET_CHAR) { if(is_safe(ch,victim) && victim != ch) { sendf(ch, "Not on %s.\n\r",PERS(victim,ch)); return; } vo = (void *) victim; } else if ((obj = get_obj_here(ch, NULL, target_name)) != NULL) { vo = (void *) obj; target = TARGET_OBJ; } else { send_to_char("You don't see that here.\n\r",ch); return; } break; case TAR_OBJ_CHAR_DEF: if (arg2[0] == '\0') { vo = (void *) ch; target = TARGET_CHAR; } else if ((victim = get_char_room(ch, NULL, target_name)) != NULL) { vo = (void *) victim; target = TARGET_CHAR; } else if ((obj = get_obj_carry(ch,target_name,ch)) != NULL) { vo = (void *) obj; target = TARGET_OBJ; } else { send_to_char("You don't see that here.\n\r",ch); return; } break; case TAR_ROOM_CHAR_DEF: if (arg2[0] == '\0') { vo = (void *) ch; target = TARGET_CHAR; } else if ((victim = get_char_room(ch, NULL, target_name)) != NULL) { vo = (void *) victim; target = TARGET_CHAR; } else if ( ( obj = get_obj_list( ch, target_name, ch->in_room->contents ) ) != NULL ) { vo = (void *) obj; target = TARGET_OBJ; } else { send_to_char("You don't see that here.\n\r",ch); return; } break; } if (IS_DNDS(ch) && (ch->pCabal == NULL || get_cskill(ch->pCabal, sn) == NULL)){ DNDS_DATA* dndsd; //cabal powers ignore this if ( (dndsd = dnds_lookup(ch->pcdata, sn, -1)) == NULL || GET_DNDMEM(ch->pcdata, sn) < 1){ send_to_char("You do not have that spell ready.\n\r", ch); return; } } if ( !IS_NPC(ch) && ch->mana < mana && !IS_IMMORTAL(ch)) { send_to_char( "You don't have enough mana.\n\r", ch ); return; } if ( str_cmp( skill_table[sn].name, "ventriloquate" ) && ch->invis_level < LEVEL_HERO) { if (iscommune) { if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE || (skill_table[sn].target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) act("$n narrows $s eyes.",ch,NULL,NULL,TO_ROOM); else act("$n closes $s eyes momentarily.",ch,NULL,NULL,TO_ROOM); } else if (is_affected(ch, gsn_subvocal)) { if ( skill_table[sn].target == TAR_CHAR_OFFENSIVE || (skill_table[sn].target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) act("Beads of perspiration form upon $n's forehead.",ch,NULL,NULL,TO_ROOM); else act("$n concentrates deeply.",ch,NULL,NULL,TO_ROOM); } else say_spell( ch, sn ); } //CABAL_NOMAGIC CHECK HERE, ALLOWS ONLY HARMFUL TYPES OF SPELLS if (target == TARGET_CHAR && (skill_table[sn].target != TAR_IGNORE && skill_table[sn].target != TAR_CHAR_OFFENSIVE && skill_table[sn].target != TAR_OBJ_CHAR_OFF) && ((CHAR_DATA*) vo)->pCabal && IS_CABAL( ((CHAR_DATA*) vo)->pCabal, CABAL_NOMAGIC)){ act("$N would not appreciate that.", ch, NULL, (CHAR_DATA*) vo, TO_CHAR); return; } //SPELL DATA spell_lvl = spell_lvl_mod(ch, sn); spell_lag = skill_table[sn].beats; if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE || (skill_table[sn].target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) && victim != ch ) { CHAR_DATA *vch, *vch_next; for ( vch = ch->in_room->people; vch; vch = vch_next ) { vch_next = vch->next_in_room; if (victim == NULL || ch == NULL || vch == NULL) break; if ( sn == 14 && IS_AFFECTED(vch,AFF_CHARM) && (is_same_group(ch,vch) || vch->master == ch || ch->master == ch)) break; if (victim == vch && ch->fighting != vch && vch->fighting != ch && !IS_NPC(ch)) fyell=TRUE; } } concen = skill; if (concen > 0){ concen += get_curr_stat(ch,STAT_LUCK) - 16; if (is_affected(ch,gsn_prayer)) concen += UMIN(5, 3 * (100 - concen) / 10); if (is_song_affected(ch,gsn_concen)){ concen += concen/3; song_strip(ch,gsn_concen); } } if ( (paf = affect_find(ch->affected, gsn_mind_disrupt)) != NULL) concen += paf->modifier; //PRESPELL_CHECK if (PRESPELL_CHECK(ch, argument, &sn, &mana, &spell_lag, &spell_lvl) == -1) bug("Error returned in PRESPELL\n\r", 0); if (!IS_IMMORTAL(ch)) WAIT_STATE2( ch, spell_lag); /* cabal cost */ if (ch->pCabal) handle_skill_cost( ch, ch->pCabal, sn ); if ( (IS_NPC(ch) && ch->desc == NULL && !ch->pIndexData->progtypes) || number_percent() > concen || check_spellblast(ch, victim, sn, mana, ch->level) ){ /* Learn from spell casting */ gain_exp(ch, 3 * spell_expgain(sn, get_skill(ch, sn), ch->level)); if (IS_IMMORTAL(ch)){ sendf(ch, "Spell exp gain: %d\n\r", spell_expgain(sn, skill, ch->level)); } send_to_char( "You lost your concentration.\n\r", ch ); check_improve(ch,sn,FALSE, 2 * (5 + mana / 10)); if (!IS_IMMORTAL(ch)) { ch->mana -= mana / 2; } } else { if (fyell && IS_AWAKE(victim)) { m_yell(ch,victim,TRUE); syell = FALSE; } if (!IS_IMMORTAL(ch)){ AFFECT_DATA* paf; ch->mana -= mana; if ( (paf = affect_find(ch->affected, gsn_ocularis)) != NULL && paf->has_string){ CHAR_DATA* och = get_char( paf->string ); int m_extra = UMAX(1, mana / 5); int mv_extra = number_range(2, 7); if (och && och != ch){ sendf(och, "The Eye of Magic channels %d mana and %d stamina to you.\n\r", m_extra, mv_extra ); och->mana = UMIN(och->max_mana, och->mana + m_extra ); och->move = UMIN(och->max_move, och->move + mv_extra ); send_to_char("It seems to take great effort to form the spell.\n\r", ch); ch->move = UMAX(0, ch->move - mv_extra); } } } /* use up the DNDS spell */ if (IS_DNDS(ch)) useup_dnds( ch->pcdata, sn ); /* spell and mana trap */ if (skill_table[sn].target == TAR_CHAR_OFFENSIVE && victim && victim != ch && !IS_NPC(ch) && !IS_NPC(victim)){ if (is_affected(victim, gsn_mana_trap)){ int mana_gain = number_range(mana / 2, mana); // sendf(victim, "You gain %d mana.\n\r", mana_Gain ); victim->mana = UMIN(victim->mana + mana_gain, 110 * victim->max_mana / 100 ); } if (is_affected(victim, gsn_spell_trap )){ int level = sklevel(ch, sn ); DNDS_HEADER* dndsh = &victim->pcdata->dndspells[UMIN(4, level / 10)]; memorize_spells(dndsh, 1 ); } } /* Learn from spell casting */ gain_exp(ch, spell_expgain(sn, skill, ch->level)); if (IS_IMMORTAL(ch)){ sendf(ch, "Spell exp gain: %d\n\r", spell_expgain(sn, skill, ch->level)); } if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE || skill_table[sn].target == TAR_CHAR_DEFENSIVE) && ( (paf = affect_find(victim->affected,gsn_mimic)) != NULL) && sn != gsn_breach && ch != victim && victim->position > POS_SITTING && number_percent() < (get_skill(victim, gsn_mimic) - 15)) { CHAR_DATA* buf; act("Your reflective shield flares and fades as $N's spell is reflected back at $M.",victim,NULL,ch,TO_CHAR); act("$n's shield of spell turning reflects $N's spell back at $M.",victim,NULL,ch,TO_NOTVICT); act("$n's shield of spell turning reflects your spell back at you",victim,NULL,ch,TO_VICT); if (--paf->modifier < 1){ affect_strip(victim,gsn_mimic); act("Your shield of spell turning collapses.", victim, NULL, NULL, TO_CHAR); act( "The shimmering, reflecting shield around $n fades away.", victim, NULL, NULL, TO_ROOM); } //we flip targets around. buf = (CHAR_DATA*) vo; vo = (void *) ch; ch = buf; spell_lvl = 2 * spell_lvl / 3; } //check for blademaster snakespeed if (skill_table[sn].target == TAR_CHAR_OFFENSIVE && snakespeedCheck(ch, victim)) return; //check for spell killer if (ch->fighting && ch->fighting->fighting == ch && spellkillerCheck(ch, ch->fighting, sn)){ return; } /////////////////////// //CAST THE SPELL HERE// ////////////////////// (*skill_table[sn].spell_fun) ( sn, spell_lvl, ch, vo,target); check_improve(ch,sn,TRUE, 3 + mana / 10); //POSTSPELL_CHECK if (POSTSPELL_CHECK(ch, argument, sn, mana, spell_lag) == -1) bug("Error returned in POSTSPELL\n\r", 0); } check_improve(ch,gsn_ancient_lore,TRUE,1); if ((skill_table[sn].target == TAR_CHAR_OFFENSIVE || (skill_table[sn].target == TAR_OBJ_CHAR_OFF && target == TARGET_CHAR)) && victim != ch ) { CHAR_DATA *vch, *vch_next; for ( vch = ch->in_room->people; vch; vch = vch_next ) { vch_next = vch->next_in_room; if (victim == NULL || ch == NULL || vch == NULL) break; if ( sn == 14 && IS_AFFECTED(vch,AFF_CHARM) &&(is_same_group(ch,vch) || vch->master == ch)) break; if ( victim == vch && victim->fighting == NULL ) { if (syell) m_yell(ch,victim,FALSE); if (IS_AWAKE(victim) && !is_affected(victim,gsn_ecstacy) && !is_affected(victim,gsn_mortally_wounded) && IS_AWAKE(ch) && !is_affected(ch,gsn_ecstacy) && !is_affected(ch,gsn_mortally_wounded) && !is_ghost(victim,600)) { set_fighting( ch, victim ); set_fighting( victim, ch ); multi_hit( victim, ch, TYPE_UNDEFINED ); } else set_delay(ch, victim); break; } if (victim == vch && ch->fighting == NULL ) { if (syell) m_yell(ch,victim,FALSE); if (IS_AWAKE(victim) && !is_affected(victim,gsn_mortally_wounded) && !is_affected(victim,gsn_ecstacy) && IS_AWAKE(ch) && !is_affected(ch, gsn_mortally_wounded) && !is_affected(ch,gsn_ecstacy) && !is_ghost(victim,600)) { set_fighting( ch, victim ); set_fighting( victim, ch ); multi_hit( victim, ch, TYPE_UNDEFINED ); } else set_delay(victim, ch); break; } } } } void do_cast( CHAR_DATA *ch, char *argument ) { if (get_trust(ch) < LEVEL_IMMORTAL && (ch->class == class_lookup("healer") || ch->class == class_lookup("shaman") || ch->class == class_lookup("cleric") || ch->class == class_lookup("paladin")|| ch->class == class_lookup("druid"))) { send_to_char("You need to commune to your god.\n\r",ch); return; } if ( !IS_IMMORTAL(ch) && (ch->class == class_lookup("necromancer") || ch->class == class_lookup("dark-knight")) && !IS_EVIL(ch) ) { send_to_char("You've lost your powers for straying from your alignment.\n\r",ch); return; } if (IS_AFFECTED2(ch, AFF_SILENCE) && !is_affected(ch, gsn_subvocal)) { send_to_char("As you utter your incantation, no sound comes out!\n\r",ch); return; } if (is_affected(ch, gsn_gag) && !is_affected(ch, gsn_subvocal)){ send_to_char("You try to work your mouth but the gag holds fast.\n\r", ch); return; } if (is_affected(ch,gsn_uppercut)) { send_to_char("Your jaws hurts too much to move.\n\r",ch); return; } if (!IS_IMMORTAL(ch) && IS_SET(ch->in_room->room_flags, ROOM_DARK_RIFT)) { send_to_char("All your ties to reality have been severed here, your magical energy is drained.\n\r",ch); return; } cast_new(ch,argument,FALSE, FALSE); } void do_commune( CHAR_DATA *ch, char *argument ) { if (ch->class != class_lookup("healer") && ch->class != class_lookup("shaman") && ch->class != class_lookup("cleric") && ch->class != class_lookup("druid") && ch->class != class_lookup("paladin") && get_trust(ch) < LEVEL_IMMORTAL) { send_to_char("You don't know how to commune.\n\r",ch); return; } if ( !IS_IMMORTAL(ch) && ((( ch->class == class_lookup("healer") || ch->class == class_lookup("paladin")) && !IS_GOOD(ch) ) || (ch->class == class_lookup("shaman") && !IS_EVIL(ch))) ) { send_to_char("You've lost your powers for straying from your alignment.\n\r",ch); return; } if (!IS_IMMORTAL(ch) && IS_SET(ch->in_room->room_flags, ROOM_DARK_RIFT)) { send_to_char("All your ties to reality have been severed here, your faith falters.\n\r",ch); return; } if (!IS_IMMORTAL(ch) && IS_SET(ch->in_room->room_flags2,ROOM_NO_MAGIC)) { send_to_char("Your prayers have been blocked off to your gods.\n\r",ch); return; } if (!IS_NPC(ch) && deity_table[ch->pcdata->way].shrine == 0){ send_to_char("Your lack of faith prevents you from communing.\n\r",ch); if (ch->pcdata->way == 0) send_to_char("Consult scrolls of \"help religion\".\n\r", ch); return; } if (is_affected(ch,gsn_blasphemy) ) { send_to_char("Your lack of faith prevents you from communing.\n\r",ch); return; } if (is_affected(ch, gsn_corrupt)) { send_to_char("Your prayers fail as the reality seems to weave and bend around you.\n\r", ch); return; } if ( argument[0] == '\0' ) { send_to_char( "Commune which what where?\n\r", ch ); return; } cast_new(ch,argument,TRUE, FALSE); } void obj_cast_spell( int sn, int level, CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj ) { void *vo = NULL; int target = TARGET_NONE; if ( sn <= 0 ) return; level = UMAX(1,level); if ( sn >= MAX_SKILL || skill_table[sn].spell_fun == 0 ) { bug( "Obj_cast_spell: bad sn %d.", sn ); return; } switch ( skill_table[sn].target ) { default: bug( "Obj_cast_spell: bad target for sn %d.", sn ); return; case TAR_IGNORE: vo = NULL; break; case TAR_CHAR_OFFENSIVE: if ( victim == NULL ) victim = ch->fighting; if ( victim == NULL ) { send_to_char( "You can't do that.\n\r", ch ); return; } if (is_safe(ch,victim) && ch != victim) 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: case TAR_OBJ_ROOM: if ( obj == NULL ) { send_to_char( "You can't do that.\n\r", ch ); 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 { send_to_char("You can't do that.\n\r",ch); return; } if (victim != NULL) { if (is_safe(ch,victim) && ch != victim) { send_to_char("Somehting isn't right...\n\r",ch); 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; } //Remmed out to allow passing of targets 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, *vch_next; for ( vch = ch->in_room->people; vch; vch = vch_next ) { vch_next = vch->next_in_room; if ( victim == vch && victim->fighting == NULL ) { m_yell(ch,victim,TRUE); multi_hit( victim, ch, TYPE_UNDEFINED ); break; } } } } void spell_acid_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam = 2 * level + dice( 40, 3 ); if ( saves_spell( level, victim, DAM_ACID,skill_table[sn].spell_type ) ) dam /= 2; else acid_effect(victim, level, dam, TARGET_CHAR); damage( ch, victim, dam, sn,DAM_ACID,TRUE); } void spell_armor( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && level < LEVEL_IMMORTAL) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if ( is_affected( victim, sn ) ) { if (victim == ch) act("You are already armored.",ch,NULL,victim,TO_CHAR); else act("$N is already armored.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 24 * UMAX(1, level / 25); af.modifier = -20; af.location = APPLY_AC; af.bitvector = 0; affect_to_char( victim, &af ); act_new( "You feel someone protecting you.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); if ( ch != victim ) act("$N is protected by your magic.",ch,NULL,victim,TO_CHAR); } void spell_bless( int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; int loc1 = APPLY_NONE; int loc2 = APPLY_NONE; int loc3 = APPLY_NONE; int mod1 = 0; int mod2 = 0; int mod3 = 0; int g_type = 0; if (!IS_NPC(ch) && ( (IS_GOOD(ch) && IS_EVIL(victim)) || (IS_GOOD(victim) && IS_EVIL(ch)) ) ) { act("$g doesn't seem to like $N.", ch, NULL, victim, TO_CHAR); return; } if ( is_affected( victim, gsn_blasphemy ) ) { sendf(ch, "%s's faith have been lost.\n\r", PERS(victim,ch)); return; } if ( is_affected( victim, sn ) || is_affected(victim, gsn_warcry)) { if (victim == ch) act( "You are already blessed.",ch,NULL,victim,TO_CHAR); else act("$N already has divine favor.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 6+level; af.bitvector = 0; if(IS_NPC(ch)) { af.location = APPLY_HITROLL; af.modifier = level / 12; affect_to_char( victim, &af ); af.location = APPLY_DAMROLL; af.modifier = level / 12; affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = 0 - level / 12; affect_to_char( victim, &af ); act( "You feel righteous.", ch,NULL,victim,TO_CHARVICT); if ( ch != victim ) act("You grant $N $g's favor.",ch,NULL,victim,TO_CHAR); return; } g_type = deity_table[IS_NPC(ch) ? 0 : ch->pcdata->way].path; act( "You feel $g's strength in your soul.", ch,NULL,victim,TO_CHARVICT); if ( ch != victim ) act("You grant $N $g's favor.",ch,NULL,victim,TO_CHAR); /* LIFE */ if (g_type == PATH_LIFE){ loc1 = APPLY_HIT; mod1 = level/2; loc2 = APPLY_HIT_GAIN; mod2 = level / 5; loc3 = APPLY_HITROLL; mod3 = level / 8; } /* DEATH */ else if (g_type == PATH_DEATH){ loc1 = APPLY_SAVING_MALED; mod1 = -level/4; } /* CHANCE */ else if (g_type == PATH_CHANCE){ /* first modifier may be hitroll or damroll or saves */ switch( number_range(0, 7)){ case 0: case 1: loc1 = APPLY_HITROLL; mod1 = level/8; break; case 2: case 3: loc1 = APPLY_DAMROLL; mod1 = level/8; break; case 4: case 5: loc1 = APPLY_AC; mod1 = -level; break; case 6: case 7: loc1 = APPLY_SAVING_SPELL; mod1 = -level/12; break; } loc2 = APPLY_LUCK; mod2 = level / 12; } /* KNOWLEDGE */ else if (g_type == PATH_KNOW){ /* select between warriro types and mage types */ if (class_table[victim->class].fMana){ loc1 = APPLY_MANA_GAIN; mod1 = level / 5; loc2 = APPLY_SAVING_SPELL; mod2 = -level / 8; } else{ OBJ_DATA* obj = get_eq_char( victim, WEAR_WIELD ); af.where = TO_SKILL; af.location = (obj == NULL || obj->value[0] == WEAPON_EXOTIC ? gsn_hand_to_hand : *weapon_table[weapon_lookup(weapon_name(obj->value[0]))].gsn); if (ch != victim) af.modifier = 1; else af.modifier = level / 16; affect_to_char(victim, &af); af.where = TO_AFFECTS; loc1 = APPLY_NONE; mod1 = 0; loc2 = APPLY_DAMROLL; mod2 = level / 6; } } /* OTHER */ else{ loc1 = APPLY_SAVING_SPELL; mod1 = -level / 12; loc2 = APPLY_DAMROLL; mod2 = level / 12; loc3 = APPLY_HITROLL; mod3 = level / 12; } //now we apply them. if (loc1 != APPLY_NONE) { af.location = loc1; af.modifier = mod1; affect_to_char(victim, &af); } if (loc2 != APPLY_NONE) { af.location = loc2; af.modifier = mod2; affect_to_char(victim, &af); } if (loc3 != APPLY_NONE) { af.location = loc3; af.modifier = mod3; affect_to_char(victim, &af); } } void spell_blindness( int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_BLIND)) { act("$N is already blinded.",ch,NULL,victim,TO_CHAR); return; } if ( saves_spell(level,victim,DAM_MALED,skill_table[sn].spell_type)) { act("You fail to blind $N.",ch,NULL,victim,TO_CHAR); return; } /* Palison tattoo check */ if (ch->tattoo == deity_lookup("compassion") && number_percent() < 75){ OBJ_DATA* tattoo = get_eq_char( ch, WEAR_TATTOO); if (tattoo) act("$p flares with a brilant aura.", ch, tattoo, victim, TO_ALL); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.location = APPLY_HITROLL; af.duration = level/10 + 4; af.bitvector = AFF_BLIND; if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){ if (is_affected(victim, gsn_battletrance)) af.modifier = 0; else af.modifier = -5; } else af.modifier = -10; affect_to_char(victim,&af); af.location = APPLY_AC; if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){ if (is_affected(victim, gsn_battletrance)) af.modifier = 0; else af.modifier = +15; } else af.modifier = +25; affect_to_char(victim,&af); act("You are blinded!", victim,NULL,NULL,TO_CHAR); act("$n appears to be blinded.",victim,NULL,NULL,TO_ROOM); } void spell_burning_hands(int sn,int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const sh_int dam_each[] = { 0, 2, 2, 5, 8, 12, 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, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); dam = number_range( dam_each[level] / 2, dam_each[level] * 2 ); if ( saves_spell( level, victim,DAM_FIRE,skill_table[sn].spell_type) ) dam /= 2; damage( ch, victim, dam, sn, DAM_FIRE,TRUE); } void spell_call_lightning( int sn, int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *vch, *vch_next; static const sh_int dam_each[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 35, 40, 45, 50, 55, 60, 70, 80, 85, 90, 92, 94, 96, 98, 100, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 114, 115, 115, 115, 115, 115, 120, 120 }; int dam; int armor = 0; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); dam = number_range( 3 * dam_each[level]/4, 3 * dam_each[level] / 2 ); if ( !IS_OUTSIDE(ch) ) { send_to_char( "You must be out of doors.\n\r", ch ); return; } if ( ( mud_data.weather_info.sky < SKY_RAINING || temp_adjust( ch->in_room->temp ) <= 35) && !IS_IMMORTAL(ch)) { send_to_char( "You need bad weather.\n\r", ch ); return; } act( "Deep thunder rolls and sheets of lightning strike your foes!", ch, NULL, NULL, TO_CHAR ); act( "$n shouts an invocation and sheets of lightning strike from above!",ch, NULL, NULL, TO_ROOM ); for ( vch = char_list; vch != NULL; vch = vch_next ) { vch_next = vch->next; if ( vch->in_room == NULL ) continue; if ( vch->in_room == ch->in_room && vch != ch && !is_area_safe(ch,vch)) { m_yell(ch,vch,FALSE); if ( saves_spell( level, vch, DAM_LIGHTNING,skill_table[sn].spell_type) ) dam /= 2; //We give bonus to the spell for the ac person has. (ac is n've so we subtr.) //bonus is 1/2 value over 150, and regular over 225. armor = GET_AC(vch, AC_PIERCE) + GET_AC(vch, AC_BASH) + GET_AC(vch, AC_SLASH); armor /= -3; if (armor > 225){ act("Sparks arc around $n's armor!", vch, NULL, NULL, TO_ROOM); act("Sparks arc around your armor!", vch, NULL, NULL, TO_CHAR); } armor = UMIN(300, armor); dam += UMAX(0 ,(armor-150)/2); dam += UMAX(0, (armor - 225)); dam = UMIN(300, dam); //And we apply damage. damage( ch, vch, dam, sn,DAM_LIGHTNING,TRUE); //And a little bonus to those with huger armor. if (armor >= 300) { act("The hair on your neck rises as air becomes charged around you.", ch, NULL, vch, TO_VICT); act("$N's armor glows with ghostly blue hue and the air crackles with charge.", vch, NULL, vch, TO_ROOM); damage( ch, vch, dam/3, sn,DAM_LIGHTNING,TRUE); } } } } void spell_calm( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *vch; AFFECT_DATA af; int gsn_frenzy = skill_lookup("frenzy"); send_to_char("You send a powerful aura of peace and calm radiating through the area.\n\r", ch); act("$n sends a powerful aura of peace and calm radiating through the area.\n\r", ch, NULL, NULL, TO_ROOM); for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room){ bool fSave = FALSE; if (IS_AFFECTED(vch,AFF_CALM)) continue; else if (is_same_group(ch, vch)) continue; else if (is_area_safe_quiet(ch,vch)) continue; if (IS_DEMON(vch) || (IS_NPC(vch) && IS_SET(vch->act, ACT_TOO_BIG))){ act("$N ignores your efforts at calming $M.", ch, NULL, vch, TO_CHAR); act("You ignore $n's efforts to calm you.", ch, NULL, vch, TO_VICT); fSave = TRUE; } else if (saves_spell( IS_UNDEAD(vch) ? level + 3 : level, vch, DAM_MENTAL, skill_table[sn].spell_type) ){ fSave = TRUE; } m_yell( ch, vch, FALSE ); if (fSave){ if( IS_AWAKE(vch) && vch->fighting != ch && ch->fighting != vch && !is_affected(vch,gsn_ecstacy) && !is_ghost(vch,600)) { if (ch->fighting == NULL || vch->fighting == NULL) multi_hit( vch, ch, TYPE_UNDEFINED ); set_fighting( vch, ch ); } continue; } act("$n has been calmed.", vch, NULL, NULL, TO_ROOM); send_to_char("You feel unnatural calm settle on your mind.\n\r",vch); /* mobs the group is fighting may be calmed */ if (vch->fighting && is_same_group(ch, vch->fighting)) stop_fighting(vch, TRUE); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level/6; af.location = APPLY_HITROLL; af.modifier = -level / 10; af.bitvector = AFF_CALM; affect_to_char(vch,&af); af.location = APPLY_DAMROLL; affect_to_char(vch,&af); if (IS_AFFECTED(vch,AFF_BERSERK)){ affect_strip(vch, gsn_berserk); REMOVE_BIT(vch->affected_by, AFF_BERSERK); act(skill_table[gsn_berserk].msg_off, vch, NULL, NULL, TO_CHAR); } if (is_affected(vch, gsn_frenzy )){ affect_strip(vch, gsn_frenzy ); act(skill_table[gsn_frenzy].msg_off, vch, NULL, NULL, TO_CHAR); } if (IS_AFFECTED2(vch,AFF_RAGE)){ REMOVE_BIT(vch->affected2_by,AFF_RAGE); affect_strip(vch,gsn_rage); act("You snap out of your madness.",vch,NULL,NULL,TO_CHAR); act("$n gasps for air as $e snaps out of $s insanity.",vch,NULL,NULL,TO_ROOM); vch->hit -= (ch->level * ch->perm_stat[STAT_CON]) /3; if (IS_IMMORTAL(vch)) vch->hit = UMAX(1,vch->hit); if (vch->hit < -2){ int shock_mod = (25 * (0 - vch->hit)) / vch->max_hit; if (number_percent( ) < con_app[UMAX(1,vch->perm_stat[STAT_CON] - shock_mod)].shock + 2*(get_curr_stat(vch,STAT_LUCK) - 16)){ act_new("Your body suddenly awakens to the wounds you've sustained and you lose consciousness.",vch,NULL,NULL,TO_CHAR,POS_DEAD); act("$n suddenly clutches $s wounds and slumps to the ground, unconscious.",vch,NULL,NULL,TO_ROOM); vch->hit = -2; vch->position = POS_STUNNED; act( "$n is stunned, but will probably recover.",vch, NULL, NULL, TO_ROOM ); act_new("You are stunned, but will probably recover.",vch, NULL, NULL, TO_CHAR, POS_DEAD ); } else{ act_new("Your body could not sustain the injuries you've suffered.",vch,NULL,NULL,TO_CHAR,POS_DEAD); act("$n suddenly clutches $s wounds and slumps to the ground.",vch,NULL,NULL,TO_ROOM); act( "$n is DEAD!!",vch, 0, 0, TO_ROOM ); act_new( "You have been `1KILLED``!!", vch,NULL,NULL,TO_CHAR,POS_DEAD); raw_kill(vch, vch ); continue; } }//end rage death }//end if rage }//end for } void spell_cause_light( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { damage( ch, (CHAR_DATA *) vo, dice(1, 8) + level / 3, sn,DAM_HARM,TRUE); } void spell_cause_critical(int sn,int level,CHAR_DATA *ch,void *vo,int target) { damage( ch, (CHAR_DATA *) vo, dice(3, 8) + level - 6, sn,DAM_HARM,TRUE); } void spell_cause_serious(int sn,int level,CHAR_DATA *ch,void *vo,int target) { damage( ch, (CHAR_DATA *) vo, dice(2, 8) + level / 2, sn,DAM_HARM,TRUE); } void spell_chain_lightning(int sn,int level,CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA* paf; int sn_ms = skill_lookup("mana shield"); if ( (paf = affect_find(victim->affected, sn_ms)) == NULL){ act("$N doesn't have mana shield active.", ch, NULL, victim, TO_CHAR); return; } act("A thousand small lightning bolts being to between you and $N!", ch, NULL, victim, TO_CHAR); act("A thousand small lightning bolts being to between $n and $N!", ch, NULL, victim, TO_NOTVICT); act("A thousand small lightning bolts being to between $n and you!", ch, NULL, victim, TO_VICT); if (!check_dispel(level, victim, paf->type)){ paf->level -= 3; act("You manage to weaken $N's $t.", ch, skill_table[paf->type].name, victim, TO_CHAR); } damage( ch, victim, 5, sn, DAM_INTERNAL, TRUE ); }//end if not is gen void spell_change_sex( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; int sex = 0; if (number_percent() < 15) sex = 0; else if (victim->sex == 1) sex = 2; else if (victim->sex == 2) sex = 1; if ( is_affected( victim, sn )) { if (victim == ch) act("You've already been changed.",ch,NULL,victim,TO_CHAR); else act("$N has already had $s sex changed.",ch,NULL,victim,TO_CHAR); return; } if (saves_spell(level , victim,DAM_OTHER,skill_table[sn].spell_type)) return; act("$n doesn't look like $mself anymore...",victim,NULL,NULL,TO_ROOM); act_new("You feel different.", victim,NULL,NULL,TO_CHAR,POS_DEAD ); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 2 * level; af.location = APPLY_SEX; af.modifier = sex; af.bitvector = 0; affect_to_char( victim, &af ); } void spell_charm_person( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; int charmies = ch->pet ? 2 : 1; if (is_affected(ch, sn)){ send_to_char("Lacking power to charm another creature, you fail.\n\r", ch); return; } if (!can_follow(ch, ch)) return; if (is_safe(ch,victim)) return; if (get_charmed_by(ch) >= charmies && !IS_IMMORTAL(ch)){ send_to_char("You are already controlling as many as you can.\n\r",ch); return; } if (!IS_NPC(victim) && !IS_IMMORTAL(ch)) return; if (is_affected(victim,gsn_ecstacy)){ act("$N's mind must be open to suggestion.",ch,NULL,victim,TO_CHAR); return; } if ( victim == ch ){ send_to_char( "You like yourself even better!\n\r", ch ); return; } /* awake the person if they were sleeping */ if (!IS_AWAKE( victim )){ REMOVE_BIT(victim->affected_by, AFF_SLEEP ); do_wake( victim, ""); } if ( IS_AFFECTED(victim, AFF_CHARM) || IS_AFFECTED(ch, AFF_CHARM) || level < victim->level || victim->fighting != NULL || (IS_NPC(victim) && IS_SET(victim->act,ACT_AGGRESSIVE)) || IS_SET(victim->imm_flags,IMM_CHARM) || IS_UNDEAD(victim) || is_affected(victim, gsn_hypnosis)){ send_to_char("You failed.\n\r", ch); return; } if ( (check_immune(victim, DAM_CHARM, TRUE) < IS_NORMAL || victim->level > ch->level) && saves_spell( level, victim,DAM_CHARM,skill_table[sn].spell_type) ){ send_to_char("You failed.\n\r", ch); return; } if (is_affected(victim, gsn_horse) && monk_good(victim, WEAR_HEAD) && !IS_NPC(victim) && !IS_IMMORTAL(ch)) { ch->leader = victim; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (IS_NPC(ch) ? number_fuzzy( level / 4 ) : number_fuzzy( level / 8 ) ); af.location = 0; af.modifier = 0; af.bitvector = AFF_CHARM; affect_to_char( ch, &af ); act( "You reverse $n's attempt to charm you, and charm $M instead!", ch, NULL, victim, TO_VICT ); act("$N reverse your charm, and charms you instead!", ch, NULL, victim, TO_CHAR ); if ( ch->master ) stop_follower( ch ); add_follower( ch, victim ); act("$N looks at you with adoring eyes.",victim,NULL,ch,TO_CHAR); act("$N looks around with adoring eyes.",victim,NULL,ch,TO_NOTVICT); return; } if ( victim->master ) stop_follower( victim ); add_follower( victim, ch ); victim->leader = ch; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = (IS_NPC(victim) ? number_fuzzy( level / 4 ) : number_fuzzy( level / 8 ) ); af.location = 0; af.modifier = 0; af.bitvector = AFF_CHARM; affect_to_char( victim, &af ); act( "Isn't $n just so nice?", ch, NULL, victim, TO_VICT ); act("$N looks at you with adoring eyes.",ch,NULL,victim,TO_CHAR); act("$N looks around with adoring eyes.",ch,NULL,victim,TO_NOTVICT); if (IS_NPC(victim)){ victim->alignment = ch->alignment; victim->hunting = ch; } /* Set a wait affect on caster */ af.bitvector = 0; affect_to_char(ch, &af); } void spell_chill_touch( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const sh_int dam_each[] = { 0, 0, 0, 6, 7, 8, 9, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27 }; AFFECT_DATA af; int dam; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); dam = number_range( dam_each[level] / 2, dam_each[level] * 2 ); if ( !saves_spell( level, victim,DAM_COLD,skill_table[sn].spell_type ) ) { act("$n turns blue and shivers.",victim,NULL,NULL,TO_ROOM); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 6; af.location = APPLY_STR; af.modifier = -2; af.bitvector = 0; if (!is_affected(ch, af.type)) affect_to_char( victim, &af ); } else dam /= 2; damage( ch, victim, dam, sn, DAM_COLD,TRUE ); } void spell_colour_spray( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const sh_int dam_each[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 41, 42, 43, 44, 44, 45, 45, 46, 46, 47, 48, 49, 50, 51, 51, 52, 52, 53, 53, 54, 55, 56, 57, 58, 58, 59, 59, 60, 60, 61, 62, 63, 64, 65, 65, 66, 66, 67, 67, 68, 69 }; int dam; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); dam = number_range( dam_each[level] / 2, dam_each[level] * 2 ); if ( saves_spell( level, victim,DAM_LIGHT,skill_table[sn].spell_type) ) dam /= 2; else spell_blindness(skill_lookup("blindness"),level/2,ch,(void *) victim,TARGET_CHAR); damage( ch, victim, dam, sn, DAM_LIGHT,TRUE ); } void spell_continual_light(int sn,int level,CHAR_DATA *ch,void *vo,int target) { OBJ_DATA *light = create_object( get_obj_index( OBJ_VNUM_LIGHT_BALL ), 0); 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 ); } void spell_control_weather(int sn,int level,CHAR_DATA *ch,void *vo,int target) { if (!target_name[0] || !str_cmp( target_name, "better" ) ) { mud_data.weather_info.change += dice( level, 4 ); send_to_char( "The sky seems to clear up a bit.\n\r", ch ); } else if ( !str_cmp( target_name, "worse" ) ) { mud_data.weather_info.change -= dice( level, 4 ); send_to_char( "The sky seems to get cloudier.\n\r", ch ); } else send_to_char ("Do you want it to get better or worse?\n\r", ch ); } void spell_create_food( int sn, int level, CHAR_DATA *ch, void *vo,int target) { char* food[] = {"mushroom", "berry", "apple", "steak", "pig roast", "meal"}; const int i = number_range(0, 5); char buf[MIL]; OBJ_DATA *mushroom = create_object( get_obj_index( OBJ_VNUM_MUSHROOM ), 0); mushroom->value[0] = level / 2; mushroom->value[1] = level; /* change the short long and name */ sprintf(buf, mushroom->name, food[i]); free_string(mushroom->name); mushroom->name = str_dup(buf); sprintf(buf, mushroom->short_descr, food[i]); free_string(mushroom->short_descr); mushroom->short_descr = str_dup(buf); sprintf(buf, mushroom->description, food[i]); free_string(mushroom->description); mushroom->description = str_dup(buf); obj_to_room( mushroom, ch->in_room ); act( "$p suddenly appears.", ch, mushroom, NULL, TO_ALL ); } void spell_create_spring(int sn,int level,CHAR_DATA *ch,void *vo,int target) { OBJ_DATA *spring = create_object( get_obj_index( OBJ_VNUM_SPRING ), 0); spring->timer = level; obj_to_room( spring, ch->in_room ); act( "$p flows from the ground.", ch, spring, NULL, TO_ALL ); } void spell_create_water( int sn, int level, CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; int water; if ( obj->item_type != ITEM_DRINK_CON ) { send_to_char( "It is unable to hold water.\n\r", ch ); return; } if ( obj->value[2] != LIQ_WATER && obj->value[1] != 0 ) { send_to_char( "It contains some other liquid.\n\r", ch ); return; } water = UMIN( level * (mud_data.weather_info.sky >= SKY_RAINING ? 4 : 2), obj->value[0] - obj->value[1]); if ( water > 0 ) { obj->value[2] = LIQ_WATER; obj->value[1] += water; if ( !is_name( "water", obj->name ) ) { char buf[MSL]; sprintf( buf, "%s water", obj->name ); free_string( obj->name ); obj->name = str_dup( buf ); } act( "$p fills with water.", ch, obj, NULL, TO_CHAR ); } if ( obj->value[1] >= obj->value[0] ) { act( "$p is now full to the brim.", ch, obj, NULL, TO_CHAR ); return; } } void spell_cure_blindness(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; if ( !is_affected( victim, gsn_blindness ) ) { if (victim == ch) act("You aren't blind.",ch,NULL,victim,TO_CHAR); else act("$N doesn't appear to be blinded.",ch,NULL,victim,TO_CHAR); return; } if (check_dispel(level,victim,gsn_blindness)) { act_new("Your vision returns!",ch,NULL,victim,TO_VICT,POS_DEAD ); act("$N is no longer blinded.",ch,NULL,victim,TO_CHAR); if (!IS_NPC(ch) && !IS_NPC(victim) && ch->class == class_lookup("healer") && ch != victim) gain_exp(ch,number_range(1,ch->level/8)); } else act("You failed to cure $N's blindness.",ch,NULL,victim,TO_CHAR); } void spell_cure_critical( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal = dice(3, 8) + level - 6; //Embrace check. if (is_affected(victim, gsn_embrace_poison)) { if (embrace_heal_check(sn, level, ch, victim, heal)) affect_strip(victim, gsn_embrace_poison); else return; } if (!IS_NPC(ch) && !IS_NPC(victim) && ch->class == class_lookup("healer") && ch != victim && victim->hit < victim->max_hit) gain_exp(ch,number_range(2,ch->level/7)); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); act_new("You feel a lot better!", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act("You cure $N's critical wounds.", ch,NULL,victim,TO_CHAR ); } void spell_cure_disease( int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; bool fSick = FALSE; if ( is_affected( victim, gsn_plague ) ){ fSick = TRUE; if (check_dispel(level,victim,gsn_plague)){ if (!IS_NPC(ch) && !IS_NPC(victim) && ch->class == class_lookup("healer") && ch != victim) gain_exp(ch,number_range(1,ch->level/8)); } else act("You failed to remove $N's disease.",ch,NULL,victim,TO_CHAR); } if (is_affected( victim, gsn_drug_use) ){ fSick = TRUE; if (check_dispel(level,victim,gsn_drug_use)){ act("$n looks relieved as $e overcomes $s addiction.",victim,NULL,NULL,TO_ROOM); } else act("You failed to remove $N's addiction.",ch,NULL,victim,TO_CHAR); } if (!fSick){ if (victim == ch) act("You aren't ill.",ch,NULL,victim,TO_CHAR); else act("$N doesn't appear to be suffering.",ch,NULL,victim,TO_CHAR); return; } } void spell_cure_light( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal = dice(1, 8) + level / 3; if ((ch->class == class_lookup("dark-knight") || ch->class == class_lookup("ninja")) && victim != ch) { send_to_char("You can't use your talents to aid others.\n\r",ch); return; } if (!IS_NPC(ch) && !IS_NPC(victim) && ch->class == class_lookup("healer") && ch != victim && victim->hit < victim->max_hit) gain_exp(ch,number_range(1,ch->level/8)); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); //Embrace check. if (is_affected(victim, gsn_embrace_poison)) { if (embrace_heal_check(sn, level, ch, victim, heal)) affect_strip(victim, gsn_embrace_poison); else return; } else { act_new("You feel a little better.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act("You cure $N's light wounds.", ch,NULL,victim,TO_CHAR ); } } void spell_cure_poison( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; if ( !is_affected( victim, gsn_poison ) ) { if (victim == ch) act("You aren't poisoned.",ch,NULL,victim,TO_CHAR); else act("$N doesn't appear to be poisoned.",ch,NULL,victim,TO_CHAR); return; } if (check_dispel(level,victim,gsn_poison)) { act_new("A warm feeling runs through your body.",victim,NULL,NULL,TO_CHAR,POS_DEAD); act("$n looks much better.",victim,NULL,NULL,TO_ROOM); if (!IS_NPC(ch) && !IS_NPC(victim) && ch->class == class_lookup("healer") && ch != victim) gain_exp(ch,number_range(1,ch->level/8)); } else act("You failed to cure $N of $S poison.",ch,NULL,victim,TO_CHAR); } void spell_cure_serious( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal = dice(2, 8) + level /2 ; //Embrace check. if (is_affected(victim, gsn_embrace_poison)) { if (embrace_heal_check(sn, level, ch, victim, heal)) affect_strip(victim, gsn_embrace_poison); else return; } act_new("You feel better.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act("You cure $N's serious wounds.", ch,NULL,victim,TO_CHAR ); if (!IS_NPC(ch) && !IS_NPC(victim) && ch->class == class_lookup("healer") && ch != victim && victim->hit < victim->max_hit) gain_exp(ch,number_range(1,ch->level/7)); victim->hit = UMIN( victim->hit + heal, victim->max_hit ); update_pos( victim ); } void spell_curse( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_AFFECTED(victim,AFF_CURSE)) { act("$N is already cursed.",ch,NULL,victim,TO_CHAR); return; } if (victim->race == race_lookup("demon")) { send_to_char("You cannot curse that which is already dammed.\n\r", ch); return; } if (saves_spell(level,victim,DAM_NEGATIVE,skill_table[sn].spell_type)) { act("You fail to curse $N.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 20 + level/5; af.location = APPLY_HITROLL; af.modifier = -1 * (level / 8); af.bitvector = AFF_CURSE; affect_to_char( victim, &af ); af.location = APPLY_SAVING_SPELL; af.modifier = level / 8; affect_to_char( victim, &af ); act_new("You feel unclean.", ch,NULL,victim,TO_CHARVICT,POS_DEAD); if ( ch != victim ) act("$N looks very uncomfortable.",ch,NULL,victim,TO_CHAR); } void spell_demonfire(int sn, int level, CHAR_DATA *ch, void *vo,int target){ CHAR_DATA *victim = (CHAR_DATA *) vo; int dam = 2 * level + dice(2, 15); if (!IS_EVIL(ch) || IS_AFFECTED(ch, AFF_CALM)){ send_to_char("You lack the malice neccessary.\n\r", ch); return; } if (IS_EVIL(ch) && IS_EVIL(victim) && number_percent( ) < 50){ victim = ch; send_to_char("The demons turn upon you!\n\r",ch); } if (victim != ch ){ act("$n calls forth the demons of Hell upon $N!", ch,NULL,victim,TO_ROOM); act_new("$n has assailed you with the demons of Hell!", ch,NULL,victim,TO_VICT,POS_DEAD); act("You conjure forth the demons of Hell!",ch,NULL,victim,TO_CHAR); } if (ch != victim && victim->race == race_lookup("demon")){ act("Something is not right...", victim, NULL, NULL, TO_ROOM); send_to_char("You easly turn the demons away.\n\r", ch); victim = ch; } if ( saves_spell( level, victim, DAM_NEGATIVE,skill_table[sn].spell_type)) dam /= 2; damage( ch, victim, dam, sn, DAM_NEGATIVE ,TRUE); } void spell_detect_evil( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_EVIL) ) { if (victim == ch) act("You can already sense evil.",ch,NULL,victim,TO_CHAR); else act("$N can already detect evil.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_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 ); act_new( "Your eyes tingle.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act( "$N can now detect evil.", ch,NULL,victim,TO_CHAR ); } void spell_omnipotence( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected(victim, sn)){ act("You're already omnipotent.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level / 5; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act_new( "Your brain seems to itch for a moment.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); } void spell_detect_good( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_GOOD) ) { if (victim == ch) act("You can already sense good.",ch,NULL,victim,TO_CHAR); else act("$N can already detect good.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_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 ); act_new( "Your eyes tingle.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act( "$N can now detect good.", ch,NULL,victim,TO_CHAR ); } void spell_detect_invis( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_INVIS) ) { if (victim == ch) act("You can already see invisible objects.",ch,NULL,victim,TO_CHAR); else act("$N can already see invisible things.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = UMAX(8, level); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_INVIS; affect_to_char( victim, &af ); act_new( "Your eyes tingle.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act("$N can now see invisible things.",ch,NULL,victim,TO_CHAR); } void spell_detect_magic( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_DETECT_MAGIC) ) { if (victim == ch) act("You can already sense magical auras.",ch,NULL,victim,TO_CHAR); else act("$N can already detect magical auras.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_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 ); act_new( "Your eyes tingle.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act("$N can now detect magical auras.",ch,NULL,victim,TO_CHAR); } void spell_detect_traps( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected(victim, sn)) { if (victim == ch) act("You can already sense traps.",ch,NULL,victim,TO_CHAR); else act("$N can already detect traps.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level > 50 ? 72 : 24; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char( victim, &af ); act_new( "Your eyes tingle.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act("$N can now detect traps.",ch,NULL,victim,TO_CHAR); } void spell_dispel_evil( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if ( !IS_NPC(ch) && IS_EVIL(ch) ) victim = ch; if ( IS_GOOD(victim) ) { act( "$N is protected by $S goodness.", ch, NULL, victim, TO_ROOM ); return; } if ( IS_NEUTRAL(victim) ) { act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); return; } if (ch->class == class_lookup("healer")) dam = dice( level/5, 14 ); else dam = dice( level, 3 ); if ( saves_spell( level, victim,DAM_HOLY,skill_table[sn].spell_type) ) dam /= 2; damage( ch, victim, dam, sn, DAM_HOLY ,TRUE); } void spell_dispel_good( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { 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; } if ( IS_NEUTRAL(victim) ) { act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); return; } if (victim->hit > (ch->level * 4)) dam = dice( level, 3 ); else dam = UMAX(victim->hit, dice(level,3)); if ( saves_spell( level, victim,DAM_NEGATIVE,skill_table[sn].spell_type) ) dam /= 2; damage( ch, victim, dam, sn, DAM_NEGATIVE ,TRUE); } void spell_earthquake( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *vch, *vch_next; AFFECT_DATA* paf; bool fBurrow = FALSE; act( "The earth trembles beneath your feet!", ch, NULL, NULL, TO_CHAR ); act( "$n makes the earth tremble and shiver.", ch, NULL, NULL, TO_ROOM ); for ( vch = char_list; vch != NULL; vch = vch_next ) { vch_next = vch->next; if ( vch->in_room == NULL ) continue; if ( (paf = affect_find(vch->affected, gsn_burrow)) != NULL) { if (paf->modifier == ch->in_room->vnum) fBurrow = TRUE; } if ( vch->in_room == ch->in_room || fBurrow) { if ( vch != ch && !is_area_safe_quiet(ch,vch)) { if (fBurrow) send_to_char("The ground begins to heave and collapse around you!\n\r", vch); else m_yell(ch,vch,FALSE); if (IS_AFFECTED(vch,AFF_FLYING) && !is_affected(vch,gsn_thrash) && !fBurrow) damage(ch,vch,0,sn,DAM_BASH,TRUE); else if (is_affected(vch,gsn_burrow)) damage( ch,vch,2*(level + dice(2, 8)), sn, DAM_BASH,TRUE); else damage( ch,vch,level + dice(2, 8), sn, DAM_BASH,TRUE); } continue; } if ( vch->in_room->area == ch->in_room->area ) send_to_char( "The earth trembles and shivers.\n\r", vch ); } } void spell_enchant_armor( int sn, int level, CHAR_DATA *ch, void *vo,int target) { //object to be enchanted OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; //bool bool fHum = FALSE; //dice int result; //base chanc to fail int fail = 10; //bace ac bonus int ac_bonus = 0; //buffer used for ac added. int added; //bool flag bool ac_found = FALSE; bool raise = FALSE; //MODIFERS const int fail_per_ac = 3; //Chance increase per point of AC enchanted. const int lvl_mod = 1; //level mod const int glow_bon = -5; //bonus for glow const int bless_bon = 15; //bless bon. const int luck_mod = 2; //luck const int skill_mod = 1; //Divisor for skill > 75 //failure levels const int shatter_lvl = 6; //Item shatters if below chance/shatter_lvl const int fade_lvl = 5; //item fades const int lower_lvl = 2; //ac bonus is lowered by one. //We check first if the item is armor if (obj->item_type != ITEM_ARMOR) { send_to_char("That item is not an armor piece.\n\r",ch); return; } //and has to be in inv. if (obj->wear_loc != -1) { send_to_char("The item must be carried to be enchanted.\n\r",ch); return; } if (is_affected(ch, skill_lookup("calm"))) { send_to_char("You are in far to peacfull mood to think of violence.", ch); return; } if (obj->pIndexData->vnum == OBJ_VNUM_ARMORCRAFT){ send_to_char("It seems to resist your magics without effort.\n\r", ch); return; } //roll for items not enchanted yet. if (!obj->enchanted) { for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next ) { //we run through the affects checking for the one for ac. if ( paf->location == APPLY_AC ) { //make the pointers point to the ac_bonus so we can change it later. ac_bonus = paf->modifier; ac_found = TRUE; //chance to fail, lower is better. if (ac_bonus > 5) fHum =TRUE; fail += (ac_bonus * ac_bonus) * fail_per_ac; }//end if APPLY_AC else fail += 7; }//end for }//if not enchanted //check for objects already enchanted for ( paf = obj->affected; paf != NULL; paf = paf->next ) { if ( paf->location == APPLY_AC ) { ac_bonus = paf->modifier; ac_found = TRUE; //we increase chacne to fail based on what ac is now. if (ac_bonus > 5) fHum =TRUE; fail += (ac_bonus * ac_bonus) * fail_per_ac; }//and if APPLY_AC else //first enchant, we add base amount fail fail += 7; }//end for //we begin calculatin chances. fail -= level * lvl_mod; //bonus to blessed items. if (IS_OBJ_STAT(obj,ITEM_BLESS)) fail -= glow_bon; //bonus to glowing/already enchatned items. if (IS_OBJ_STAT(obj,ITEM_GLOW)) fail -= bless_bon; //luck modifier fail -= (get_curr_stat(ch,STAT_LUCK) - 16)*luck_mod; //skill mod fail -= (get_skill(ch, sn) - 75) / skill_mod; //ceiling. fail = URANGE(5,fail,85); //we caluclate the chance result = number_percent(); //now we applie results. if (result < (fail / shatter_lvl )) { act("$p flares blindingly... and evaporates!",ch,obj,NULL,TO_ALL); extract_obj(obj); return; } else if (result < (fail / fade_lvl)) { AFFECT_DATA *paf_next; act("$p glows brightly, then fades.",ch,obj,NULL,TO_ALL); //we remove all affects. obj->enchanted = TRUE; for (paf = obj->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; //not the owner effect. if (paf->type == gen_has_owner) continue; free_affect(paf); } obj->affected = NULL; REMOVE_BIT(obj->extra_flags,ITEM_GLOW); REMOVE_BIT(obj->extra_flags,ITEM_HUM); REMOVE_BIT(obj->extra_flags,ITEM_MAGIC); return; } //increase ac. else if ( result < (fail/lower_lvl)) raise = TRUE; else if ( result <= fail) { send_to_char("Nothing seemed to happen.\n\r",ch); return; } if (!obj->enchanted) { AFFECT_DATA *af_new; obj->enchanted = TRUE; for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next) { af_new = new_affect(); af_new->next = obj->affected; obj->affected = af_new; af_new->where= paf->where; af_new->type = UMAX(0,paf->type); af_new->level= paf->level; af_new->duration= paf->duration; af_new->location= paf->location; af_new->modifier= paf->modifier; af_new->bitvector= paf->bitvector; } } if (result <= (90 - level/5)) { if (!raise) { //we roll for a chance to really raise it. if (number_percent() < 75) { act("$p shimmers with a gold aura.",ch,obj,NULL,TO_ALL); added = -1; } else { act("$p shivers and sizzles with sudden heat!",ch,obj,NULL,TO_ALL); added = 1; } } else { act("$p begins to shimmer with a gold aura then suddenly begins to smoke!.",ch,obj,NULL,TO_ALL); added = 1; } SET_BIT(obj->extra_flags, ITEM_MAGIC); } else { if (!raise) { act("$p glows a brillant gold!",ch,obj,NULL,TO_ALL); if (!IS_SET(obj->extra_flags,ITEM_GLOW)) SET_BIT(obj->extra_flags,ITEM_GLOW); else SET_BIT(obj->extra_flags,ITEM_HUM); added = -2; } else { act("$p shivers and sizzles with heat!",ch,obj,NULL,TO_ALL); added = 2; } SET_BIT(obj->extra_flags, ITEM_MAGIC); } if (obj->level < LEVEL_HERO) obj->level = UMIN(LEVEL_HERO - 1,obj->level + 1); if (ac_found) { for ( paf = obj->affected; paf != NULL; paf = paf->next) if ( paf->location == APPLY_AC) { paf->type = sn; paf->modifier += added; if (fHum && added < 0) SET_BIT(obj->extra_flags,ITEM_HUM); paf->level = UMAX(paf->level,level); } } else { paf = new_affect(); paf->where= TO_OBJECT; paf->type= sn; paf->level= level; paf->duration= -1; paf->location= APPLY_AC; paf->modifier= added; paf->bitvector = 0; paf->next= obj->affected; obj->affected= paf; } }//end enchant armor void spell_enchant_weapon(int sn,int level,CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA* paf; char buf [MIL]; char color [MIL]; //Data for the process int enchant_bonus = 0; int total_enchant = 0; int hit_bonus = 0; int dam_bonus = 0; int tot_dam = 0; int tot_hit = 0; int chance = number_percent(); //spell fails if chance is greater then fail int fail = 5; //holds which type of enchant we are doing. int enchant_type = APPLY_NONE; //modifiers const int lvl_mod = 1; const int Bless_mod = 15; const int EvilItem_mod = 15; const int glow_mod = 10; const int hum_mod = 5; const int intwis_mod = 2; const int luck_mod = 2; const int skill_mod = 1; //Skill mod const int limit_mod = 5; //modifier for over 6 enchant (over 6)^2*limit_mod const int good_mod = -20; //modifer in percent for chance to get damage if good. const int evil_mod = 20; //modifer in percent for chance to get damage if evil. int align_med = 50; //median //levels in percent const int shatter_lvl = 3;//destroy const int fry_lvl = 15;//lower DAMTYPE or DAMDICE const int fade_lvl = 30;//fade weapon const int lower2_lvl = 45;//lower affect by 1 or 2 const int lower_lvl = 65;//lower affect by 1 or 2 const int nothing_lvl = 100;//nothin //Level to enchant single is >fail // const int single_lvl = 60;//single poit raise to hit or dam int double_lvl = 100 - level/5;//double raise to hit or dam //flags bool blow = FALSE; bool lower = FALSE; bool enchant_found = FALSE; bool ch_evil = FALSE; bool ch_good = FALSE; //first we check if this is a weapon if (obj->item_type != ITEM_WEAPON){ send_to_char("That item is not a weapon.\n\r",ch); return; } if (obj->wear_loc != WEAR_NONE) { send_to_char("The item must be carried to be enchanted.\n\r",ch); return; } if (is_affected(ch, skill_lookup("calm"))) { send_to_char("You are in far to peaceful mood to think of violence.", ch); return; } //Malform weapon check. if (affect_find(obj->affected, gen_malform) || obj->pIndexData->vnum == OBJ_VNUM_WEAPONCRAFT) { act("$p seems to soak the spell right up with no other visible effect.", ch, obj, NULL, TO_ALL); return; } //now we check align of char. //and modifiy chance for damroll enchantement. //and the color stored in color if (ch->alignment <= EVIL_THRESH) { ch_evil = TRUE; align_med += evil_mod; } else if (ch->alignment >GOOD_THRESH) { ch_good = TRUE; align_med += good_mod; } //we roll if this is going to be enchant of hit or damage if (chance < align_med) { enchant_type = APPLY_DAMROLL; sprintf(color, "red aura"); } else { sprintf(color, "blue aura"); enchant_type = APPLY_HITROLL; } //we randomize again to be sure of good distribution. chance = number_percent(); //we check if an enchatement exits already if (!obj->enchanted) { for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next ) if ( paf->location == APPLY_DAMROLL ) { if (paf->location == enchant_type) enchant_found = TRUE; //we add all the existing enchants up. dam_bonus = paf->modifier; tot_dam += dam_bonus; fail += 2 * (dam_bonus * dam_bonus); } else if ( paf->location == APPLY_HITROLL ) { if (paf->location == enchant_type) enchant_found = TRUE; //we add all the existing enchants up. hit_bonus = paf->modifier; tot_hit += hit_bonus; fail += 2 * (hit_bonus * hit_bonus); } } //We scan regular way now to get the total of effects on obj. for ( paf = obj->affected; paf != NULL; paf = paf->next ) { if ( paf->location == APPLY_DAMROLL ) { if (paf->location == enchant_type) enchant_found = TRUE; //we add all the existing enchants up. dam_bonus = paf->modifier; tot_dam += dam_bonus; fail += 2 * (dam_bonus * dam_bonus); } else if ( paf->location == APPLY_HITROLL ) { if (paf->location == enchant_type) enchant_found = TRUE; //we add all the existing enchants up. hit_bonus = paf->modifier; tot_hit += hit_bonus; fail += 2 * (hit_bonus * hit_bonus); } } //we average out the enchants total_enchant = (tot_hit + tot_dam)/2; //we now have total enchants already on the item. //start caluclating chances. //the higher "fail" the smaller chance to enchant and greater risk. //level bonus fail -= level * lvl_mod; //skill mod fail -= (get_skill(ch, sn) - 75) / skill_mod; //smarts bonus fail -=( ((get_curr_stat(ch, STAT_INT) - 21) + (get_curr_stat(ch, STAT_WIS) - 21) ) / 2) * intwis_mod; //penalty for objects of higher level then caster. if (obj->level > level) fail += (obj->level - level) * lvl_mod; //Align things. if (IS_OBJ_STAT(obj,ITEM_BLESS) && ch_good) {fail -= Bless_mod;chance+=Bless_mod/2;} if (IS_OBJ_STAT(obj,ITEM_EVIL) && ch_evil) {fail -= EvilItem_mod;chance+=EvilItem_mod/2;} if (IS_OBJ_STAT(obj,ITEM_GLOW)) fail += glow_mod; if (IS_OBJ_STAT(obj,ITEM_HUM)) fail += hum_mod; //penalty for superduper lvl enchant. //penalty for average, or high singulars. if (total_enchant >= 5 || (tot_hit > 5 || tot_dam > 5)) fail+= (total_enchant - 4) * (total_enchant - 4) * limit_mod; //ceiling for super dupers enchants. if (total_enchant >= 7 || (tot_hit >=7 || tot_dam >= 7)) blow = TRUE; //check for manacharge if ((paf = affect_find(obj->affected, gen_mana_charge)) != NULL) blow = TRUE; //luck bonus fail -= (get_curr_stat(ch,STAT_LUCK) - 16) * luck_mod; //ceiling fail = URANGE(5,fail,90); chance = URANGE(0,chance,100); //DEBUG //sprintf(buf, "Enchnat: Chance= %d, Fail = %d \n\r", chance, fail); //send_to_char(buf, ch); //begin enchanting, from worst to best. //shatter if ( (chance < (shatter_lvl * fail /100)) || (chance <= 3) || (blow && (chance >= nothing_lvl * fail / 100)) ) { act("$p shivers violently and shatters into a million pieces!",ch,obj,NULL,TO_ALL); extract_obj(obj); return; } //fry ie: lower weapon dice. else if (chance < (fry_lvl * fail /100) || (chance <= 8)) { //50:50 act("$p shivers and smokes with sudden heat.",ch,obj,NULL,TO_ALL); if (number_percent() < 50) { //we try to fand first die, if cant we try second. if (obj->value[1] > 1) obj->value[1]--; else if (obj->value[2] > 1) obj->value[2]--; } else { //we try to fadie SECOND die if not then try first. if (obj->value[2] > 1) obj->value[2]--; else if (obj->value[1] > 1) obj->value[1]--; } return; } //fade, remove all enchants else if (chance < (fade_lvl * fail /100)) { AFFECT_DATA *paf_next; act("$p flares with blinding light, then quickly fades.",ch,obj,NULL,TO_ALL); obj->enchanted = TRUE; for (paf = obj->affected; paf != NULL; paf = paf_next) { paf_next = paf->next; //not the owner effect. if (paf->type == gen_has_owner) continue; free_affect(paf); } obj->affected = NULL; REMOVE_BIT(obj->extra_flags,ITEM_GLOW); REMOVE_BIT(obj->extra_flags,ITEM_HUM); REMOVE_BIT(obj->extra_flags,ITEM_MAGIC); return; } //lower, the enchant is inverted else if (chance < (lower_lvl * fail /100)) lower = TRUE; //nothing else if (chance < (nothing_lvl * fail /100)) { send_to_char("Nothing seemed to happen.\n\r",ch); return; } //begin enchanting, inverse or regular.notice these are not elseif now. //double enchant with a check for double fade. if ((chance >= double_lvl) || (lower && (chance < (lower2_lvl * fail /100))) ) { //jackpot check if (chance >=99) { sprintf(buf, "The room is painted with a %s as $p flares with arcane power!",color); enchant_bonus = 3; }//end if jackpot, begin regualr. else { enchant_bonus = 2; if (lower) { enchant_bonus *= -1; sprintf(buf, "$p glows with a %s then shudders violently and fades.",color); } else sprintf(buf, "$p glows with a brilliant %s.",color); }//end else if not jackpot //we shoot out the message. act(buf,ch,obj,NULL,TO_ALL); }//end double enchant //regular 1 point enchant, else if ( (chance >= fail) || lower) { enchant_bonus = 1; //we include the color of enchantement here. if (lower) { enchant_bonus *= -1; sprintf(buf, "$p glows with a %s then quickly fades to gray.",color); } else sprintf(buf, "$p glows with a %s.",color); //we shoot out the message. act(buf,ch,obj,NULL,TO_ALL); }//end single enchant //now we actualuy modify the effects. //first set the glow/hum/magic flags. if (obj->level < LEVEL_HERO - 1) obj->level = UMIN(LEVEL_HERO - 1,obj->level + 1); //always set SET_BIT(obj->extra_flags, ITEM_MAGIC); //set only if bonus is greater then 1 if (enchant_bonus > 1) SET_BIT(obj->extra_flags,ITEM_GLOW); //set if total enchant is more then 4 on obj, if (total_enchant > 4) SET_BIT(obj->extra_flags,ITEM_HUM); //now we slap down the effects. //If object was not previously affected we copy affects. if (!obj->enchanted) { AFFECT_DATA *af_new; obj->enchanted = TRUE; for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next) { af_new = new_affect(); af_new->next = obj->affected; obj->affected = af_new; af_new->where= paf->where; af_new->type = UMAX(0,paf->type); af_new->level= paf->level; af_new->duration= paf->duration; af_new->location= paf->location; af_new->modifier= paf->modifier; af_new->bitvector= paf->bitvector; af_new->has_string = paf->has_string; af_new->string = paf->string; } } if (enchant_found) { for ( paf = obj->affected; paf != NULL; paf = paf->next) if ( paf->location == enchant_type) { paf->type = sn; paf->modifier += enchant_bonus; paf->level = UMAX(paf->level,level); } }//end if already enchatned. else { paf = new_affect(); paf->where= TO_OBJECT; paf->type= sn; paf->level= level; paf->location = enchant_type; paf->duration= -1; paf->modifier = enchant_bonus; paf->bitvector = 0; paf->next= obj->affected; obj->affected= paf; }//done if no similiar enchants. }//edn spell_enchant_weapon void spell_energy_drain( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if ( saves_spell( level , victim,DAM_NEGATIVE,skill_table[sn].spell_type) ) { act("You failed to drain $N's energy.",ch,NULL,victim,TO_CHAR); act_new("You feel a momentary chill.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); return; } if ( victim->level <= 2 ){ act("$n withers before your eyes as all his energy is sucked away.", victim, NULL, NULL, TO_ROOM); dam = ch->hit + 1; } else { gain_exp( victim, 0 - number_range( level/2, 3 * level / 2 ) ); victim->mana /= 2; victim->move /= 2; dam = dice(1, level); ch->hit += dam; } act_new("You feel your life slipping away!",ch,NULL,victim,TO_CHARVICT,POS_DEAD); act("What a rush!",ch,NULL,victim,TO_CHAR); damage( ch, victim, dam, sn, DAM_NEGATIVE ,TRUE); } void spell_drained( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim, sn)) return; if ( ch != victim && saves_spell( level , victim,DAM_NEGATIVE,skill_table[sn].spell_type) ) { act("You failed to drain $N's vitality.",ch,NULL,victim,TO_CHAR); act_new("You feel a momentary weakness.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); return; } act_new("You feel your vitality slipping away!",ch,NULL,victim,TO_CHARVICT,POS_DEAD); if (ch != victim) act("You drain $N of $S vitality!",ch,NULL,victim,TO_CHAR); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level / 8; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = 0; affect_to_char( victim, &af ); } void spell_fireball( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { int dam; int save; CHAR_DATA *vch, *vch_next; static const sh_int dam_each[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 35, 40, 45, 50, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 69, 71, 73, 75, 80, 85, 90, 95, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110 }; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); for (vch = ch->in_room->people; vch != NULL; vch = vch_next){ int res = check_immune(vch, DAM_FIRE, FALSE); vch_next = vch->next_in_room; dam = number_range(dam_each[level], dam_each[level] * 2 ); if (res != IS_VULNERABLE && ch->race == grn_demon) dam *= 1.2; //the higher the victim saves, the less damage fireball does save = URANGE(25, calc_saves(level, vch, DAM_FIRE, SPELL_AFFLICTIVE), 95); //adjust saves for magic vulnerability, they already take +50% damage as is if (res == IS_VULNERABLE) save += 15; dam = (200 - 2 * save) * dam / 100; if ( vch != ch && !is_area_safe(ch,vch)){ m_yell(ch,vch,FALSE); damage( ch, vch, dam, sn, DAM_FIRE ,TRUE); } } } void spell_flamestrike( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; CHAR_DATA *vch, *vch_next; int dam; bool fAdv = ch->class == class_lookup("paladin"); for (vch = ch->in_room->people; vch; vch = vch_next ){ vch_next = vch->next_in_room; if (vch == ch || vch == victim) continue; else if (!fAdv && vch != victim) continue; if ( (is_same_group(victim, vch) || (vch->fighting && vch->fighting == ch)) && !is_area_safe_quiet(ch, vch )){ if (vch != victim) m_yell(ch, vch, FALSE ); dam = level + dice(level / 5, 6); if ( saves_spell( level, vch,DAM_FIRE,skill_table[sn].spell_type) ) dam /= 2; fire_effect(vch, ch->level, dam, TARGET_CHAR); damage( ch, vch, dam, sn, DAM_FIRE ,TRUE); } } /* make sure we are fighting the victim when this ends */ if ( saves_spell( level, victim,DAM_FIRE,skill_table[sn].spell_type) ) dam /= 2; dam = level + dice(level / 5, 6); set_fighting( ch, victim ); fire_effect(victim, ch->level, dam, TARGET_CHAR); damage( ch, victim, dam, sn, DAM_FIRE ,TRUE); } void spell_faerie_fire( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_FAERIE_FIRE) || victim->race == race_lookup("faerie")) { if (victim == ch) act("You are already outlined in pink.",ch,NULL,victim,TO_CHAR); else act("$N is already outlined in pink.",ch,NULL,victim,TO_CHAR); return; } if ( saves_spell( level, victim,DAM_OTHER,skill_table[sn].spell_type) ) { act("You failed to outline $N in pink.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 10; af.location = APPLY_AC; af.modifier = level; af.bitvector = AFF_FAERIE_FIRE; affect_to_char( victim, &af ); affect_strip ( victim, gsn_invis ); affect_strip ( victim, gsn_mass_invis ); if ( IS_NPC(victim) || !IS_SET(race_table[victim->race].aff,AFF_SNEAK) ) { affect_strip ( victim, gsn_sneak ); REMOVE_BIT ( victim->affected_by, AFF_SNEAK ); } REMOVE_BIT ( victim->affected_by, AFF_HIDE ); REMOVE_BIT ( victim->affected_by, AFF_INVISIBLE ); affect_strip(victim,gsn_camouflage); REMOVE_BIT ( victim->affected2_by, AFF_CAMOUFLAGE ); act_new( "You are surrounded by a pink outline.", victim, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n is surrounded by a pink outline.", victim, NULL, NULL, TO_ROOM ); } void spell_faerie_fog( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *ich; act( "$n conjures a cloud of yellow dust.", ch, NULL, NULL, TO_ROOM ); act( "You conjure a cloud of yellow dust.", ch, NULL, NULL, TO_CHAR ); for ( ich = ch->in_room->people; ich != NULL; ich = ich->next_in_room ) { AFFECT_DATA af; if ( IS_AFFECTED(ich, AFF_FAERIE_FOG) || ich->race == race_lookup("faerie")) continue; if (ich->invis_level > 0) continue; if ( ich == ch || is_safe(ch,ich) || saves_spell( level, ich,DAM_OTHER,skill_table[sn].spell_type) ) continue; a_yell( ch, ich ); affect_strip ( ich, gsn_invis ); affect_strip ( ich, gsn_mass_invis ); if ( IS_NPC(ich) || !IS_SET(race_table[ich->race].aff,AFF_SNEAK) ) { affect_strip ( ich, gsn_sneak ); REMOVE_BIT ( ich->affected_by, AFF_SNEAK ); } REMOVE_BIT ( ich->affected_by, AFF_HIDE ); REMOVE_BIT ( ich->affected_by, AFF_INVISIBLE ); affect_strip(ich,gsn_camouflage); REMOVE_BIT ( ich->affected2_by, AFF_CAMOUFLAGE ); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 10; af.location = 0; af.modifier = 0; af.bitvector = AFF_FAERIE_FOG; affect_to_char( ich, &af ); act_new( "You start glowing.", ich, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n starts glowing.", ich, NULL, NULL, TO_ROOM ); } } void spell_fly( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && !IS_IMMORTAL(ch)) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if ( IS_AFFECTED(victim, AFF_FLYING) ) { if (victim == ch) act("You are already airborne.",ch,NULL,victim,TO_CHAR); else act("$N doesn't need your help to fly.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level + 3; af.location = 0; af.modifier = 0; af.bitvector = AFF_FLYING; affect_to_char( victim, &af ); act_new( "Your feet rise off the ground.", victim, NULL,NULL, TO_CHAR, POS_DEAD ); act( "$n's feet rise off the ground.", victim, NULL, NULL, TO_ROOM ); } void spell_frenzy(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim,sn) || IS_AFFECTED(victim,AFF_BERSERK)) { if (victim == ch) act("You are already in a frenzy.",ch,NULL,victim,TO_CHAR); else act("$N is already in a frenzy.",ch,NULL,victim,TO_CHAR); return; } if (is_affected(victim,skill_lookup("calm")) || is_affected(victim,gsn_prayer)) { if (victim == ch) act("Why don't you just relax for a while?",ch,NULL,victim,TO_CHAR); else act("$N doesn't look like $e wants to fight anymore.", ch,NULL,victim,TO_CHAR); return; } 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; } if ( is_affected( victim, gsn_blasphemy ) ) { sendf(ch, "%s's faith have been lost.\n\r", PERS(victim,ch)); return; } af.where = TO_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); act_new("You are filled with holy wrath!",victim,NULL,NULL,TO_CHAR,POS_DEAD); act("$n gets a wild look in $s eyes!",victim,NULL,NULL,TO_ROOM); } void spell_gate( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim; bool gate_pet; if (IS_AFFECTED2(ch, AFF_SHADOWFORM)) { REMOVE_BIT(ch->affected2_by, AFF_SHADOWFORM); affect_strip(ch, gsn_shadowform); act("Your body regains its substance, and you materialize into existence.",ch,NULL,NULL,TO_CHAR); act("$n's body regains its substance, and $e materializes into existence.",ch,NULL,NULL,TO_ROOM); WAIT_STATE(ch, 24); } 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_PRIVATE) || ((IS_SET(victim->in_room->room_flags, ROOM_SAFE) || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) || IS_SET(victim->in_room->room_flags, ROOM_NO_GATEIN) || IS_SET(ch->in_room->room_flags, ROOM_NO_GATEOUT) || IS_SET(victim->in_room->room_flags, ROOM_NO_INOUT) || IS_SET(ch->in_room->room_flags, ROOM_NO_INOUT) || IS_SET(ch->in_room->area->area_flags, AREA_NOMORTAL) || IS_SET(victim->in_room->area->area_flags, AREA_NOMORTAL) || IS_SET(ch->in_room->area->area_flags, AREA_RESTRICTED) || IS_SET(victim->in_room->area->area_flags, AREA_RESTRICTED) || victim->level >= level + 5 || (!IS_NPC(victim) && victim->level > LEVEL_HERO) || (!IS_IMMORTAL(ch) && IS_IMMORTAL(victim)) || (IS_NPC(victim) && (IS_AFFECTED(victim,AFF_CHARM) && victim->master != NULL && victim->in_room == victim->master->in_room && !is_pk(ch,victim->master)) ) || (!IS_NPC(victim) && IS_SET(victim->act,PLR_NOSUMMON) && !is_pk(ch,victim)) || is_affected(victim,gen_watchtower) || is_affected(victim,gsn_coffin) || is_affected(victim,gsn_entomb) || is_affected(ch, gsn_tele_lock) || is_affected(victim,gsn_catalepsy) || (saves_spell( level- 5, victim,DAM_OTHER,skill_table[sn].spell_type) ) ) && !IS_IMMORTAL(ch))) { send_to_char("Something blocks the spell.\n\r",ch); return; } else if (is_affected(ch,gen_ensnare)){ send_to_char("You sense a powerful magical field preventing your departure.\n\r", ch); return; } else if (!IS_NPC(victim) && !IS_IMMORTAL(ch)){ send_to_char("Your target moves away before you complete the spell.\n\r", ch); return; } if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL) { send_to_char("You mount refuses to enter the gate.\n\r",ch); return; } if (ch->pet != NULL && ch->in_room == ch->pet->in_room && ch->pet->pIndexData->vnum != MOB_VNUM_SPECIAL_GUARD) gate_pet = TRUE; else gate_pet = FALSE; if (ch->invis_level < LEVEL_HERO) { act("$n steps through a gate and vanishes.",ch,NULL,NULL,TO_ROOM); act("You step through a gate and vanish.",ch,NULL,NULL,TO_CHAR); } else { act("$n steps through a gate and vanishes.",ch,NULL,NULL,TO_IMMROOM); act("You step through a gate and vanish.",ch,NULL,NULL,TO_CHAR); } char_from_room(ch); char_to_room(ch,victim->in_room); if (ch->invis_level < LEVEL_HERO) act("$n has arrived through a gate.",ch,NULL,NULL,TO_ROOM); else act("$n has arrived through a gate.",ch,NULL,NULL,TO_IMMROOM); do_look(ch,"auto"); if (gate_pet) { act("$n steps through a gate and vanishes.",ch->pet,NULL,NULL,TO_ROOM); act("You step through a gate and vanish.",ch->pet,NULL,NULL,TO_CHAR); 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"); } } void spell_giant_strength(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (ch->class == class_lookup("psionicist") && ch != victim) { send_to_char("You can only cast this spell on yourself.\n\r", ch); return; } if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && !IS_IMMORTAL(ch)) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if ( is_affected( victim, sn ) ) { if (victim == ch) act("You are already as strong as you can get!",ch,NULL,victim,TO_CHAR); else act("$N can't get any stronger.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level; af.location = APPLY_STR; af.modifier = level / 10; af.bitvector = 0; affect_to_char( victim, &af ); act_new( "Your muscles surge with heightened power!", victim,NULL,NULL,TO_CHAR,POS_DEAD ); act("$n's muscles surge with heightened power.",victim,NULL,NULL,TO_ROOM); } void spell_harm( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam = UMAX( 20, victim->hit - dice(1,4) ); if ( saves_spell( level, victim,DAM_HARM,skill_table[sn].spell_type) ) dam = UMIN( 50, dam / 2 ); dam = UMIN( 100, dam ); damage( ch, victim, dam, sn, DAM_HARM ,TRUE); } void spell_haste( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && !IS_IMMORTAL(ch)) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if ( is_affected( victim, sn ) || IS_AFFECTED(victim,AFF_HASTE) || IS_SET(victim->off_flags,OFF_FAST)) { if (victim == ch) act("You can't move any faster!",ch,NULL,victim,TO_CHAR); else act("$N is already moving as fast as $E can.", ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; if (victim == ch) af.duration = 1 + level/2; else af.duration = 1 + level/4; af.location = APPLY_DEX; af.modifier = 1 + (level >= 18) + (level >= 25) + (level >= 32); af.bitvector = AFF_HASTE; affect_to_char( victim, &af ); act_new( "You feel yourself moving more quickly.", victim,NULL,NULL,TO_CHAR,POS_DEAD); act("$n is moving more quickly.",victim,NULL,NULL,TO_ROOM); } void spell_heal( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; //Embrace check. if (is_affected(victim, gsn_embrace_poison)) { if (embrace_heal_check(sn, level, ch, victim, 100)) affect_strip(victim, gsn_embrace_poison); else return; } act_new( "A warm feeling fills your body.", ch,NULL,victim,TO_CHARVICT,POS_DEAD ); if ( ch != victim ) act( "You heal $N.", ch,NULL,victim,TO_CHAR ); if (!IS_NPC(ch) && !IS_NPC(victim) && ch->class == class_lookup("healer") && ch != victim && victim->hit < victim->max_hit) gain_exp(ch,number_range(2,ch->level/5)); victim->hit = UMIN( victim->hit + 100, victim->max_hit ); update_pos( victim ); } /* used in spell_wrath */ void spell_holy_word(int sn, int level, CHAR_DATA *ch, void *vo,int target){ AFFECT_DATA af; if (is_affected(ch, sn)){ send_to_char("You've already spoken the Divine Word.\n\r", ch); return; } act("$n's eyes glow slightly as $e utters a Divine Word!",ch,NULL,NULL,TO_ROOM); act("Your mind fills with holy wrath as the Divine Word escapes your lips!",ch,NULL,NULL,TO_CHAR); af.type = sn; af.level = level; af.duration = level / 6; af.where = TO_AFFECTS; af.bitvector = 0; af.location = APPLY_MANA_GAIN; af.modifier = -25; affect_to_char(ch, &af); } /* SPELL HURRICANE General effects: light damage, possible air_thrash to flying, area. Coded By: Athaekeetha */ void spell_hurricane( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *vch, *vch_next; // victim char data AFFECT_DATA af; // affect data (for air_thrash) int dam = 0; /* loop over each player in the room */ for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; /* if victim is safe, continue to next victim */ if (is_safe(ch,vch)) continue; /* if victim is charmie's master, goto next victim */ if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == vch ) { sendf(ch, "%s is your beloved master.\n\r", PERS(vch,ch) ); continue; } /* if victim is not caster, and they are not in a safe area, victim is hit */ if ( vch == ch || is_area_safe(ch,vch)) continue; m_yell(ch,vch,FALSE); dam = 50 + dice( 6, 3 ) * level / 6; /* if the victim saves vs. the spell, goto next victim */ if ( saves_spell( level, vch, DAM_AIR, skill_table[sn].spell_type) ) { dam /= 2; } /* damage the victim */ damage( ch, vch, dam, sn, DAM_AIR, TRUE); /* air thrash the victim if flying */ if (IS_AFFECTED(vch, AFF_FLYING) && !is_affected(vch, gsn_thrash)){ af.where = TO_AFFECTS; af.type = gsn_thrash; af.level = ch->level; af.duration = 0; af.modifier = 0; af.location = 0; af.bitvector = 0; affect_to_char(vch,&af); act("You can't seem to get back into the air",vch,NULL,NULL,TO_CHAR); act("$n can't seem to get back into the air",vch,NULL,NULL,TO_ROOM); } } } void spell_identify( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { OBJ_DATA *obj = (OBJ_DATA*) vo; int i; AFFECT_DATA *paf; AFFECT_DATA *pbuf = NULL; bool extract = FALSE; if (obj == NULL){ if (IS_NULLSTR(target_name)){ send_to_char("Identify what object in room or inventory?\n\r", ch); return; } else if ( (obj = get_obj_carry(ch, target_name, ch)) == NULL && (obj = get_obj_list( ch, target_name, ch->in_room->contents )) == NULL){ send_to_char("It doesn't appear to be here.\n\r", ch); return; } } if (obj->pIndexData->vnum == OBJ_VNUM_CLONE){ extract = TRUE; obj = create_object( get_obj_index(obj->cost), obj->level); } sendf( ch,"Object '%s' is type %s, material %s.\n\rExtra flags: %s.\n\rWeight is %d, value is %d, level is %d.\n\r", obj->name, item_name(obj->item_type), obj->material, extra_bit_name( obj->extra_flags ), obj->weight / 10, obj->cost, obj->level); switch ( obj->item_type ) { case ITEM_SOCKET: if (IS_SOC_STAT(obj, SOCKET_ARMOR) && IS_SOC_STAT(obj, SOCKET_WEAPON)) act("Armor and Weapon socket.", ch, obj, NULL, TO_CHAR); else if (IS_SOC_STAT(obj, SOCKET_ARMOR)) act("Armor only socket.", ch, obj, NULL, TO_CHAR); else if (IS_SOC_STAT(obj, SOCKET_WEAPON)) act("Weapon only socket.", ch, obj, NULL, TO_CHAR); else act("Weapon only socket.", ch, obj, NULL, TO_CHAR); if (obj->value[1]) sendf(ch, "Adds following to extra flags: %s\n\r", flag_string( extra_flags, obj->value[1] ) ); if (obj->value[4]) sendf(ch, "Adds following to weapon flags: %s\n\r", flag_string( weapon_type2, obj->value[4] ) ); break; case ITEM_SCROLL: case ITEM_ARTIFACT: case ITEM_POTION: case ITEM_PILL: sendf( ch, "Level %d spells of:", obj->value[0] ); for ( i = 1; i <= 4; i++ ) if ( obj->value[i] >= 0 && obj->value[i] < MAX_SKILL && skill_table[obj->value[i]].name != NULL) sendf(ch, " '%s'", skill_table[obj->value[i]].name); send_to_char( ".\n\r", ch ); break; case ITEM_WAND: case ITEM_STAFF: if (skill_table[obj->value[3]].name == NULL) break; sendf( ch, "Has %d charges of level %d", obj->value[2], obj->value[0] ); if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL ) sendf(ch, " '%s'.\n\r", skill_table[obj->value[3]].name); break; case ITEM_THROW: sendf( ch, "Has %d %s left.\n\r",obj->value[0],obj->short_descr); if (obj->pIndexData->new_format) sendf(ch,"Damage is %dd%d (average %d).\n\r", obj->value[1],obj->value[2], (1 + obj->value[2]) * obj->value[1] / 2); else sendf( ch, "Damage is %d to %d (average %d).\n\r", obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 ); break; case ITEM_DRINK_CON: sendf(ch,"It holds %s-colored %s.\n\r", liq_table[obj->value[2]].liq_color, liq_table[obj->value[2]].liq_name); break; case ITEM_CONTAINER: sendf(ch,"Capacity: %d# Maximum weight: %d# flags: %s\n\r", obj->value[3], obj->value[0], cont_bit_name(obj->value[1])); if (obj->value[4] != 100) sendf(ch,"Weight multiplier: %d%%\n\r", obj->value[4]); break; case ITEM_WEAPON: send_to_char("Weapon type is ",ch); if (IS_WEAPON_STAT(obj, WEAPON_TWO_HANDS) ) send_to_char("two-handed ", ch); switch (obj->value[0]) { case(WEAPON_EXOTIC) : send_to_char("exotic.\n\r",ch); break; case(WEAPON_SWORD) : send_to_char("sword.\n\r",ch); break; case(WEAPON_DAGGER) : send_to_char("dagger.\n\r",ch); break; case(WEAPON_SPEAR) : send_to_char("spear.\n\r",ch); break; case(WEAPON_STAFF) : send_to_char("staff.\n\r",ch); break; case(WEAPON_MACE) : send_to_char("mace/club.\n\r",ch); break; case(WEAPON_AXE) : send_to_char("axe.\n\r",ch); break; case(WEAPON_FLAIL) : send_to_char("flail.\n\r",ch); break; case(WEAPON_WHIP) : send_to_char("whip.\n\r",ch); break; case(WEAPON_POLEARM): send_to_char("polearm.\n\r",ch); break; default : send_to_char("unknown.\n\r",ch); break; } if (obj->pIndexData->new_format) sendf(ch,"Damage is %dd%d (average %d).\n\r", obj->value[1],obj->value[2], (1 + obj->value[2]) * obj->value[1] / 2); else sendf( ch, "Damage is %d to %d (average %d).\n\r", obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 ); if ( IS_OBJ_STAT(obj, ITEM_SOCKETABLE)) { if (obj->contains){ act( "$p has the following affixed to it:", ch, obj, NULL, TO_CHAR ); show_list_to_char( obj->contains, ch, TRUE, TRUE ); } else act( "Can be socketed.", ch, obj, NULL, TO_CHAR ); } break; case ITEM_ARMOR: sendf( ch, "Armor class is %d pierce, %d bash, %d slash, and %d vs. magic.\n\r", obj->value[0], obj->value[1], obj->value[2], obj->value[3] ); if ( IS_OBJ_STAT(obj, ITEM_SOCKETABLE)) { if (obj->contains){ act( "$p has the following affixed to it:", ch, obj, NULL, TO_CHAR ); show_list_to_char( obj->contains, ch, TRUE, TRUE ); } else act( "Can be socketed.", ch, obj, NULL, TO_CHAR ); } break; case ITEM_RANGED: if (obj->value[3] == 0) sendf(ch, "Can be used to fire: %s.\n\r", flag_string(projectile_type, obj->value[0])); else{ OBJ_INDEX_DATA* ammo = get_obj_index( obj->value[3] ); sendf(ch, "Can be used to fire: %s.\n\r", ammo == NULL ? "NOT FOUND" : ammo->short_descr); } sendf(ch, "Has accuracy of: %d%%, and rate of fire: %d\n\rFlags: %s\n\r", obj->value[1], obj->value[2], flag_string(ranged_type, obj->value[4])); break; case ITEM_PROJECTILE: sendf(ch, "Is a projectile of type %s\n\r", flag_string(projectile_type, obj->value[0])); if (obj->pIndexData->new_format) sendf(ch,"Damage is %dd%d (average %d).\n\r", obj->value[1],obj->value[2], (1 + obj->value[2]) * obj->value[1] / 2); else sendf( ch, "Damage is %d to %d (average %d).\n\r", obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 ); } if (!obj->enchanted) for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next ) { if ( paf->location != APPLY_NONE && (paf->location < APPLY_O_COND || paf->where == TO_SKILL) && paf->modifier != 0 ) sendf( ch, "Affects %s by %d.\n\r", (paf->where == TO_SKILL ? skill_table[paf->location].name : affect_loc_name( paf->location )), paf->modifier ); if (paf->bitvector) { switch(paf->where) { case TO_AFFECTS: sendf(ch,"Adds %s affect.\n", affect_bit_name(paf->bitvector)); break; case TO_OBJECT: sendf(ch,"Adds %s object flag.\n", extra_bit_name(paf->bitvector)); break; case TO_IMMUNE: sendf(ch,"Adds immunity to %s.\n", imm_bit_name(paf->bitvector)); break; case TO_RESIST: sendf(ch,"Adds resistance to %s.\n\r", imm_bit_name(paf->bitvector)); break; case TO_VULN: sendf(ch,"Adds vulnerability to %s.\n\r", imm_bit_name(paf->bitvector)); break; case TO_SKILL: /* handled above */ break; default: sendf(ch,"Unknown bit %d: %d\n\r", paf->where,paf->bitvector); break; } } } for ( paf = obj->affected; paf != NULL; paf = paf->next ) //We store mana charge in a buffer so we can show it last. if ( paf->location != APPLY_NONE && (paf->location < APPLY_O_COND || paf->where == TO_SKILL) && paf->modifier != 0 ) { sendf( ch, "Affects %s by %d", (paf->where == TO_SKILL ? skill_table[paf->location].name : affect_loc_name( paf->location )), paf->modifier ); if ( paf->duration > -1) sendf(ch,", %d hours.\n\r",paf->duration); else sendf(ch,".\n\r"); if (paf->bitvector) { switch(paf->where) { case TO_AFFECTS: sendf(ch,"Adds %s affect.\n", affect_bit_name(paf->bitvector)); break; case TO_OBJECT: sendf(ch,"Adds %s object flag.\n", extra_bit_name(paf->bitvector)); break; case TO_WEAPON: sendf(ch,"Adds %s weapon flags.\n", weapon_bit_name(paf->bitvector)); break; case TO_IMMUNE: sendf(ch,"Adds immunity to %s.\n", imm_bit_name(paf->bitvector)); break; case TO_RESIST: sendf(ch,"Adds resistance to %s.\n\r", imm_bit_name(paf->bitvector)); break; case TO_VULN: sendf(ch,"Adds vulnerability to %s.\n\r", imm_bit_name(paf->bitvector)); break; case TO_SKILL: /* handled above */ break; default: sendf(ch,"Unknown bit %d: %d\n\r", paf->where,paf->bitvector); break; } } }//end if not APPLY_NONE //MANA CHARGE MESSAGE if ( (pbuf = affect_find(obj->affected, gen_mana_charge)) != NULL) { char buf [MIL]; if(mcharge_info(ch, buf, obj, pbuf, FALSE)) send_to_char(buf, ch); } if (obj->pCabal || obj->race || obj->class >= 0){ sendf(ch, "You have a feeling only a %s%s%s%s%s%scan use it.\n\r", obj->race ? race_table[obj->race].name : "", obj->race ? " " : "", obj->class >= 0 ? class_table[obj->class].name : "", obj->class >= 0 ? " ": "", obj->pCabal ? obj->pCabal->name : "", obj->pCabal ? " ": ""); } if (CAN_WEAR(obj, ITEM_UNIQUE)) send_to_char("Unique item.\n\r",ch); if (CAN_WEAR(obj, ITEM_RARE)) send_to_char("Rare item.\n\r",ch); if (CAN_WEAR(obj, ITEM_PARRY)) send_to_char("Can be dual parried.\n\r",ch); if ( obj && HAS_TRIGGER_OBJ( obj, TRIG_USE ) ) send_to_char("You have a vauge feeling this item can be used somehow.\n\r", ch); if (extract) extract_obj(obj); } void spell_infravision( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && !IS_IMMORTAL(ch)) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if ( IS_AFFECTED(victim, AFF_INFRARED) ) { if (victim == ch) act("You can already see in the dark.",ch,NULL,victim,TO_CHAR); else act("$N can already see in the dark,",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level + 10; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_INFRARED; affect_to_char( victim, &af ); act_new( "Your eyes glow red.", victim, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n's eyes glow red.", victim, NULL, NULL, TO_ROOM ); } void spell_invis( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (ch->class == class_lookup("psionicist") && ch != victim) { send_to_char("You can only alter perceptions about your person.\n\r", ch); return; } if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && !IS_IMMORTAL(ch)) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if ( IS_AFFECTED(victim, AFF_INVISIBLE) ) { if (victim == ch) act("You are already invisible.",ch,NULL,victim,TO_CHAR); else act("$N is already invisible.",ch,NULL,victim,TO_CHAR); return; } if ( IS_AFFECTED(victim, AFF_FAERIE_FOG) || IS_AFFECTED(victim, AFF_FAERIE_FIRE)) { if (victim == ch) act("You can't become invisible while glowing.",ch,NULL,victim,TO_CHAR); else act("$N is glowing right now.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_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 ); act_new( "You fade out of existence.", victim, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n fades out of existence.", victim, NULL, NULL, TO_ROOM ); } void spell_know_alignment(int sn,int level,CHAR_DATA *ch,void *vo,int target ) { CHAR_DATA *victim; if (IS_NULLSTR(target_name)){ send_to_char("Whom do you wish to target?\n\r", ch); return; } else if ( (victim = get_char_world(ch,target_name )) == NULL){ send_to_char("They aren't here.\n\r", ch ); return; } else if (IS_NPC(victim)){ send_to_char("Why would you wish to know mob's religion?\n\r", ch); return; } sendf( ch, "%s is a loyal believer in way of %s and powers of %s.", PERS(victim, ch), deity_table[victim->pcdata->way].way, path_table[deity_table[victim->pcdata->way].path].name); } void spell_lightning_bolt(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const sh_int dam_each[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 28, 31, 34, 37, 40, 45, 50, 52, 52, 53, 54, 54, 55, 56, 56, 57, 58, 58, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 65, 65, 65, 65, 65 }; int dam; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); dam = number_range( dam_each[level] / 2, dam_each[level] * 2 ); if ( saves_spell( level, victim,DAM_LIGHTNING,skill_table[sn].spell_type) ) dam /= 2; damage( ch, victim, dam, sn, DAM_LIGHTNING ,TRUE); } void spell_locate_object( int sn, int level, CHAR_DATA *ch, void *vo,int target) { char buf[MSL]; BUFFER *buffer; OBJ_DATA *obj, *in_obj; bool found = FALSE; int number = 0, max_found = IS_IMMORTAL(ch) ? 200 : 2 * level, chance = number_percent(); buffer = new_buf(); for ( obj = object_list; obj != NULL; obj = obj->next ) { if ( !can_see_obj( ch, obj ) || (obj->carried_by && !can_see(ch, obj->carried_by)) || !is_name( target_name, obj->name ) || IS_OBJ_STAT(obj,ITEM_NOLOCATE) || UMIN(chance - 2*(get_curr_stat(ch,STAT_LUCK)-17),100) > (2 * level) || (obj->carried_by != NULL && IS_IMMORTAL(obj->carried_by) && !IS_IMMORTAL(ch)) || ch->level < obj->level || ( obj->in_room != NULL && (obj->in_room->vnum == ROOM_VNUM_LIMIT || obj->in_room->vnum == ROOM_VNUM_BOUNTY)) || ( obj->in_room != NULL && obj->in_room->vnum <= 150)) 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 && IS_IMMORTAL(in_obj->carried_by) && !IS_IMMORTAL(ch)) continue; if ( in_obj->carried_by != NULL && can_see(ch,in_obj->carried_by)) { if (in_obj->carried_by->desc && in_obj->carried_by->desc->connected != CON_PLAYING) continue; sprintf( buf, "%s is carried by %s\n\r", obj->short_descr,PERS(in_obj->carried_by, ch) ); } else { if (IS_IMMORTAL(ch) && in_obj->in_room != NULL) sprintf( buf, "%s is in %s [Room %d]\n\r", obj->short_descr,in_obj->in_room->name, in_obj->in_room->vnum); else sprintf( buf, "%s is in %s\n\r", obj->short_descr,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 ) send_to_char( "Nothing like that in heaven or earth.\n\r", ch ); else page_to_char(buf_string(buffer),ch); free_buf(buffer); } void spell_magic_missile( int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const sh_int dam_each[] = { 0, 3, 3, 4, 4, 5, 6, 6, 6, 6, 6, 8, 10, 18, 20, 22, 25, 28, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 }; int dam, i; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); for(i = UMAX(1,level/12); i > 0 && victim != NULL; i--) { dam = number_range( 2 * dam_each[level] / 3, dam_each[level] ); if (victim != NULL && (ch->in_room != victim->in_room || is_ghost(victim,600))) break; if ( saves_spell( level, victim,DAM_ENERGY,skill_table[sn].spell_type) ) dam /= 2; damage( ch, victim, dam, sn, DAM_ENERGY ,TRUE); } } void spell_mass_healing(int sn, int level, CHAR_DATA *ch, void *vo, int target) { CHAR_DATA *gch; int heal_num = skill_lookup("heal"), refresh_num = skill_lookup("refresh"); for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if ( gch->pCabal && IS_CABAL(get_parent(gch->pCabal), CABAL_NOMAGIC)) continue; if (is_same_group(ch, gch) && !IS_IMMORTAL(gch)) { spell_heal(heal_num,level,ch,(void *) gch,TARGET_CHAR); spell_refresh(refresh_num,level,ch,(void *) gch,TARGET_CHAR); } } } void spell_mass_invis( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { AFFECT_DATA af; CHAR_DATA *gch; for ( gch = ch->in_room->people; gch != NULL; gch = gch->next_in_room ) { if (ch->pCabal && IS_SET(ch->pCabal->progress, PROGRESS_CHALL)) continue; if ( !is_same_group( gch, ch ) || IS_AFFECTED(gch, AFF_INVISIBLE) ) continue; else if ( gch->pCabal && IS_CABAL(get_parent(gch->pCabal), CABAL_NOMAGIC)) continue; if ( IS_AFFECTED(gch, AFF_FAERIE_FOG) || IS_AFFECTED(gch, AFF_FAERIE_FIRE)) continue; act( "$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM ); act_new( "You slowly fade out of existence.", gch, NULL, NULL, TO_CHAR, POS_DEAD ); af.where = TO_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 ); } } void spell_null( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { send_to_char( "That's not a spell!\n\r", ch ); } void spell_pass_door( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_PASS_DOOR) ) { if (victim == ch) act("You are already out of phase.",ch,NULL,victim,TO_CHAR); else act("$N is already shifted out of phase.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_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_new( "You phase out of existence.", victim, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n phases out of existence.", victim, NULL, NULL, TO_ROOM ); } void spell_plague( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; AFFECT_DATA* paf; const int skill = get_skill(ch, sn); int dur = 0; if ( is_affected( victim, sn ) ) { act("$N is already plagued.",ch,NULL,victim,TO_CHAR); return; } if (check_immune(ch, DAM_DISEASE, TRUE) == IS_VULNERABLE && number_percent() < 10){ send_to_char("You feel your immune system give in.\n\r", ch); victim = ch; } if (ch == victim || saves_spell(level,victim,DAM_DISEASE,skill_table[sn].spell_type) || (IS_NPC(victim) && IS_SET(victim->act,ACT_UNDEAD))) { act_new("You feel momentarily ill, but it passes.",victim,NULL,NULL,TO_CHAR,POS_DEAD); if (ch != victim) act("$N seems to be unaffected.",ch,NULL,victim,TO_CHAR); return; } /* skill calcs etc. all done only if the spell is cast by a char with skill */ if (skill > 0){ if (!IS_NPC(ch) && ch->class != class_lookup("shaman") && ch->class != class_lookup("necromancer")) level -= level/3; dur = level / 10 + (skill > 77? 1: 0) + (skill > 84? 1: 0) + (skill > 88? 1: 0) + (skill > 92? 2: 0) + (skill > 95? 2: 0) + + (skill > 99? 3: 0); if (ch->class == class_lookup("shaman")) dur +=3; } else dur = level / 4; af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = dur; af.location = APPLY_STR; af.modifier = -(level/10); af.bitvector = AFF_PLAGUE; affect_to_char(victim,&af); /* now damage counter */ af.where = TO_NONE; af.type = sn; af.level = level; af.location = APPLY_NONE; if (ch->class == class_lookup("shaman")) af.modifier = 5; else af.modifier = 0; af.bitvector = 0; paf = affect_to_char(victim,&af); if (!IS_NPC(ch)) string_to_affect(paf, ch->name); act_new("You scream in agony as plague sores erupt from your skin.",victim,NULL,NULL,TO_CHAR,POS_DEAD); act("$n screams in agony as plague sores erupt from $s skin.",victim,NULL,NULL,TO_ROOM); } void spell_poison( int sn, int level, CHAR_DATA *ch, void *vo, int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; AFFECT_DATA* paf; int skill = get_skill(ch, sn); int dur = 0; bool fAdv = get_skill(ch, skill_lookup("lotus scourge")) > 1; if (is_affected(victim,sn) ) { act("$N is already poisoned.",ch,NULL,victim,TO_CHAR); return; } if ( ch == victim || saves_spell( level, victim,DAM_POISON,skill_table[sn].spell_type) ) { act_new("You feel momentarily ill, but it passes.",victim,NULL,NULL,TO_CHAR,POS_DEAD); if (ch != victim) act("$n turns slightly green, but it passes.",victim,NULL,NULL,TO_ROOM); return; } if (skill > 0){ if (!IS_NPC(ch) && !fAdv && ch->class != class_lookup("shaman") && ch->class != class_lookup("necromancer")) level -= level/3; dur = level / 10 + (skill > 80? 1: 0) + (skill > 84? 1: 0) + (skill > 88? 1: 0) + (skill > 95? 1: 0) + (skill > 99? 1: 0); } else dur = level / 6; if (fAdv) dur = UMAX(dur, 6); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = dur; af.location = APPLY_STR; af.modifier = -2; af.bitvector = AFF_POISON; paf = affect_to_char( victim, &af ); if (!IS_NPC(ch)) string_to_affect(paf, ch->name); /* Set bit preventing damage till first tick. */ if (ch->class != class_lookup("shaman")) SET_BIT(paf->bitvector, AFF_FLAG); act_new( "You feel very sick.", victim,NULL,NULL,TO_CHAR,POS_DEAD ); act("$n looks very ill.",victim,NULL,NULL,TO_ROOM); } void spell_protection(int sn,int level,CHAR_DATA *ch,void *vo, int target) { 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) act("You are already protected.",ch,NULL,victim,TO_CHAR); else act("$N is already protected.",ch,NULL,victim,TO_CHAR); return; } if ( is_affected( victim, gsn_blasphemy ) ) { sendf(ch, "%s's faith have been lost.\n\r", PERS(victim,ch)); return; } if (IS_GOOD(ch)) { af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 23; af.location = APPLY_SAVING_SPELL; af.modifier = -1; af.bitvector = AFF_PROTECT_EVIL; affect_to_char( victim, &af ); act_new( "You feel holy and pure.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); if ( ch != victim ) act("$N is protected from evil.",ch,NULL,victim,TO_CHAR); return; } if (IS_EVIL(ch)) { af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_SAVING_SPELL; af.modifier = -1; af.bitvector = AFF_PROTECT_GOOD; affect_to_char( victim, &af ); act_new( "You feel aligned with darkness.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); if ( ch != victim ) act("$N is protected from good.",ch,NULL,victim,TO_CHAR); return; } else { send_to_char( "You lack the moral commitment to recieve protection.\n\r",victim); return; } } void spell_protection_evil(int sn,int level,CHAR_DATA *ch,void *vo, int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_NEUTRAL(victim)){ send_to_char( "You lack the moral commitment.\n\r",victim); return; } if ( IS_AFFECTED(victim, AFF_PROTECT_EVIL) || IS_AFFECTED(victim, AFF_PROTECT_GOOD)) { if (victim == ch) act("You are already protected.",ch,NULL,victim,TO_CHAR); else act("$N is already protected.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_SAVING_SPELL; af.modifier = -1; af.bitvector = AFF_PROTECT_EVIL; affect_to_char( victim, &af ); act_new( "You feel holy and pure.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); if ( ch != victim ) act("$N is protected from evil.",ch,NULL,victim,TO_CHAR); } void spell_protection_good(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (IS_NEUTRAL(victim)){ send_to_char( "You lack the moral commitment.\n\r",victim); return; } if ( IS_AFFECTED(victim, AFF_PROTECT_GOOD) || IS_AFFECTED(victim, AFF_PROTECT_EVIL)) { if (victim == ch) act("You are already protected.",ch,NULL,victim,TO_CHAR); else act("$N is already protected.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 24; af.location = APPLY_SAVING_SPELL; af.modifier = -1; af.bitvector = AFF_PROTECT_GOOD; affect_to_char( victim, &af ); act_new( "You feel aligned with darkness.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); if ( ch != victim ) act("$N is protected from good.",ch,NULL,victim,TO_CHAR); } void spell_ray_of_truth (int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (IS_EVIL(ch) ) { victim = ch; send_to_char("The energy explodes inside you!\n\r",ch); } if (victim != ch) { act("A blinding ray of magic shots from $n's hands and envelops $N.", ch, NULL, victim, TO_NOTVICT); act("As the ray of $g's power shoots forth, $N cries out in remorse.", ch, NULL, victim, TO_CHAR); send_to_char("Your life flashes before your eyes and you are crushed by the error of your ways.\n\r", victim); } if (IS_NPC(victim)) dam = dice(UMIN(100, victim->level * 2), 3); else dam = number_range(0, 30) + 2 * level + UMIN(10, victim->pcdata->kpc) * 3 + UMIN(3, victim->pcdata->flagged) * 10; if (!IS_GOOD(ch)) dam /= 2; if ( saves_spell( level, victim, DAM_LIGHT, skill_table[sn].spell_type) ) dam /= 2; else { level = UMIN( 0, level ); switch (number_range(1, 3)) { case 1: spell_blindness(gsn_blindness,level, ch, (void *) victim,TARGET_CHAR); break; case 2: spell_shrink(skill_lookup("shrink"),level, ch, (void *) victim,TARGET_CHAR); break; case 3: spell_silence(skill_lookup("silence"),level - 3, ch, (void *) victim,TARGET_CHAR); break; } } damage( ch, victim, dam, sn, DAM_ENERGY ,TRUE); } void spell_path_of_deceit (int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam; if (IS_GOOD(ch) ) { victim = ch; send_to_char("The energy explodes inside you!\n\r",ch); } if (victim != ch) { act("You call onto $g's power and envelop $N in the very stuff of evil.", ch, NULL, victim, TO_CHAR); act("A sinister dark aura envelops $N and $E falls to $S knees.", ch, NULL, victim, TO_NOTVICT); send_to_char("The vile taint of evil begins to suffocate your soul.\n\r", victim); } if (IS_NPC(ch)) dam = dice(UMIN(100, victim->level * 2), 3); else dam = number_range(0, 30) + (2 * level) + (UMIN(10, ch->pcdata->kpc) * 3) + (UMIN(3, ch->pcdata->flagged) * 10); if (!IS_EVIL(ch)) dam /= 3; if ( saves_spell( level, victim,DAM_NEGATIVE,skill_table[sn].spell_type) ) dam /= 2; else { level = UMIN(50, level); switch (number_range(1, 3)) { case 1: spell_poison(gsn_poison,level, ch, (void *) victim,TARGET_CHAR); break; case 2: spell_plague(gsn_plague,level, ch, (void *) victim,TARGET_CHAR); break; case 3: spell_blasphemy(gsn_blasphemy,level, ch, (void *) victim,TARGET_CHAR); break; } } damage( ch, victim, dam, sn, DAM_NEGATIVE ,TRUE); } void spell_refresh( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; victim->move = UMIN( victim->move + level, victim->max_move ); if (victim->max_move == victim->move) send_to_char("You feel fully refreshed!\n\r",victim); else send_to_char( "You feel less tired.\n\r", victim ); if ( ch != victim ) sendf(ch, "You refresh %s.\n\r", PERS(victim,ch) ); } /* syntax for this spell is: <object> or <victim> <object> */ void spell_remove_curse( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim; OBJ_DATA *obj; //mobs can cure curse on players if (IS_NPC(ch) && (victim = get_char_room(ch, NULL, target_name)) != NULL){ if (!IS_AFFECTED(victim, AFF_CURSE)){ act("But $N is not cursed!", ch, NULL, victim, TO_CHAR); return; } if (check_dispel(level, victim, gsn_curse)){ act("$n glows blue.", victim, NULL, victim, TO_ROOM); act("You glow blue.", victim, NULL, victim, TO_CHAR); } else{ act("The curse on $N has withstood your power.",ch, NULL, victim,TO_CHAR); } return; } /* check if the first argument matches an object we are carrying */ if ( (obj = get_obj_carry(ch, target_name, ch )) == NULL){ obj = get_obj_wear(ch, target_name, ch ); } /* now we either work on the object, or handle another character */ if (obj != NULL){ if (IS_OBJ_STAT(obj,ITEM_NODROP) || IS_OBJ_STAT(obj,ITEM_NOREMOVE) || is_affected_obj(obj, gsn_curse_weapon)){ if (!IS_OBJ_STAT(obj,ITEM_NOUNCURSE) && !saves_dispel(level + 2, obj->level, 0)){ REMOVE_BIT(obj->extra_flags,ITEM_NODROP); REMOVE_BIT(obj->extra_flags,ITEM_NOREMOVE); affect_strip_obj(obj, gsn_curse_weapon); act("$p glows blue.",ch,obj,NULL,TO_ALL); return; } act("The curse on $p has withstood your power.",ch,obj,NULL,TO_CHAR); return; } act("There doesn't seem to be a curse on $p.",ch,obj,NULL,TO_CHAR); return; } /* no object of such name, we handle the victim now */ else{ char name[MIL]; target_name = one_argument( target_name, name ); if ( (victim = get_char_room( ch, NULL, name )) == NULL){ send_to_char("There is no such item or person here.\n\r", ch); return; } else if (IS_NULLSTR( target_name )){ sendf(ch, "Remove curse from what item on %s?\n\r", PERS( victim, ch )); return; } else if (!IS_NPC(ch) && victim->master != ch && victim != ch && !is_same_group(victim, ch) && !IS_IMMORTAL(ch)){ send_to_char("They are not following you.\n\r", ch ); return; } /* the the object now like we did before */ else if ( (obj = get_obj_carry(victim, target_name, ch )) == NULL && (obj = get_obj_wear(victim, target_name, ch )) == NULL){ sendf( ch, "%s does not seem to be carrying or using that.\n\r", PERS( victim, ch )); return; } /* now we either work on the object, or handle another character */ if (IS_OBJ_STAT(obj,ITEM_NODROP) || IS_OBJ_STAT(obj,ITEM_NOREMOVE) || is_affected_obj(obj, gsn_curse_weapon)){ if (!IS_OBJ_STAT(obj,ITEM_NOUNCURSE) && !saves_dispel(level + 2, obj->level, 0)){ REMOVE_BIT(obj->extra_flags,ITEM_NODROP); REMOVE_BIT(obj->extra_flags,ITEM_NOREMOVE); affect_strip_obj(obj, gsn_curse_weapon); act("$p glows blue.",ch,obj,NULL,TO_ALL); return; } act("The curse on $p has withstood your power.",ch,obj,NULL,TO_CHAR); return; } act("There doesn't seem to be a curse on $p.",ch,obj,NULL,TO_CHAR); return; } } void spell_sanctuary( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; int dur = 1; if (ch->class == gcn_adventurer && ch != victim){ send_to_char("You cannot cast this spell on another.\n\r", ch); return; } if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && !IS_IMMORTAL(ch)) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if (is_affected(victim, gsn_pyramid_of_force)){ send_to_char("Strangly nothing happens...\n\r", ch); return; } if (is_affected(victim, gsn_sacred_runes)){ send_to_char("The vile runes seem to negate the effect.\n\r", ch); return; } if (is_affected(victim, gsn_lifeforce)) { if (victim == ch) act("Not with a lifeforce surrounding you!",ch,NULL,victim,TO_CHAR); else act("$N is already surrounded by a lifeforce.",ch,NULL,victim,TO_CHAR); return; } if ( IS_AFFECTED(victim, AFF_SANCTUARY) ) { if (victim == ch) act("You are already in sanctuary.",ch,NULL,victim,TO_CHAR); else act("$N is already in sanctuary.",ch,NULL,victim,TO_CHAR); return; } /* duration, goods get a bonus */ if (IS_GOOD(ch)){ dur = (level > 30 ? 1 : 0) + number_fuzzy( level / 5); } else dur = number_fuzzy( level / 6); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = dur; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SANCTUARY; affect_to_char( victim, &af ); act_new( "You are surrounded by a white aura.", victim, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n is surrounded by a white aura.", victim, NULL, NULL, TO_ROOM ); } void spell_shield( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (((IS_GOOD(ch) && IS_EVIL(victim)) || (IS_EVIL(ch) && IS_GOOD(victim))) && !IS_IMMORTAL(ch)) { sendf(ch, "It would go against your beliefs to aid %s.\n\r", PERS(victim,ch)); return; } if ( is_affected( victim, sn ) ) { if (victim == ch) act("You are already shielded from harm.",ch,NULL,victim,TO_CHAR); else act("$N is already protected by a shield.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = 24 * UMAX(1, level / 25); af.location = APPLY_AC; af.modifier = -20; af.bitvector = 0; affect_to_char( victim, &af ); act_new( "You are surrounded by a force shield.", victim, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n is surrounded by a force shield.", victim, NULL, NULL, TO_ROOM ); } void spell_shocking_grasp(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; static const int dam_each[] = { 0, 2, 4, 5, 7, 12, 15, 20, 25, 29, 33, 36, 39, 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57 }; int dam; level = UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1); level = UMAX(0, level); dam = number_range( dam_each[level] / 2, 3 * dam_each[level] /2 ); if ( saves_spell( level, victim,DAM_LIGHTNING,skill_table[sn].spell_type) ) dam /= 2; damage( ch, victim, dam, sn, DAM_LIGHTNING ,TRUE); } void spell_sleep( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( IS_AFFECTED(victim, AFF_SLEEP) ) { act( "$N is already asleep.", ch, NULL, victim, TO_CHAR); return; } set_delay(ch, victim); if (is_affected(victim, gen_watchtower)){ sendf( ch, "%s is shielded within the Watchtower.\n\r", PERS(victim, ch )); return; } if ( (IS_NPC(victim) && IS_SET(victim->act,ACT_TOO_BIG) ) || IS_UNDEAD(victim) || saves_spell( level, victim,DAM_CHARM,skill_table[sn].spell_type)) { act( "You fail to cause $N to fall asleep.", ch, NULL, victim, TO_CHAR); return; } if (is_affected(victim, gsn_horse) && monk_good(victim, WEAR_HEAD) && !IS_NPC(victim) && !IS_IMMORTAL(ch)) { act( "You reverse $n's attempt to charm you, and charm $M instead!", ch, NULL, victim, TO_VICT ); act("$N reverses your charm, and charms you instead!", ch, NULL, victim, TO_CHAR ); af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = number_fuzzy( level / 15) +1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; affect_to_char( ch, &af ); if ( IS_AWAKE(ch) ) { send_to_char( "You feel very sleepy...\n\r", ch ); do_sleep(ch,""); } return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = number_fuzzy( level / 15) +1; af.location = APPLY_NONE; af.modifier = 0; af.bitvector = AFF_SLEEP; affect_to_char( victim, &af ); if ( IS_AWAKE(victim) ) { send_to_char( "You feel very sleepy...\n\r", victim ); do_sleep(victim,""); } } void spell_slow( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; bool fFriend = FALSE; /* quick check for in combat */ if (IS_NULLSTR(target_name) && ch->fighting) victim = ch->fighting; fFriend = is_same_group(ch, victim); if (!fFriend){ /* checks for pk etc */ if (is_safe(ch,victim) && victim != ch){ sendf(ch, "Not on %s.\n\r",PERS(victim,ch)); return; } if (is_safe(ch, victim)) return; /* these are the checks for yelling and attacking */ if (victim->fighting != ch && ch->fighting != victim && !IS_NPC(ch) && IS_AWAKE(victim)) m_yell(ch, victim, TRUE); /* check for start of combat */ if (IS_AWAKE(victim) && (victim->fighting == NULL || ch->fighting == NULL) && !is_affected(victim,gsn_ecstacy) && !is_ghost(victim,600)) { set_fighting( ch, victim ); set_fighting( victim, ch ); multi_hit( victim, ch, TYPE_UNDEFINED ); } /* and saves check */ if (saves_spell( level, victim,DAM_MENTAL,skill_table[sn].spell_type)){ send_to_char("You failed.\n\r", ch); return; } } if ( is_affected( victim, sn ) || IS_AFFECTED(victim,AFF_SLOW)) { if (victim == ch) act("You can't move any slower!",ch,NULL,victim,TO_CHAR); else act("$N can't get any slower than that.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level/4; af.location = APPLY_DEX; af.modifier = -1 - (level >= 18) - (level >= 25) - (level >= 32); af.bitvector = AFF_SLOW; affect_to_char( victim, &af ); act_new( "You feel yourself moving more slowly.", victim,NULL,NULL,TO_CHAR,POS_DEAD ); act("$n starts to move in slow motion.",victim,NULL,NULL,TO_ROOM); } void spell_stone_skin( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( ch, sn ) ) { if (victim == ch) act("Your skin is already as hard as a rock.",ch,NULL,victim,TO_CHAR); else act("$N is already as hard as $E can be.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_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_new( "Your skin turns to stone.", victim, NULL, NULL, TO_CHAR, POS_DEAD ); act( "$n's skin turns to stone.", victim, NULL, NULL, TO_ROOM ); } void spell_summon( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim, *och, *och_next; if (( victim = get_char_world( ch, target_name ) ) == NULL){ send_to_char("You cannot locate them.\n\r", ch); return; } if ( (victim == ch || victim->in_room == NULL || (!IS_NPC(victim) && victim->level >= LEVEL_IMMORTAL) || (IS_NPC(victim) && IS_SET(victim->act,ACT_AGGRESSIVE)) || (IS_NPC(victim) && victim->pIndexData->pShop != NULL) || IS_SET(ch->in_room->area->area_flags, AREA_RESTRICTED) || IS_SET(victim->in_room->area->area_flags, AREA_RESTRICTED) || IS_SET(victim->imm_flags,IMM_SUMMON) || 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_INOUT) || IS_SET(ch->in_room->room_flags, ROOM_NO_INOUT) || IS_SET(victim->in_room->room_flags, ROOM_NO_SUMMONOUT) || IS_SET(ch->in_room->room_flags, ROOM_NO_SUMMONIN) || victim->level > level + 5 || victim->fighting != NULL || (!IS_NPC(victim) && IS_SET(victim->act,PLR_NOSUMMON) && !is_pk(ch,victim)) || ((!IS_NPC(victim) || IS_AFFECTED(victim,AFF_CHARM)) && victim->in_room->area != ch->in_room->area) || (IS_NPC(victim) && IS_AFFECTED(victim,AFF_CHARM) && victim->master != NULL && victim->in_room == victim->master->in_room && !is_pk(ch,victim->master)) || ((ch->in_room->exit[0] == NULL || IS_SET((ch->in_room->exit[0])->exit_info, EX_CLOSED)) && (ch->in_room->exit[1] == NULL || IS_SET((ch->in_room->exit[1])->exit_info, EX_CLOSED)) && (ch->in_room->exit[2] == NULL || IS_SET((ch->in_room->exit[2])->exit_info, EX_CLOSED)) && (ch->in_room->exit[3] == NULL || IS_SET((ch->in_room->exit[3])->exit_info, EX_CLOSED)) && (ch->in_room->exit[4] == NULL || IS_SET((ch->in_room->exit[4])->exit_info, EX_CLOSED)) && (ch->in_room->exit[5] == NULL || IS_SET((ch->in_room->exit[5])->exit_info, EX_CLOSED))) || is_affected(victim,gsn_coffin) || is_affected(victim,gen_watchtower) || is_affected(victim,gsn_entomb) || is_affected(victim, gsn_tele_lock) || saves_spell( IS_SET(victim->vuln_flags,VULN_SUMMON) ? level + 3 : level - 3 , victim,DAM_OTHER,skill_table[sn].spell_type)) && !IS_IMMORTAL(ch)) { act( "You failed the summon.", ch, NULL, NULL, TO_CHAR ); return; } if (number_percent() < get_skill(victim,gsn_mind_link)) { for ( och = ch->in_room->people; och != NULL; och = och_next ) { och_next = och->next_in_room; if ( IS_AFFECTED(och, AFF_CHARM) && IS_NPC(och) && och->master == ch && och->pIndexData->vnum == MOB_VNUM_DISPLACER) { victim = och; break; } } } a_yell( ch, victim ); act( "$n disappears suddenly.", victim, NULL, NULL, TO_ROOM ); char_from_room( victim ); char_to_room( victim, ch->in_room ); if (!IS_NPC(victim) && victim->pcdata->pStallion!=NULL) { victim->pcdata->pStallion = NULL; } act( "$n arrives suddenly.", victim, NULL, NULL, TO_ROOM ); act( "$n has summoned you!", ch, NULL, victim, TO_VICT ); do_look( victim, "auto" ); /* CONTINENCY */ check_contingency(victim, NULL, CONT_SUMMON); } void spell_teleport( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; ROOM_INDEX_DATA *pRoomIndex; bool fSafe = FALSE; const int bad_max = 5; int bad_num = 0; /* forsaken lands MUST BE LAST */ char* bad_areas[5] = {"winter", "faction of steel", "faction of blood", "faction of magic", "forsaken lands"}; int e_r1[] = {ROOM_NO_TELEPORTIN}; int area_pool = 10; if (victim != ch){ send_to_char("You cannot teleport others.\n\r", ch); return; } if ( victim->in_room == NULL || IS_SET(victim->in_room->room_flags, ROOM_NO_INOUT) || IS_SET(victim->in_room->room_flags, ROOM_NO_TELEPORTOUT) || ( victim != ch && IS_SET(victim->imm_flags,IMM_SUMMON)) || is_affected(victim, gsn_tele_lock) || is_affected(victim,gen_ensnare) || ( !IS_NPC(ch) && victim->fighting != NULL ) || (IS_NPC(ch) && ch->pIndexData->pShop != NULL) || ( victim != ch && ( saves_spell( level - 5, victim,DAM_OTHER,skill_table[sn].spell_type)))){ if (victim == ch){ send_to_char("You failed.\n\r",ch); return; } } /* try to get a safe room if skill allows */ if (number_percent() < (get_skill(ch, sn) - 50)) fSafe = TRUE; else{ /* exclude forsaken lands from higher up players */ if (ch->level < 45) bad_num = bad_max; else bad_num = UMAX(0, bad_max - 1); } pRoomIndex = get_rand_room(0,0, //area range (0 to ignore) 0,0, //room ramge (0 to ignore) bad_areas,bad_num,//areas to choose from NULL,0, //areas to exclude NULL,0, //sectors required NULL,0, //sectors to exlude NULL,0, //room1 flags required e_r1,1, //room1 flags to exclude NULL,0, //room2 flags required NULL,0, //room2 flags to exclude area_pool, //number of seed areas TRUE, //exit required? fSafe, //Safe? ch); //Character for room checks /* check if we failed getting a safe room */ if (fSafe && pRoomIndex == NULL) pRoomIndex = get_rand_room(0,0, //area range (0 to ignore) 0,0, //room ramge (0 to ignore) bad_areas,bad_num,//areas to choose from NULL,0, //areas to exclude NULL,0, //sectors required NULL,0, //sectors to exlude NULL,0, //room1 flags required e_r1,1, //room1 flags to exclude NULL,0, //room2 flags required NULL,0, //room2 flags to exclude area_pool, //number of seed areas TRUE, //exit required? fSafe, //Safe? ch );//Character for room checks if (pRoomIndex == NULL || IS_SET(pRoomIndex->area->area_flags, AREA_NOMORTAL) ){ send_to_char("You failed.\n\r", ch); return; } if (victim != ch) send_to_char("You have been teleported!\n\r",victim); act( "$n vanishes!", victim, NULL, NULL, TO_ROOM ); /* remove ghost */ if (!IS_NPC(ch) && ch->pcdata->ghost != (time_t)NULL){ send_to_char("You are no longer a ghost.\n\r", ch); ch->pcdata->ghost = (time_t)NULL; } char_from_room( victim ); char_to_room( victim, pRoomIndex ); act( "$n suddenly pops into existence.", victim, NULL, NULL, TO_ROOM ); do_look( victim, "auto" ); } void spell_ventriloquate( int sn, int level, CHAR_DATA *ch,void *vo,int target) { char buf1[MSL], buf2[MSL], speaker[MIL]; CHAR_DATA *vch; target_name = one_argument( target_name, speaker ); sprintf( buf1, "%s says '`#%s``'\n\r", speaker, target_name ); sprintf( buf2, "Someone makes %s say '`#%s``'\n\r", speaker, target_name ); buf1[0] = UPPER(buf1[0]); for ( vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room ) if (!is_exact_name( speaker, vch->name) && IS_AWAKE(vch)) send_to_char( saves_spell(level,vch,DAM_OTHER,skill_table[sn].spell_type) ? buf2 : buf1, vch ); } void spell_weaken( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if ( is_affected( victim, sn ) ) { if (victim == ch) act("You are already in a weakened state.",ch,NULL,victim,TO_CHAR); else act("$N is already in a weakened state.",ch,NULL,victim,TO_CHAR); return; } if (saves_spell( level, victim,DAM_MALED,skill_table[sn].spell_type) && victim != ch) { act("You fail to weaken $N.",ch,NULL,victim,TO_CHAR); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = level / 3; af.location = APPLY_STR; af.modifier = -1 * (level / 8); af.bitvector = AFF_WEAKEN; affect_to_char( victim, &af ); act_new( "You feel your strength slip away.", victim,NULL,NULL,TO_CHAR,POS_DEAD); act("$n looks tired and weak.",victim,NULL,NULL,TO_ROOM); } void spell_word_of_recall( int sn, int level, CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; ROOM_INDEX_DATA *location; if (!IS_NPC(victim)) location = get_room_index(get_temple(victim)); else if (victim->master != NULL && victim->master == ch) location = get_room_index(get_temple(ch)); else return; if (location == NULL) { send_to_char("You are completely lost.\n\r",victim); return; } if (!IS_NPC(ch) && victim->master != ch && victim != ch && !is_same_group(victim, ch) && !IS_IMMORTAL(ch)) { sendf(ch, "But %s isn't following you.\n\r", PERS2(victim)); return; } if (IS_SET(victim->in_room->room_flags,ROOM_NO_RECALL) || IS_SET(victim->in_room->room_flags,ROOM_NO_INOUT) || IS_AFFECTED(victim,AFF_CURSE) || (!IS_NPC(victim) && (IS_SET(victim->act,PLR_DOOF) )) || is_exiled(victim, location->area->vnum) || is_affected(victim,gsn_damnation) ) { send_to_char( "The Gods have forsaken you.\n\r", victim ); return; } if (is_affected(victim, gsn_tele_lock)){ send_to_char("Something seems to be blocking the spell.\n\r", ch); return; } else if (is_affected(victim,gen_ensnare)){ send_to_char("You sense a powerful magical field preventing your departure.\n\r", ch); return; } if (victim->fighting != NULL) { if ( IS_NPC(victim->fighting) && !IS_SET(victim->fighting->act2, ACT_LAWFUL) && !IS_SET(victim->fighting->act, ACT_RAIDER) && !IS_SET(victim->fighting->off_flags,CABAL_GUARD)){ if (!IS_NPC(victim)) victim->fighting->hunting = victim; else if (victim->master != NULL) victim->fighting->hunting = victim->master; else victim->fighting->hunting = victim; victim->fighting->hunttime = 0; } stop_fighting(victim,TRUE); } victim->move /= 2; if (!IS_NPC(victim) && victim->pcdata->pStallion != NULL ) { victim->pcdata->pStallion = NULL; } if ( IS_SET(victim->act,PLR_OUTCAST)){ AFFECT_DATA af; int exp_dr = -1 * number_range(5 * level, 20 * level); act("$g exacts a heavy toll on your mind.", victim, NULL, NULL, TO_CHAR); if (victim->level < 50){ sendf(victim, "You lose %d experience!\n\r", exp_dr); gain_exp(victim, exp_dr); } af.type = sn; af.level = level; af.duration = 6; af.where = TO_AFFECTS; af.bitvector = 0; af.location = APPLY_HIT_GAIN; af.modifier = -10; affect_join(victim, &af); } /* lag the victim if he is bloody */ if (!IS_NPC(victim) && is_fight_delay(victim, 180)){ WAIT_STATE(victim, PULSE_TICK / 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"); } void spell_acid_breath( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int 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(10,ch->hit); dam = number_range( hpch/16+1, hpch/8 ); if (saves_spell(level,victim,DAM_ACID,skill_table[sn].spell_type)) { acid_effect(victim,level/2,dam/4,TARGET_CHAR); damage(ch,victim,dam/2,sn,DAM_ACID,TRUE); } else { acid_effect(victim,level,dam,TARGET_CHAR); damage(ch,victim,dam,sn,DAM_ACID,TRUE); } } void spell_death_breath( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *vch, *vch_next; int dam, hpch; act("$n breathes forth a blast of black fire.",ch,NULL, NULL,TO_ROOM); act("You breath forth a blast of black fire.",ch,NULL,NULL,TO_CHAR); for (vch = ch->in_room->people; vch != NULL; vch = vch_next){ vch_next = vch->next_in_room; if ( vch == ch || is_area_safe(ch,vch)) continue; hpch = UMAX( 10, ch->hit ); dam = number_range( hpch/16+1, hpch/8 ); if (saves_spell(level,vch,DAM_NEGATIVE,skill_table[sn].spell_type)) { paralyze_effect(vch,level/2,dam/4,TARGET_CHAR); damage(ch,vch,dam/2,sn,DAM_NEGATIVE,TRUE); } else { paralyze_effect(vch,level,dam,TARGET_CHAR); damage(ch,vch,dam,sn,DAM_NEGATIVE,TRUE); } } } void spell_fire_breath( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int dam, 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 ); dam = number_range( hpch/16+1, hpch/8 ); if (saves_spell(level,victim,DAM_FIRE,skill_table[sn].spell_type)) { fire_effect(victim,level/2,dam/4,TARGET_CHAR); damage(ch,victim,dam/2,sn,DAM_FIRE,TRUE); } else { fire_effect(victim,level,dam,TARGET_CHAR); damage(ch,victim,dam,sn,DAM_FIRE,TRUE); } } void spell_frost_breath( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *victim = (CHAR_DATA *) vo; int 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(10,ch->hit); dam = number_range( hpch/16+1, hpch/8 ); if (saves_spell(level,victim,DAM_COLD,skill_table[sn].spell_type)) { cold_effect(victim,level/2,dam/4,TARGET_CHAR); damage(ch,victim,dam/2,sn,DAM_COLD,TRUE); } else { cold_effect(victim,level,dam,TARGET_CHAR); damage(ch,victim,dam,sn,DAM_COLD,TRUE); } } void spell_gas_breath( int sn, int level, CHAR_DATA *ch, void *vo,int target ) { CHAR_DATA *vch, *vch_next; int dam, hpch; act("$n breathes out a cloud of poisonous gas!",ch,NULL,NULL,TO_ROOM); act("You breath out a cloud of poisonous gas.",ch,NULL,NULL,TO_CHAR); for (vch = ch->in_room->people; vch != NULL; vch = vch_next) { vch_next = vch->next_in_room; if ( vch == ch || is_area_safe(ch,vch)) continue; hpch = UMAX( 10, ch->hit ); dam = number_range( hpch/16+1, hpch/8 ); if (saves_spell(level,vch,DAM_POISON,skill_table[sn].spell_type)) { poison_effect(vch,level/2,dam/4,TARGET_CHAR); damage(ch,vch,dam/2,sn,DAM_POISON,TRUE); } else { poison_effect(vch,level,dam,TARGET_CHAR); damage(ch,vch,dam,sn,DAM_POISON,TRUE); } } } void spell_lightning_breath(int sn,int level,CHAR_DATA *ch,void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int 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); dam = number_range( hpch/16+1, hpch/8 ); if (saves_spell(level,victim,DAM_LIGHTNING,skill_table[sn].spell_type)) { shock_effect(victim,level/2,dam/4,TARGET_CHAR); damage(ch,victim,dam/2,sn,DAM_LIGHTNING,TRUE); } else { shock_effect(victim,level,dam,TARGET_CHAR); damage(ch,victim,dam,sn,DAM_LIGHTNING,TRUE); } } void spell_curse_weapon(int sn,int level,CHAR_DATA *ch, void *vo,int target) { OBJ_DATA *obj = (OBJ_DATA *) vo; AFFECT_DATA *paf; int result, fail = 30, hit_bonus = 0, dam_bonus = 0, added; bool hit_found = FALSE, dam_found = FALSE; bool fCurse = FALSE; if (obj->item_type != ITEM_WEAPON) { send_to_char("That isn't a weapon.\n\r",ch); return; } if (obj->wear_loc != -1) { send_to_char("The item must be carried to be cursed.\n\r",ch); return; } if (!obj->enchanted) for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next ) { if ( paf->location == APPLY_HITROLL ) { hit_bonus = paf->modifier; hit_found = TRUE; fail += 2 * (hit_bonus * hit_bonus); } else if (paf->location == APPLY_DAMROLL ) { dam_bonus = paf->modifier; dam_found = TRUE; fail += 2 * (dam_bonus * dam_bonus); } else fail += 25; } for ( paf = obj->affected; paf != NULL; paf = paf->next ) { if ( paf->location == APPLY_HITROLL ) { hit_bonus = paf->modifier; hit_found = TRUE; fail += 2 * (hit_bonus * hit_bonus); } else if (paf->location == APPLY_DAMROLL ) { dam_bonus = paf->modifier; dam_found = TRUE; fail += 2 * (dam_bonus * dam_bonus); } else fail += 25; } fail -= level; if (IS_OBJ_STAT(obj,ITEM_BLESS)) fail -= 20; if (IS_OBJ_STAT(obj,ITEM_GLOW)) fail -= 10; fail = URANGE(5,fail,95); result = number_percent(); result += 2*(get_curr_stat(ch,STAT_LUCK) - 16); /* for mob shoppies etc */ if (IS_NPC(ch)){ fail = 0; result = 101; } if (result < (fail / 3) && !IS_IMMORTAL(ch) ) { act("$p shivers violently and explodes!",ch,obj,NULL,TO_ALL); extract_obj(obj); return; } if ( result <= fail && !IS_IMMORTAL(ch) ) { send_to_char("Nothing seemed to happen.\n\r",ch); return; } if (!obj->enchanted) { AFFECT_DATA *af_new; obj->enchanted = TRUE; for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next) { af_new = new_affect(); af_new->next = obj->affected; obj->affected = af_new; af_new->where = paf->where; af_new->type = UMAX(0,paf->type); af_new->level = paf->level; af_new->duration = paf->duration; af_new->location = paf->location; af_new->modifier = paf->modifier; af_new->bitvector = paf->bitvector; } } if (result <= (100 - level)) { act("$p fades gray.",ch,obj,NULL,TO_ALL); SET_BIT(obj->extra_flags, ITEM_MAGIC); added = -1; } else { act("$p blackens completely!",ch,obj,NULL,TO_ALL); added = -2; fCurse = TRUE; } if (obj->level < LEVEL_HERO - 1) obj->level = UMIN(LEVEL_HERO - 1,obj->level + 1); if (dam_found) { for ( paf = obj->affected; paf != NULL; paf = paf->next) if ( paf->location == APPLY_DAMROLL) { paf->type = sn; paf->modifier += added; paf->level = UMAX(paf->level,level); if (paf->modifier > 4) SET_BIT(obj->extra_flags,ITEM_HUM); } } else { paf = new_affect(); paf->where = TO_OBJECT; paf->type = sn; paf->level = level; paf->duration = -1; 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); if (paf->modifier > 4) SET_BIT(obj->extra_flags,ITEM_HUM); } } else { paf = new_affect(); paf->type = sn; paf->level = level; paf->duration = -1; paf->location = APPLY_HITROLL; paf->modifier = added; paf->bitvector = 0; paf->next = obj->affected; obj->affected = paf; } if (fCurse){ AFFECT_DATA af; af.type = sn; af.level = level; af.duration = -1; af.where = TO_OBJECT; af.bitvector = ITEM_NODROP; af.modifier = 0; af.location = 0; affect_to_obj(obj, &af); af.bitvector = ITEM_NOREMOVE; affect_to_obj(obj, &af); af.bitvector = ITEM_MAGIC; affect_to_obj(obj, &af); } } void spell_divine_retribution(int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; if (is_affected(victim,sn)) { send_to_char("You are already protected by the wrath of the gods.\n\r",ch); return; } if (IS_AFFECTED2(victim,AFF_BARRIER)) { send_to_char("You must get rid of the barrier first.\n\r",ch); return; } af.where = TO_AFFECTS; af.type = sn; af.level = level; af.duration = number_fuzzy( level/6); af.location = 0; af.modifier = 0; af.bitvector = 0; affect_to_char( victim, &af ); send_to_char( "You are protected by the wrath of the gods.\n\r",ch); act( "A globe of white light encases $n.", ch, NULL, NULL, TO_ROOM ); } void spell_dispel_undead( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; AFFECT_DATA af; int dam; if ( !IS_UNDEAD(victim) ) { act( "$N does not seem to be affected.", ch, NULL, victim, TO_CHAR ); return; } act("You attempt to banish $G's power over $N.", ch, NULL, victim, TO_CHAR); dam = dice( 10 + level, 5 ); if ( saves_spell( level, victim,DAM_HOLY,skill_table[sn].spell_type) ) { send_to_char("You failed.\n\r", ch); return; } if (is_affected(victim, sn)) { send_to_char("Prepared for the attack you easly fortify your power and resist.\n\r", victim); act("$N resists the spell!", ch, NULL, victim, TO_CHAR); dam /=5; } else { act("You feel $G's link to you disappear momentarly.", ch, NULL, victim, TO_VICT); af.type = sn; af.where = TO_AFFECTS; af.bitvector = 0; af.duration = number_fuzzy(2); af.level = level; af.location = APPLY_NONE; af.modifier = 0; affect_to_char(victim, &af); } damage( ch, victim, dam, sn, DAM_HOLY ,TRUE); } void spell_cure_mana( int sn, int level, CHAR_DATA *ch, void *vo,int target) { CHAR_DATA *victim = (CHAR_DATA *) vo; int heal = dice(1, 8) + level / 3; if (ch->in_room->sector_type != SECT_FOREST) { send_to_char("Your mana can only be healed within a forest!\n\r",ch); return; } victim->mana = UMIN( victim->mana + heal, victim->max_mana ); act_new("Harnessing natural forces, you restore a little mana.",ch,NULL,victim,TO_CHARVICT,POS_DEAD); } ///////////////////// //embrace_heal_check// ///////////////////// //checks if removal of gsn_embrace_poison if successful //Returns TRUE on success inline bool embrace_heal_check(int sn, int level, CHAR_DATA* ch, CHAR_DATA* vic, int healed) { //Checks if the embrace effect was removed. //Embrace can be removed only through healing spells, with the amount healed being //cut in half to obtain the chance to heal, modified by rank ratio of caster and*/ //target. //Cannot be cast on self //EZ cases. if (ch == NULL) return FALSE; //Check if this spell can cure this condition. if ( sn != skill_lookup("heal") && sn != gsn_heal && sn != skill_lookup("cure light") && sn != skill_lookup("cure serious") && sn != skill_lookup("cure critical") && sn != gsn_lay_on_hands ) return FALSE; if ( (ch == vic) && is_affected(ch, gsn_embrace_poison)) { send_to_char("Your efforts have been tainted, and the healing fails.\n\r", ch); return FALSE; } //Lay on hands get a large bonus :) if (sn == gsn_lay_on_hands) healed = ch->level * 3; else if (sn == skill_lookup("heal")) healed = healed / 2; else { healed /= 4; //chance to cure is positivly affected by rank diff. between caster and target. healed *=(float) ch->level / vic->level; } //And we roll if success. if (number_percent() < healed) //SUCCESS { //Different messges for lay on hands and regular healing. if(sn == gsn_lay_on_hands) act("You purge the taint from $N's blood and soul", ch, NULL, vic, TO_CHAR); else act("The power of your healing purges the taint from $N's body and soul.", ch, NULL, vic, TO_CHAR); //And the single healing message. act("The bite wound sizzles, smokes and then quickly heals and disappears.", ch, NULL, vic, TO_ROOM); return TRUE; } else { //FAILURE has its price. act("Your efforts are in vain, the foul mark remains.", ch, NULL, vic, TO_CHAR); act("The bite wound smokes momentarly then explodes in a fountain of puss.", ch, NULL, vic, TO_ROOM); damage(vic, vic, healed, gsn_embrace_poison, DAM_POISON, TRUE); } return FALSE; }//end heal_embrace_check. void spell_timer( int sn, int level, CHAR_DATA *ch, void *vo,int target){ char arg[MIL]; int dur; CHAR_DATA* victim; target_name = one_argument( target_name, arg ); if (IS_NULLSTR(target_name)) return; victim = get_char_room( ch, NULL, target_name ); dur = atoi( arg ); if (victim == NULL) return; else{ AFFECT_DATA af; af.type = gsn_timer; af.level = ch->level; af.duration = dur; af.where = TO_NONE; af.bitvector = 0; af.modifier = 0; af.location= APPLY_NONE; affect_join(victim, &af); } }