/***************************************************************************
* 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 "magic.h"
#include "recycle.h"
#include "interp.h"
extern char *target_name;
extern bool effect_manalock(int sn, int level, CHAR_DATA* ch, CHAR_DATA* victim);
#define WEP_NAMED (dd)
void spell_mind_thrust( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA* victim = (CHAR_DATA *) vo;
int dam = dice(level / 5, 5) + 2 * level;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 2 * level;
if (level < 15
|| (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL, skill_table[sn].spell_type))
){
dam /= 2;
}
else{
AFFECT_DATA af;
af.where = TO_AFFECTS;
af.type = sn;
af.level = ch->level;
af.duration = number_range(1, 2);
af.location = APPLY_SAVING_MENTAL;
af.modifier = number_range(1, 4);
af.bitvector = 0;
affect_join(victim,&af);
act_new( "You become less confident.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N becomes less confident.",ch,NULL,victim,TO_CHAR);
}
damage( ch, victim, dam, sn, DAM_MENTAL, TRUE);
}
void spell_mind_disruption( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(level / 5, 5) + 2 * level;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 2 * level;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
dam /= 2;
else if (dam > 1){
//make it harder to concentrate on spells
AFFECT_DATA* paf, af;
if ( (paf = affect_find(victim->affected, gsn_mind_disrupt)) == NULL
|| paf->modifier > -60){
af.type = gsn_mind_disrupt;
af.level = ch->level;
af.duration = 1;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = -20;
affect_join( victim, &af );
act("You disrupt $N's ability to concentrate.", ch, NULL, victim, TO_CHAR);
act("$n disrupts your ability to concentrate.", ch, NULL, victim, TO_VICT);
}
}
damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}
void spell_mind_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(level / 5, 5) + 3 * level;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 3 * level;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
dam /= 2;
victim->mana = UMAX(0, victim->mana - dam / 2 );
damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}
void spell_psychic_crush( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(4, 3) + level * 2;
if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
dam /= 2;
if (!IS_SET(victim->act, ACT_UNDEAD) && number_percent() < level)
{
send_to_char("You feel you psyche slip.\n\r", victim);
act("$N's eyes glaze over momentarly.", victim, NULL, victim, TO_ROOM);
victim->mana = UMAX(0, victim->mana - dam / 2);
}
damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}
void spell_psionic_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *vch, *vch_next;
int dam = 0;
act("You send a blast of mental energy through the room.",ch,NULL,NULL,TO_CHAR);
act("A blast of mental energy surges through the room.",ch,NULL,NULL,TO_ROOM);
for (vch = ch->in_room->people; vch; vch = vch_next){
vch_next = vch->next_in_room;
if ( vch == ch || is_area_safe_quiet(ch,vch))
continue;
dam = dice(level / 5, 10) + 3 * level;
if (is_affected(ch, gsn_mindsurge))
dam = 100 + 3 * level;
if (psiamp_failed(ch, vch, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, vch, DAM_MENTAL,skill_table[sn].spell_type))
dam /= 2;
else if (!IS_UNDEAD(vch)){
/* paralyze */
if (!is_affected(vch, gsn_paralyze)){
AFFECT_DATA af;
act("$n has been paralyzed!", vch, NULL, NULL, TO_ROOM);
act("You have been paralyzed!", vch, NULL, NULL, TO_CHAR);
af.type = gsn_paralyze;
af.level = level;
af.duration = number_range(1, 3);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 3 * af.duration;
affect_to_char( vch, &af );
}
}
m_yell(ch,vch,FALSE);
damage( ch, vch, dam, sn, DAM_MENTAL,TRUE);
}
}
/* mental spells do more damage */
void spell_psychic_purge( 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 )
|| check_immune(victim, DAM_MENTAL, FALSE) == IS_VULNERABLE)
{
if (victim == ch)
act("You are already vulnerable to mental attacks.",ch,NULL,victim,TO_CHAR);
else
act("$N is already vulnerable to mental attacks.",ch,NULL,victim,TO_CHAR);
return;
}
if (IS_UNDEAD(victim)
|| (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type))
){
act("$N resists your efforts.", 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( "You are now more vulnerable to mental damage.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N is now vulnerable to mental damage.",ch,NULL,victim,TO_CHAR);
}
void spell_photon( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
AFFECT_DATA af;
if (is_affected(ch, gen_photon_wall)){
send_to_char("You are already shielded.\n\r", ch);
return;
}
af.where = TO_AFFECTS;
af.type = gen_photon_wall;
af.level = level;
af.duration = 24;
af.modifier = 0;
af.location = 0;
af.bitvector = 0;
affect_to_char( ch, &af );
}
void spell_flesh_armor( 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("Your flesh has already been hardened.",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level / 2;
if (ch->class == class_lookup("psionicist"))
af.modifier = -25 - level / 2;
else
af.modifier = -20;
af.location = APPLY_AC;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You cause your flesh to numb and thicken.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n's flesh becomes inanimate.",victim,NULL,NULL,TO_ROOM);
}
void spell_detect_aura( 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 can already detect auras.",ch,NULL,victim,TO_CHAR);
return;
}
affect_strip(victim, skill_lookup("detect good"));
affect_strip(victim, skill_lookup("detect evil"));
affect_strip(victim, skill_lookup("detect magic"));
affect_strip(victim, skill_lookup("detect invis"));
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level > 25 ? 48 : 24;
af.modifier = 0;
af.location = 0;
af.bitvector = AFF_DETECT_GOOD;
affect_to_char( victim, &af );
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.modifier = 0;
af.location = 0;
af.bitvector = AFF_DETECT_EVIL;
affect_to_char( victim, &af );
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.modifier = 0;
af.location = 0;
af.bitvector = AFF_DETECT_MAGIC;
affect_to_char( victim, &af );
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.modifier = 0;
af.location = 0;
af.bitvector = AFF_DETECT_INVIS;
affect_to_char( victim, &af );
act_new( "You can now detect auras.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}
void spell_displacement( 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("Your image is already projected away from your body.",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 8 + level;
af.modifier = -(10 + level);
af.location = APPLY_AC;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You project your image away from your body.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n seems to move away from where you thought $e was.",victim,NULL,NULL,TO_ROOM);
}
void spell_awaken( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim;
AFFECT_DATA af;
if ( ( victim = get_char_world( ch, target_name ) ) == NULL )
{
send_to_char( "They aren't here.\n\r",ch );
return;
}
if (is_affected(ch, sn)){
send_to_char("You are too tired for another attempt.\n\r", ch);
return;
}
if ( IS_AWAKE(victim) )
{
act("They are already awake.",ch,NULL,victim,TO_CHAR);
return;
}
if (IS_UNDEAD(victim))
{
sendf(ch, "You can't awaken %s!\n\r", PERS(victim,ch));
return;
}
act_new( "A voice in your head commands you to wake up.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
act("You have awakened $N.",ch,NULL,victim,TO_CHAR);
affect_strip(victim, gsn_sleep);
do_stand(victim,"");
af.type = sn;
af.level = level;
af.duration = number_fuzzy(4);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.modifier = 0;
af.location = APPLY_NONE;
affect_to_char(ch, &af);
}
void spell_mental_drain( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA* victim = (CHAR_DATA *) vo;
int dam = UMAX(25, victim->mana / 5);
if ( psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type) ){
act("You failed to drain $N's mental power.",ch,NULL,victim,TO_CHAR);
act_new("You feel something invading your mind.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
return;
}
if (victim->mana < 1){
send_to_char("You only sense emptiness.\n\r", ch);
return;
}
ch->mana = UMIN(ch->max_mana, ch->mana + dam);
victim->mana -= dam;
victim->mana = UMAX(0, victim->mana);
act_new("You feel your mental powers slipping away!",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
act("You have absorbed $N's mental powers!",ch,NULL,victim,TO_CHAR);
}
void spell_iron_will( 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("Your self-control is already as strong as it can be.",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = ch->level/2;
af.modifier = -level/15;
af.location = APPLY_SAVING_SPELL;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "Your self-control increases.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}
void spell_cell_adjustment( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA* victim = (CHAR_DATA *) vo;
int chance = IS_NPC(ch) ? 100 : get_skill(ch,sn) - 25;
send_to_char("Your body begins to right itself.\n\r", victim);
if (is_affected(victim,gsn_blindness) && number_percent() < chance)
{
affect_strip(victim,gsn_blindness);
send_to_char("Your can see again.\n\r",victim);
}
if (!IS_NPC(ch) && is_affected(victim,gsn_death_grasp) && number_percent() < chance)
{
affect_strip(victim,gsn_death_grasp);
send_to_char("You regain some of your vitality.\n\r",victim);
}
if (is_affected(victim,gsn_poison) && number_percent() < chance)
{
affect_strip(victim,gsn_poison);
send_to_char("You feel less sick.\n\r",victim);
}
if (is_affected(victim,gsn_plague) && number_percent() < chance)
{
affect_strip(victim,gsn_plague);
send_to_char("Your sores vanish.\n\r",victim);
}
if (!IS_NPC(ch) && is_affected(victim,skill_lookup("dysentery")) && number_percent() < chance)
{
affect_strip(victim,skill_lookup("dysentery"));
send_to_char("Your bowel movements returns to normal.\n\r",victim);
}
if (is_affected(victim,gsn_enfeeblement) && number_percent() < chance)
{
affect_strip(victim,gsn_enfeeblement);
send_to_char("Your sores vanish.\n\r",victim);
}
if (is_affected(victim,gsn_embrace_poison) && number_percent() < chance)
affect_strip(victim,gsn_embrace_poison);
}
void spell_bio_manipulation( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA* victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
int type = ch->fighting ? number_range(0,3) : number_range(0,2);
if (IS_UNDEAD(victim))
{
send_to_char("Strange, but the cells are totaly inert, almost as if dead...\n\r", ch);
return;
}
switch (type)
{
case (0):
af.where = TO_AFFECTS;
af.type = gsn_gag;
af.level = ch->level;
af.duration = number_range(0,2);
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_join(victim,&af);
act_new( "Your vocal cords grow inanimate.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("You impare $N's vocal cords.",ch,NULL,victim,TO_CHAR);
break;
case (1):
af.where = TO_AFFECTS;
af.type = gsn_silence;
af.level = ch->level;
af.duration = number_range(0,2);
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_join(victim,&af);
act_new( "Your hearing weakens.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("You impare $N's ear drums.",ch,NULL,victim,TO_CHAR);
break;
case (2):
af.where = TO_AFFECTS;
af.type = gsn_blindness;
af.level = ch->level;
af.duration = number_range(0,2);
af.location = 0;
af.modifier = 0;
af.bitvector = AFF_BLIND;
affect_join(victim,&af);
act_new( "Your vision begins to fail.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("You impare $N's optic nerves.",ch,NULL,victim,TO_CHAR);
break;
case (3):
WAIT_STATE(victim, 12 * number_range(1, 3) );
act_new( "Your motor functions stop working.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("You halt $N's motor functions.",ch,NULL,victim,TO_CHAR);
break;
}
}
void spell_ego_whip( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
int dam = number_fuzzy(level);
int svs_mental = ch->savingspell + ch->savingmental;
af.where = TO_AFFECTS;
af.type = gsn_ego_whip;
af.level = ch->level;
af.duration = number_range(2,3);
af.location = APPLY_SAVING_MENTAL;
af.modifier = -2 * svs_mental / 10;
af.bitvector = 0;
affect_join(victim,&af);
act_new( "You become less confident.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N becomes less confident.",ch,NULL,victim,TO_CHAR);
damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}
void spell_tele_lock( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if (is_safe(ch,victim) && victim != ch){
sendf(ch, "Not on %s.\n\r",PERS(victim,ch));
return;
}
if ( is_affected(victim, gsn_tele_lock))
{
if (victim == ch)
act("You are already locked down.",ch,NULL,victim,TO_CHAR);
else
act("$N is already locked down.",ch,NULL,victim,TO_CHAR);
return;
}
else if (ch == victim){
send_to_char("You failed.\n\r", ch);
return;
}
if (!psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
|| !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
{
af.where = TO_AFFECTS;
af.type = gsn_tele_lock;
af.level = ch->level;
af.duration = ch->level / 4;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You are now locked down",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N is now locked down.",ch,NULL,victim,TO_CHAR);
}
else
send_to_char("You failed.\n\r", ch);
}
void spell_enhance_armor( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
OBJ_DATA *obj = (OBJ_DATA *) vo;
int fail = 50, result, i;
char buf[MSL];
if (obj->item_type != ITEM_ARMOR)
{
send_to_char("That isn't an armor.\n\r",ch);
return;
}
if (obj->wear_loc != -1)
{
send_to_char("The item must be carried to be enchanted.\n\r",ch);
return;
}
if (IS_OBJ_STAT(obj,ITEM_PSI_ENHANCE))
{
send_to_char("This item is already psionically altered.\n\r",ch);
return;
}
if (obj->value[0] == 0 && obj->value[1] == 0 && obj->value[2] == 0 && obj->value[3] == 0)
{
send_to_char("This item can not be psionically enhanced at all.\n\r",ch);
return;
}
fail += obj->level;
fail -= level;
if (IS_OBJ_STAT(obj,ITEM_BLESS))
fail -= 10;
if (IS_OBJ_STAT(obj,ITEM_MAGIC))
fail += 25;
fail -= get_curr_stat(ch,STAT_LUCK) - 16;
fail = URANGE(5,fail,85);
result = number_percent();
SET_BIT(obj->extra_flags, ITEM_MAGIC);
if (result < (fail / 5) && !IS_IMMORTAL(ch))
{
act("$p glows red hot and melts!",ch,obj,NULL,TO_ALL);
sprintf( buf, "lump %s", obj->material);
free_string( obj->name );
obj->name = str_dup( buf );
sprintf( buf, "A lump of %s", obj->material);
free_string( obj->short_descr );
obj->short_descr = str_dup( buf );
sprintf( buf, "A lump of %s lies here.", obj->material);
free_string( obj->description );
obj->description = str_dup( buf );
obj->wear_flags = ITEM_TAKE + ITEM_HOLD;
for (i = 0; i < 4; i++)
obj->value[i] = 0;
return;
}
if (result < (fail / 3) && !IS_IMMORTAL(ch))
{
SET_BIT(obj->extra_flags, ITEM_PSI_ENHANCE);
act("$p becomes mis-shapened.",ch,obj,NULL,TO_ALL);
for (i = 0; i < 4; i++)
obj->value[i] = 0;
obj->condition = 0;
return;
}
if ( result <= fail && !IS_IMMORTAL(ch))
{
send_to_char("The molecules stir for a second but stop.\n\r",ch);
return;
}
SET_BIT(obj->extra_flags, ITEM_PSI_ENHANCE);
act("$p is enhanced to perfection!",ch,obj,NULL,TO_ALL);
for (i = 0; i < 4; i++){
obj->value[i] = UMIN(20, obj->value[i] + obj->value[i] * level / 100);
}
}
void spell_there_not_there( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
OBJ_DATA *obj = (OBJ_DATA*) vo;
AFFECT_DATA af;
if ((!CAN_WEAR(obj, ITEM_TAKE)
|| (CAN_WEAR(obj, ITEM_NO_SAC) && obj->timer == 0)
|| obj->item_type == ITEM_CABAL
|| obj->wear_flags == 0)
&& obj->timer == 0//time is here so requested items can be affected.
//(request items will have above flags, but times is != 0)
){
send_to_char("Not on that object!\n\r", ch);
return;
}
if (is_affected_obj(obj, sn))
{
send_to_char("This item is already phased out.\n\r",ch);
return;
}
if (is_affected(ch, sn))
{
send_to_char("You are not ready for another attempt.\n\r", ch);
return;
}
if (obj->item_type == ITEM_CORPSE_PC
|| obj->pIndexData->vnum == get_temple_pit(ch->in_room->vnum)){
send_to_char("Not on that object.\n\r", ch);
return;
}
af.type = sn;
af.level = level;
af.duration = level / 4;
af.location = 0;
af.modifier = 0;
af.where = TO_AFFECTS;
af.bitvector = 0;
affect_to_char(ch, &af);
affect_to_obj(obj, &af);
act("You phase $p out of this dimension.", ch, obj, NULL, TO_CHAR);
act("You see something disappear from $n's hands.", ch, NULL, NULL, TO_ROOM);
}
void spell_phase_shift( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
ROOM_INDEX_DATA *room;
if (!IS_NULLSTR(target_name )){
spell_mind_store( sn, level, ch, vo, target );
return;
}
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL)
{
sendf(ch, "You cannot shift while on %s!\n\r",ch->pcdata->pStallion->short_descr);
return;
}
if (ch->pcdata->beacon == 0 || (room = get_room_index(ch->pcdata->beacon)) == NULL)
room = get_room_index(get_temple(ch));
if ( IS_SET(room->room_flags, ROOM_SAFE)
|| IS_SET(room->room_flags, ROOM_PRIVATE)
|| IS_SET(room->room_flags, ROOM_SOLITARY)
|| IS_SET(room->room_flags, ROOM_NO_GATEIN)
|| IS_SET(ch->in_room->room_flags, ROOM_NO_GATEOUT)
|| IS_SET(ch->in_room->room_flags, ROOM_NO_INOUT)
|| is_affected(ch, gsn_tele_lock)
|| IS_SET(room->room_flags, ROOM_NO_INOUT))
{
send_to_char("You failed the phase shift.\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;
}
act("$n closes $s eyes and vanishes.",ch,NULL,NULL,TO_ROOM);
act("You close your eyes and vanish.",ch,NULL,NULL,TO_CHAR);
char_from_room(ch);
char_to_room(ch,room);
act("$n suddenly appears and opens $s eyes.",ch,NULL,NULL,TO_ROOM);
do_look(ch,"auto");
}
void spell_mind_store( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
char arg[MSL];
one_argument(target_name, arg);
if (arg[0] != '\0' && !str_cmp(arg, "none"))
{
ch->pcdata->beacon = 0;
send_to_char("You empty your mind.\n\r",ch);
return;
}
else
{
if (ch->in_room == NULL)
return;
if ( IS_SET(ch->in_room->room_flags, ROOM_SAFE)
|| IS_SET(ch->in_room->room_flags, ROOM_PRIVATE)
|| IS_SET(ch->in_room->room_flags, ROOM_SOLITARY)
|| IS_SET(ch->in_room->room_flags, ROOM_NO_GATEIN)
|| IS_SET(ch->in_room->room_flags, ROOM_NO_INOUT))
{
send_to_char("You failed to memorize this room.\n\r",ch);
return;
}
send_to_char("You memorize this room.\n\r",ch);
ch->pcdata->beacon = ch->in_room->vnum;
}
}
void spell_levitate( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA*) vo;
AFFECT_DATA af;
if ( is_affected( victim, gen_levitation )){
send_to_char("You are already levitated.\n\r", ch);
return;
}
af.type = gen_levitation;
af.level = level;
af.duration = URANGE(12, level - 2, 48);
af.where = TO_AFFECTS;
af.bitvector = AFF_FLYING;
af.modifier = APPLY_NONE;
af.location = 0;
if (!IS_AFFECTED(ch, AFF_FLYING)){
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);
}
affect_to_char( victim, &af );
}
void do_wish( CHAR_DATA* ch, char* argument){
AFFECT_DATA* paf;
CHAR_DATA* vch;
const int dur = 24;
const int gsn_wish = skill_lookup("wish");
if ( (paf = affect_find(ch->affected, gsn_wish)) == NULL
|| paf->modifier){
send_to_char("Huh?\n\r", ch);
return;
}
if (IS_NULLSTR(argument)){
send_to_char("You may wish for FOOD, TRAINING, PROTECTION, or HEALING.\n\r", ch);
return;
}
else if (!str_prefix(argument, "food")){
act("The magical flames roar with power as $n wishes for food.", ch, NULL, NULL, TO_ROOM);
act("The magical flames roar with power as you wish for food.", ch, NULL, NULL, TO_CHAR);
paf->modifier = TRUE;//completed wish
paf->duration = dur;
for (vch = ch->in_room->people; vch; vch = vch->next_in_room){
if (IS_NPC(vch) || !is_same_group(ch, vch))
continue;
if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_NOMAGIC))
continue;
send_to_char("You feel all traces of hunger and thirst disappear.\n\r", vch);
vch->pcdata->condition[COND_HUNGER] = 100;
vch->pcdata->condition[COND_THIRST] = 100;
}
WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
return;
}
else if (!str_prefix(argument, "training")){
CHAR_DATA* trainer;
AFFECT_DATA af;
act("The magical flames roar with power as $n wishes for training.", ch, NULL, NULL, TO_ROOM);
act("The magical flames roar with power as you wish for training.", ch, NULL, NULL, TO_CHAR);
paf->modifier = TRUE;//completed wish
paf->duration = dur;
trainer = create_mobile(get_mob_index(MOB_VNUM_WISH_TRAINER));
char_to_room(trainer, ch->in_room);
af.type = gsn_timer;
af.level = paf->level;
af.duration = 3;
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(trainer, &af);
act("$n suddenly appears before you.", trainer, NULL, NULL, TO_ROOM);
do_say(trainer, "What do you wish to practice or train?");
WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
return;
}
else if (!str_prefix(argument, "protection")){
int sn = 0;
act("The magical flames roar with power as $n wishes for protection.", ch, NULL, NULL, TO_ROOM);
act("The magical flames roar with power as you wish for protection.", ch, NULL, NULL, TO_CHAR);
paf->modifier = TRUE;//completed wish
paf->duration = dur;
/* select random spell */
switch (number_range(1, 4)){
case 1: sn = skill_lookup("armor"); break;
case 2: sn = skill_lookup("shield"); break;
case 3: sn = skill_lookup("stone skin"); break;
default: sn = gsn_sanctuary; break;
}
for (vch = ch->in_room->people; vch; vch = vch->next_in_room){
if (IS_NPC(vch) || !is_same_group(ch, vch))
continue;
if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_NOMAGIC))
continue;
(*skill_table[sn].spell_fun) ( sn, 60, vch, vch, 0);
}
WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
return;
}
else if (!str_prefix(argument, "healing")){
act("The magical flames roar with power as $n wishes for healing.", ch, NULL, NULL, TO_ROOM);
act("The magical flames roar with power as you wish for healing.", ch, NULL, NULL, TO_CHAR);
paf->modifier = TRUE;//completed wish
paf->duration = dur;
for (vch = ch->in_room->people; vch; vch = vch->next_in_room){
if (IS_NPC(vch) || !is_same_group(ch, vch))
continue;
if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_NOMAGIC))
continue;
if (vch->hit > 4 * vch->max_hit / 5){
send_to_char("You lack any serious wounds to heal.\n\r", vch);
}
else{
act("Some of $n's wounds disappear.", vch, NULL, NULL, TO_ROOM);
send_to_char("Some of your wounds disappear.\n\r", vch);
vch->hit = UMAX(4 * vch->max_hit / 5, vch->hit + vch->max_hit / 3);
update_pos( vch );
}
if (number_percent() < 50){
if (IS_AFFECTED(vch, AFF_BLIND)){
check_dispel(paf->level,vch,gsn_blindness);
}
if (IS_AFFECTED(vch,AFF_POISON)){
check_dispel(paf->level,vch,gsn_poison);
}
if (IS_AFFECTED(vch, AFF_PLAGUE)){
check_dispel(paf->level,vch,gsn_plague);
}
if (IS_AFFECTED(vch, AFF_CURSE)){
check_dispel(paf->level,vch,gsn_curse);
}
}
}
WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
return;
}
else
do_wish( ch, "");
}
/* first part of the do_wish */
void spell_wish( 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 not ready to make another wish.\n\r", ch);
return;
}
if (number_percent() > get_skill(ch, sn)){
int dam = number_range(150, 250);
send_to_char("Your self control slips for a moment!\n\r", ch );
act("$n's self control slips for a moment!\n\r", ch, NULL, NULL, TO_ROOM);
damage(ch, ch, dam, sn, DAM_INTERNAL, TRUE);
return;
}
af.type = sn;
af.level = level;
af.duration = 3;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.modifier = APPLY_NONE;
af.location = FALSE;//wish not made yet
affect_to_char( victim, &af );
act("A ring of blue flames erupts around $n.", ch, NULL, NULL, TO_ROOM );
act("A ring of blue flames erupts around you.", ch, NULL, NULL, TO_CHAR );
act("A voice says '`#I await your wish $n.``'", ch, NULL, NULL, TO_ALL );
send_to_char("Use the \"wish\" command to complete your wish.\n\r", ch );
}
void spell_gravitate( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
OBJ_DATA *obj = (OBJ_DATA *) vo;
AFFECT_DATA af;
if ( is_affected_obj( obj, sn))
{
send_to_char("That object is already gravitated.\n\r", ch);
return;
}
if ( is_affected_obj( obj, gsn_levitate))
{
act("$p falls to the ground.",ch,obj,NULL,TO_CHAR);
affect_strip_obj(obj, gsn_levitate);
return;
}
if ( (!CAN_WEAR(obj, ITEM_TAKE)
|| CAN_WEAR(obj, ITEM_NO_SAC)
|| obj->weight > 1000
|| obj->wear_flags == 0
|| obj->item_type == ITEM_CABAL)
&& obj->timer == 0
//time is here so requested items can be affected.
//(request items will have above flags, but times is != 0)
)
{
send_to_char("The spell seems to fail.\n\r", ch);
return;
}
act("$p seems to gain weight and sinks into the ground.", ch, obj, NULL, TO_ALL);
af.type = sn;
af.level = level;
af.duration = level;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_to_obj(obj, &af);
}
void spell_bio_feedback( 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 are already controlling your blood flow.",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 8 + level;
af.modifier = -30;
af.location = APPLY_AC;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You control your blood flow.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}
void spell_psychic_healing( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
int heal = dice(3, 8) + level;
victim->hit = UMIN( victim->hit + heal, victim->max_hit );
update_pos( victim );
act_new("You heal yourself.", ch,NULL,victim,TO_CHARVICT,POS_DEAD );
}
void spell_pyramid_of_force( 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 are already surrounded by a pulsating pyramid.",ch,NULL,victim,TO_CHAR);
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;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 12;
af.modifier = 0;
af.location = 0;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You are surrounded by a pulsating pyramid.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n is surrounded by a pulsating pyramid.",victim,NULL,NULL,TO_ROOM);
}
void spell_terror( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if (ch == victim)
{
send_to_char("You scare yourself.\n\r",ch);
return;
}
if ( is_affected(victim, gsn_fear)){
act("$N is already cowering in fear.",ch,NULL,victim,TO_CHAR);
return;
}
if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)
|| IS_SET(victim->act, ACT_UNDEAD)){
act_new( "You feel scared for a second.",ch, NULL, victim, TO_CHARVICT, POS_DEAD);
act("You failed to induce terror in $N.",ch, NULL, victim,TO_CHAR);
return;
}
act_new("You start to panic as your mind runs away from you!",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N starts to panic in terror!",ch,NULL,victim,TO_CHAR);
af.where = TO_AFFECTS;
af.type = gsn_fear;
af.level = level;
af.location = 0;
af.duration = 1;
af.bitvector = 0;
af.modifier = 20;
affect_to_char(victim, &af);
}
void spell_body_weaponry( 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("Your hands are already shaped like weapons.",ch,NULL,victim,TO_CHAR);
return;
}
if ( get_eq_char(ch,WEAR_WIELD) != NULL)
{
act("You can't be wielding a weapon.",ch,NULL,victim,TO_CHAR);
return;
}
if ( get_eq_char(ch,WEAR_SHIELD) != NULL)
{
act("You can't be holding a shield.",ch,NULL,victim,TO_CHAR);
return;
}
if ( get_eq_char(ch,WEAR_HOLD) != NULL)
{
act("You can't be holding anything.",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 24;
af.modifier = ch->level / 10;
af.location = APPLY_HITROLL;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You shape your hands into weapons.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n shapes $s hands into weapons.",victim,NULL,NULL,TO_ROOM);
}
void spell_ectoplasm( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
AFFECT_DATA af;
if (get_summoned(ch, MOB_VNUM_VAPOR) + get_summoned(ch, MOB_VNUM_SOLID) > 0)
{
send_to_char("You already have ectoplasm.\n\r",ch);
return;
}
if ( is_affected( ch, sn ) )
{
send_to_char("You can not conjure up more ectoplasm.\n\r",ch);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 24;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_to_char( ch, &af );
act ("You conjure up some ectoplasm!", ch, NULL, NULL, TO_CHAR);
act ("$n conjures up some ectoplasm!", ch, NULL, NULL, TO_ROOM);
if (number_percent() <= 50)
ecto_vapor(ch, NULL);
else
ecto_solid(ch, NULL);
}
void ecto_vapor(CHAR_DATA *ch, CHAR_DATA *ecto)
{
CHAR_DATA* mob;
MOB_INDEX_DATA* pMobIndex;
if (ecto == NULL)
{
mob = create_mobile( get_mob_index( MOB_VNUM_VAPOR ) );
char_to_room(mob,ch->in_room);
mob->level = ch->level;
mob->alignment = ch->alignment;
mob->max_hit = ch->level*10;
mob->hit = mob->max_hit;
mob->hitroll = (ch->level/10 + 20) / 2;
mob->damroll = (ch->level/10 + 20) / 2;
mob->damage[DICE_NUMBER] = 4;
mob->damage[DICE_TYPE] = ch->level/10 +1;
SET_BIT(mob->affected_by, AFF_CHARM);
mob->comm = COMM_NOTELL|COMM_NOYELL|COMM_NOCHANNELS;
mob->summoner = ch;
add_follower(mob,ch);
mob->leader = ch;
return;
}
pMobIndex = get_mob_index( MOB_VNUM_VAPOR);
ecto->max_hit /= 2;
ecto->hit /= 2;
ecto->hitroll /= 2;
ecto->damroll /= 2;
ecto->damage[DICE_NUMBER] = 4;
act ("$n vaporizes!", ecto, NULL, NULL, TO_ALL);
ecto->spec_fun = pMobIndex->spec_fun;
free_string(ecto->name);
ecto->name = str_dup( pMobIndex->player_name );
free_string(ecto->short_descr);
ecto->short_descr = str_dup( pMobIndex->short_descr );
free_string(ecto->long_descr);
ecto->long_descr = str_dup( pMobIndex->long_descr );
free_string(ecto->description);
ecto->description = str_dup( pMobIndex->description );
if (pMobIndex->new_format)
{
ecto->act = pMobIndex->act;
ecto->act2 = pMobIndex->act2;
REMOVE_BIT(ecto->affected_by, ecto->pIndexData->affected_by);
SET_BIT(ecto->affected_by, pMobIndex->affected_by);
ecto->alignment = pMobIndex->alignment;
ecto->dam_type = pMobIndex->dam_type;
ecto->off_flags = pMobIndex->off_flags;
ecto->imm_flags = pMobIndex->imm_flags;
ecto->res_flags = pMobIndex->res_flags;
ecto->vuln_flags = pMobIndex->vuln_flags;
ecto->sex = pMobIndex->sex;
if (ecto->sex == 3)
ecto->sex = number_range(1,2);
ecto->race = pMobIndex->race;
ecto->form = pMobIndex->form;
ecto->parts = pMobIndex->parts;
ecto->size = pMobIndex->size;
}
ecto->pIndexData = pMobIndex;
interpret(ecto, "remove all");
interpret(ecto, "drop all");
}
void ecto_solid(CHAR_DATA *ch, CHAR_DATA *ecto)
{
MOB_INDEX_DATA *pMobIndex;
CHAR_DATA *mob;
if (ecto == NULL)
{
mob = create_mobile( get_mob_index( MOB_VNUM_SOLID ) );
char_to_room(mob,ch->in_room);
mob->level = ch->level;
mob->alignment = ch->alignment;
mob->max_hit = ch->level*20;
mob->hit = mob->max_hit;
mob->hitroll = ch->level/10 + 20;
mob->damroll = ch->level/10 + 20;
mob->damage[DICE_NUMBER] = 8;
mob->damage[DICE_TYPE] = ch->level/10 +1;
SET_BIT(mob->affected_by, AFF_CHARM);
mob->comm = COMM_NOTELL|COMM_NOYELL|COMM_NOCHANNELS;
mob->summoner = ch;
add_follower(mob,ch);
mob->leader = ch;
return;
}
pMobIndex = get_mob_index( MOB_VNUM_SOLID);
act ("$n solidifies!", ecto, NULL, NULL, TO_ALL);
ecto->max_hit *= 2;
ecto->hit *= 2;
ecto->hitroll *= 2;
ecto->damroll *= 2;
ecto->damage[DICE_NUMBER] = 8;
ecto->spec_fun = pMobIndex->spec_fun;
free_string(ecto->name);
ecto->name = str_dup( pMobIndex->player_name );
free_string(ecto->short_descr);
ecto->short_descr = str_dup( pMobIndex->short_descr );
free_string(ecto->long_descr);
ecto->long_descr = str_dup( pMobIndex->long_descr );
free_string(ecto->description);
ecto->description = str_dup( pMobIndex->description );
if (pMobIndex->new_format)
{
ecto->act = pMobIndex->act;
ecto->act2 = pMobIndex->act2;
REMOVE_BIT(ecto->affected_by, ecto->pIndexData->affected_by);
SET_BIT(ecto->affected_by, pMobIndex->affected_by);
ecto->alignment = pMobIndex->alignment;
ecto->dam_type = pMobIndex->dam_type;
ecto->off_flags = pMobIndex->off_flags;
ecto->imm_flags = pMobIndex->imm_flags;
ecto->res_flags = pMobIndex->res_flags;
ecto->vuln_flags = pMobIndex->vuln_flags;
ecto->sex = pMobIndex->sex;
if (ecto->sex == 3)
ecto->sex = number_range(1,2);
ecto->race = pMobIndex->race;
ecto->form = pMobIndex->form;
ecto->parts = pMobIndex->parts;
ecto->size = pMobIndex->size;
}
ecto->pIndexData = pMobIndex;
}
void spell_hypnosis( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( victim == ch )
{
send_to_char( "You can't place yourself under hypnosis!\n\r", ch );
return;
}
if (get_curr_stat(ch, STAT_INT ) < get_curr_stat(victim, STAT_INT))
{
send_to_char("You cannot hypnotize someone smarter than you.\n\r", ch);
return;
}
if (!IS_AWAKE(victim) || is_affected(victim,gsn_ecstacy))
{
act("$N need to be conscious for you to take over $S mind.",ch,NULL,victim,TO_CHAR);
return;
}
if ( IS_AFFECTED(victim, AFF_SLEEP) )
{
act( "$N is already asleep.", ch, NULL, victim, TO_CHAR);
return;
}
if (is_affected(victim, gen_watchtower)){
sendf( ch, "%s is shielded within the Watchtower.\n\r", PERS(victim, ch ));
return;
}
act("$n locks $N's gaze as beads of sweat form on $s forehead.", ch, NULL, victim, TO_NOTVICT);
act("You lock $N's gaze and try to force $M to sleep.", ch, NULL, victim, TO_CHAR);
if ( (IS_NPC(victim) && IS_SET(victim->act,ACT_TOO_BIG) )
|| IS_UNDEAD(victim)
|| (psiamp_failed(ch, victim, level, DAM_CHARM, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_CHARM,skill_table[sn].spell_type))
)
{
act( "You failed.", 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 = 4;
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,"");
}
}
/* field_of_fear effect */
inline bool effect_field_of_fear(CHAR_DATA* ch)
{
AFFECT_DATA af;
//bool
//data
int chance = 0;
//const
const int base_chance = 25;
//EZ
if (!IS_SET(ch->in_room->room_flags2, ROOM_PSI_FEAR)
|| IS_IMMORTAL(ch)
|| is_affected(ch, gsn_mental_barrier)
|| check_immune(ch, DAM_MENTAL, TRUE) < IS_NORMAL
|| IS_UNDEAD(ch)
)
return FALSE;
//get the chance to scare them away
chance = base_chance + 2 * (ch->level / 2 - ch->in_room->psitimer);
chance += (get_curr_stat(ch, STAT_INT) - 20) * 5;
if (number_percent() < chance)
{
act("The hairs on your body stand on end.",ch,NULL,NULL,TO_ROOM);
return FALSE;
}
if (is_affected(ch, skill_lookup("fear"))) {
return FALSE;
}
//we scare them.
send_to_char("You are overpowered with intense fear.\n\r", ch);
act("$n's eyes widen in fear", ch, NULL, NULL, TO_ROOM);
/* attach effect to hurt skills */
af.type = skill_lookup("fear");
af.level = ch->in_room->psitimer;
af.duration = number_range(0,1);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(ch, &af);
return TRUE;
}//END IF SUCCESS
void spell_field_of_fear( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
AFFECT_DATA af;
int chance = int_app[get_curr_stat(ch,STAT_INT)].learn;
CHAR_DATA *ich, *ich_next;
if (is_affected(ch, sn))
{
send_to_char("You are not ready for another attempt.\n\r", ch);
return;
}
if (IS_SET(ch->in_room->room_flags2, ROOM_PSI_FEAR))
{
send_to_char("The area looks too safe to place an effective enchantement.\n\r", ch);
return;
}
for ( ich = ch->in_room->people; ich != NULL; ich = ich->next_in_room )
{
if (IS_NPC(ch))
chance -= 2;
else
chance -= 5;
}
if (IS_SET(ch->in_room->room_flags, ROOM_SAFE)
|| ch->in_room->sector_type == SECT_CITY)
{
send_to_char("This room is far to peacefull for that.\n\r", ch);
return;
}
if (number_percent() > chance)
{
act("You failed to place a field of fear in this room!", ch, NULL, NULL, TO_CHAR );
act("The hairs on your body tingle.",ch,NULL,NULL,TO_ROOM);
return;
}
act("You place a field of fear in this room!", ch, NULL, NULL, TO_CHAR );
act("$n places a field of fear in this room!",ch,NULL,NULL,TO_ROOM);
SET_BIT(ch->in_room->room_flags2, ROOM_PSI_FEAR);
ch->in_room->psitimer = ch->level / 2;
for ( ich = ch->in_room->people; ich != NULL; ich = ich_next )
{
ich_next = ich->next_in_room;
effect_field_of_fear(ich);
}
af.type = sn;
af.level = level;
af.duration = ch->level / 4;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(ch, &af);
}
void spell_control_flames( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
OBJ_DATA *obj;
bool strong = TRUE;
int dam;
if ((obj = get_eq_char( victim, WEAR_LIGHT )) == NULL)
{
strong = FALSE;
if ((obj = get_eq_char( ch, WEAR_LIGHT )) == NULL)
{
send_to_char("Neither you nor your opponent are using a light source.\n\r", ch);
return;
}
}
dam = dice(2, 8) + UMAX(90, obj->level * 4);
if (!strong)
dam /= 2;
if ( saves_spell( level, victim, DAM_FIRE,skill_table[sn].spell_type) )
dam /= 2;
act( "$p glows brightly and shoots forth a ball of fire at you!", victim, obj, NULL, TO_CHAR );
act( "$p glows brightly and shoots forth a ball of fire at $n!", victim, obj, NULL, TO_ROOM );
damage( ch, victim, dam, sn, DAM_FIRE ,TRUE);
}
void spell_forget( 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("$N already forgot all $S spells.",ch,NULL,victim,TO_CHAR);
return;
}
if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)
|| IS_UNDEAD(victim))
if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)
||IS_UNDEAD(victim))
{
if (IS_UNDEAD(victim))
act("$N's mind seems cold and empty.", ch, NULL, victim, TO_CHAR);
act("You failed to make $N lose $S memory.",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 1 + (level > 38? 1 : 0);
af.modifier = 0;
af.location = 0;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "Your memory falters and you forget all your spells.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N forgets all $S spells.",ch,NULL,victim,TO_CHAR);
}
void spell_graft_weapon( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
OBJ_DATA *obj;
if ( is_affected( victim, sn ))
{
act("Your weapon is already grafted to your hands.",ch,NULL,victim,TO_CHAR);
return;
}
if ((obj = get_eq_char(ch,WEAR_WIELD)) == NULL)
{
act("You have to be wielding a weapon.",ch,NULL,victim,TO_CHAR);
return;
}
if (IS_OBJ_STAT(obj, ITEM_PSI_ENHANCE))
{
act("$p resists your attempts!", ch, obj, NULL, TO_CHAR);
return;
}
af.type = sn;
af.level = level;
af.duration = 24;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
act_new( "You graft $p to your hands.",victim,obj,NULL,TO_CHAR,POS_DEAD);
act("$n grafts $p to $s hands.",victim,obj,NULL,TO_ROOM);
}
void spell_ballistic_attack( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
OBJ_DATA *obj = (OBJ_DATA *) vo;
CHAR_DATA *victim;
int dam;
int weight = get_obj_weight(obj);
if ((victim = ch->fighting) == NULL)
{
send_to_char("You don't have the anger.\n\r", ch);
return;
}
if (!CAN_WEAR(obj, ITEM_TAKE)
|| CAN_WEAR(obj, ITEM_NO_SAC)
|| obj->item_type == ITEM_CABAL
|| is_affected_obj(obj, gsn_gravitate)
|| weight > 1000
)
{
send_to_char("You cannot lift that object.\n\r", ch);
return;
}
dam = dice(level / 10, 8);
if (is_affected_obj(obj, gsn_levitate))
dam += UMIN(weight, 500) / 5;
else
dam += UMIN(weight, 500) / 3;
if ( saves_spell( level, victim,DAM_BASH,skill_table[sn].spell_type) )
dam /= 2;
act( "$p rises in the air and suddenly flies straight at you!", victim, obj, ch, TO_CHAR );
act( "$p rises in the air and suddenly flies straight at $n!", victim, obj, ch, TO_ROOM );
damage( ch, victim, dam, sn, DAM_BASH ,TRUE);
/* move the object from where it is to the ground */
if (!ch->in_room)
return;
if (obj->carried_by)
obj_from_char(obj);
else if (obj->in_obj)
obj_from_obj(obj);
else if (obj->in_room)
obj_from_room(obj);
obj_to_room(obj, ch->in_room);
}
void spell_mental_barrier( 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 have already created a mental barrier",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 24;
af.modifier = -25;
af.location = APPLY_SAVING_MENTAL;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You create a mental barrier.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}
void spell_telekinetic_barrier( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
}
void spell_psychic_shout( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *vch, *vch_next;
int dam = dice(5, 8) + level * 2;
for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
{
vch_next = vch->next_in_room;
if ( saves_spell( level, vch, DAM_MENTAL,skill_table[sn].spell_type) )
dam /= 2;
if ( vch != ch && !is_area_safe(ch,vch))
{
m_yell(ch,vch,FALSE);
damage( ch, vch, dam, sn, DAM_MENTAL ,TRUE);
}
}
}
void spell_clairvoyance( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim;
DESCRIPTOR_DATA *orig;
ROOM_INDEX_DATA *location;
if ( ( victim = get_char_world( ch, target_name ) ) == NULL )
{
send_to_char( "They aren't here.\n\r",ch );
return;
}
if (ch == victim)
{
send_to_char("Why not simply open your eyes?\n\r", ch);
return;
}
if ((location = victim->in_room) == NULL)
return;
if ( room_is_private( location ) && get_trust(ch) < MAX_LEVEL)
{
send_to_char( "That room is private right now.\n\r", ch );
return;
}
if ( !have_access(ch,location) || IS_IMMORTAL(victim) || is_safe_quiet(ch, victim))
{
send_to_char( "Something blocks your attempts.\n\r",ch);
return;
}
if ( saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type ) )
{
send_to_char("You failed.\n\r", ch);
send_to_char("Your eyes feel funny.\n\r", victim);
return;
}
if (IS_UNDEAD(victim) && number_percent() < 60)
{
AFFECT_DATA af;
act("As begin to look through $N's eyes horros of undeath and forces of Limbo tear into you!", ch, NULL, victim, TO_CHAR);
damage(ch, ch, victim->level * 4, sn, DAM_NEGATIVE, TRUE);
send_to_char("Unable to stand the strain you collapse.\n\r", ch);
act("$n's eyes roll back and he collapses.", ch, NULL, NULL, TO_ROOM);
af.type = gsn_sleep;
af.level = level;
af.duration = 1 + victim->level > level? 1: 0
+ victim->level-2 > level? 1 : 0
+ victim->level - 6 > level? 2: 0;
af.where = TO_AFFECTS;
af.bitvector = AFF_SLEEP;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(ch, &af);
do_sleep(ch, "");
}
send_to_char("You look and feel through the faculties of your victim.\n\r", ch);
orig = victim->desc;
victim->desc = ch->desc;
if (number_percent() < 35)
interpret (victim, "score");
else
interpret (victim, "eq");
victim->desc = orig;
}
void spell_ghoul_touch( 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("They're already sluggish.\n\r",ch);
return;
}
act("A green glow envelops $n's hands.",ch,NULL,victim,TO_ROOM);
act("A green glow envelops your hands.",ch ,NULL,NULL, TO_CHAR);
if (saves_spell(level-2,victim,DAM_NEGATIVE,skill_table[sn].spell_type))
{
act("$N wasn't affected by the ghoul touch.",ch,NULL,victim,TO_CHAR);
if ( ch != victim)
act("You shake off $n's ghoul touch.",ch,NULL,victim,TO_VICT);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level/5;
af.location = 0;
af.modifier = 5;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new("You feel very sluggish.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N looks very sluggish.",ch,NULL,victim,TO_CHAR);
}
void spell_eternal_day( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
ROOM_INDEX_DATA * room;
AFFECT_DATA af;
int np = number_percent();
if (is_affected(ch,sn))
{
send_to_char("You cannot cast this spell yet.\n\r",ch);
return;
}
if (ch->in_room == NULL)
return;
room = ch->in_room;
if (room->pCabal)
{
send_to_char("Not in a cabal.\n\r",ch);
return;
}
if (np - 2*(get_curr_stat(ch,STAT_LUCK) - 16) < 50)
{
send_to_char("You failed to bathe the room with sunlight.\n\r",ch);
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.location = 0;
af.duration = 24;
af.bitvector = 0;
af.modifier = 0;
affect_to_char(ch,&af);
return;
}
if (IS_SET(room->room_flags2,ROOM_DAY))
{
send_to_char("This room is already bathed in sunlight.\n\r",ch);
return;
}
send_to_char("You bathe the room with eternal sunlight.\n\r",ch);
act("$n bathes the room with eternal sunlight.",ch,NULL,NULL,TO_ROOM);
SET_BIT(room->room_flags2,ROOM_DAY);
REMOVE_BIT(room->room_flags,ROOM_DARK);
REMOVE_BIT(room->room_flags2,ROOM_NIGHT);
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.location = 0;
af.duration = 200;
af.bitvector = 0;
af.modifier = 0;
affect_to_char(ch,&af);
}
void spell_everlasting_night( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
ROOM_INDEX_DATA * room;
AFFECT_DATA af;
int np = number_percent();
if (is_affected(ch,sn))
{
send_to_char("You cannot cast this spell yet.\n\r",ch);
return;
}
if (ch->in_room == NULL)
return;
room = ch->in_room;
if (room->pCabal)
{
send_to_char("Not in a cabal.\n\r",ch);
return;
}
if (np - 2*(get_curr_stat(ch,STAT_LUCK) - 16) < 50)
{
send_to_char("You failed to induce the room into night.\n\r",ch);
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.location = 0;
af.duration = 24;
af.bitvector = 0;
af.modifier = 0;
affect_to_char(ch,&af);
return;
}
if (IS_SET(room->room_flags2,ROOM_DAY))
{
send_to_char("This room is already stopped in nighttime.\n\r",ch);
return;
}
if (mud_data.time_info.hour > 6 && mud_data.time_info.hour < 19)
{
send_to_char("The sun disappears, never to appear in this room again.\n\r",ch);
act("The sun disappears, never to appear in this room again.",ch,NULL,NULL,TO_ROOM);
}
else
{
send_to_char("The night halts dead in its tracks.\n\r",ch);
act("$n stops the night in its tracks.",ch,NULL,NULL,TO_ROOM);
}
SET_BIT(room->room_flags2,ROOM_NIGHT);
SET_BIT(room->room_flags,ROOM_DARK);
REMOVE_BIT(room->room_flags2,ROOM_DAY);
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.location = 0;
af.duration = 200;
af.bitvector = 0;
af.modifier = 0;
affect_to_char(ch,&af);
}
void spell_apathey( 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("They're already apathetic.\n\r",ch);
return;
}
if (saves_spell(level-2,victim,DAM_MENTAL,skill_table[sn].spell_type))
{
act("$N wasn't affected by your apathey.",ch,NULL,victim,TO_CHAR);
if ( ch != victim)
act("You resist $n's attempt to apathetize you.",ch,NULL,victim,TO_VICT);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level/5;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new("You feel apathetic.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N looks around without a care.",ch,NULL,victim,TO_CHAR);
stop_follower( ch );
}
void spell_feedback( 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("They are already affected by feedback.\n\r",ch);
return;
}
if (saves_spell(level-2,victim,DAM_MENTAL,skill_table[sn].spell_type))
{
act("You failed to set a feedback on $N.",ch,NULL,victim,TO_CHAR);
if ( ch != victim)
act("$n failed to set a feedback on you.",ch,NULL,victim,TO_VICT);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = level/5;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new("Your are now set to feedback.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N is set to feedback.",ch,NULL,victim,TO_CHAR);
}
void spell_virtuous_light( int sn, int level, CHAR_DATA *ch, void *vo, int target)
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
int dur;
if(is_affected(victim,sn))
{
send_to_char("You are already filled with a virtuous light.\n\r",victim);
return;
}
dur = number_fuzzy(level/2);
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = dur;
af.bitvector = 0;
af.location = APPLY_AC;
af.modifier = -2*(level-10)/3;
affect_to_char( victim, &af );
af.location = APPLY_LUCK;
af.modifier = number_range( 1, 2);
affect_to_char( victim, &af );
send_to_char("The Light of Virtue fills you with conviction.\n\r",victim);
act("$n bows $s head and is filled with a virtuous light.",ch,NULL,NULL,TO_ROOM);
}
void spell_assist( 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_STATE2(ch, 24);
}
if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL)
{
send_to_char("Your mount refuses to enter the gate.\n\r",ch);
return;
}
if ( (victim = get_char_world( ch, target_name ) ) == NULL
|| victim == ch || victim->in_room == NULL || !can_see_room(ch,victim->in_room)
|| IS_NPC(victim) || !is_same_group(ch,victim)
|| 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_IMMORTAL(ch) && IS_IMMORTAL(victim))
|| (!IS_NPC(victim) && IS_SET(victim->act,PLR_NOSUMMON) && !is_pk(ch,victim))
|| is_affected(ch, gsn_tele_lock) || is_affected(victim,gsn_catalepsy) )
{
send_to_char("You failed to create a gate.\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;
}
if (ch->pet != NULL && ch->in_room == ch->pet->in_room)
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);
}
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);
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_unholy_strength(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
char arg[MIL];
AFFECT_DATA af, *paf;
//data
int sklevel = 0;//current level of the spell.
int gsn = 0 ;
//const
const int amplvl_mod = 10; //amount added onto lvl when duration is extended.
const int dur_mod = 5; //amount of duration extended.
const int mod_mod = 3; //amount added onto str/dam/svs for each additional cast.
const int lvl_mod = 10; //divisor for comparin lvl of spell to caster lvl.
//bool
bool is_message = FALSE;
one_argument(target_name, arg);
if (is_affected(ch, gsn = skill_lookup("calm")))
if (!check_dispel(level,ch,gsn))
{
send_to_char( "Your mind flares with demonic visions.\n\r", ch );
return;
}
if (is_affected(ch,gsn_drained))
{
send_to_char("You are too drained right now to try that.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
if (!is_affected(ch,sn))
{
af.type = sn;
af.where = TO_AFFECTS;
af.level = 1;
af.bitvector = 0;
af.duration = (level / lvl_mod);
af.modifier = UMAX(1, (level / lvl_mod) - 1);
af.location = APPLY_DAMROLL;
affect_to_char(ch,&af);
af.where = TO_AFFECTS;
af.level = 1;
af.duration = (level / lvl_mod);
af.bitvector = 0;
af.modifier = UMAX(1, (level / lvl_mod) - 1);
af.location = APPLY_HITROLL;
affect_to_char(ch,&af);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.duration = (level / lvl_mod);
af.level = 1;
af.modifier = UMIN(-1,-(level / lvl_mod - 1));
af.location = APPLY_SAVING_SPELL;
affect_to_char(ch,&af);
send_to_char("Vengence of the Eternal Army surges through your forsaken soul.\n\r",ch);
act("$n's body surges with unholy energy!",ch,NULL,NULL,TO_ROOM);
}
else
{
for(paf=ch->affected;paf!=NULL;paf=paf->next)
{
if(paf->type == sn)
{
sklevel = paf->level;
break;
}
}
if (sklevel == 0)
return;
else if(sklevel%lvl_mod > level/lvl_mod)
{
send_to_char("Your body has already reached the breaking point.\n\r",ch);
return;
}
else if(sklevel%lvl_mod > 0)
{
send_to_char("You bring your body closer to the breaking point.\n\r",ch);
act("$n screams in agony as his body surges with power!",ch,NULL,NULL,TO_ROOM);
for(paf=ch->affected;paf!=NULL;paf=paf->next)
{
if(paf->type == sn)
{
paf->level+= mod_mod;
if (paf->location == APPLY_HITROLL)
{
ch->hitroll+=mod_mod;
paf->modifier+=mod_mod;
}
if (paf->location == APPLY_DAMROLL)
{
ch->damroll+=mod_mod;
paf->modifier+=mod_mod;
}
if (paf->location == APPLY_SAVING_SPELL)
{
ch->savingspell-= mod_mod;
paf->modifier-= mod_mod;
}
}
}
}
}
}
else if (!str_cmp(arg,"amplify"))
{
for(paf=ch->affected;paf!=NULL;paf=paf->next)
{
if(paf->type == sn)
{
sklevel=paf->level;
if (sklevel/lvl_mod > level/lvl_mod)
{
send_to_char("Your body has already reached the breaking point.\n\r",ch);
return;
}
paf->level +=amplvl_mod;
paf->duration +=dur_mod;
is_message = TRUE;
}
}
if (is_message)
{
send_to_char("You amplify your allegiance with the Eternal Army.\n\r",ch);
act("$n screams in agony as his body surges with power!",ch,NULL,NULL,TO_ROOM);
}
else
send_to_char("You are not affected by unholy strength to amplify it.\n\r",ch);
}
else
send_to_char("To amplify your allegiance with the Eternal Army: <syntax: ca 'unholy strength' amplify>.\n\r",ch);
}
void spell_hex( 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("$N is already jinxed by a hex.",ch,NULL,victim,TO_CHAR);
return;
}
if ( saves_spell( level,victim,DAM_NEGATIVE,skill_table[sn].spell_type) )
{
act("You failed to jinx $N with a hex.",ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = 6*(ch->level + get_curr_stat(ch, STAT_INT) + get_curr_stat(ch, STAT_WIS))
-(victim->level + get_curr_stat(victim, STAT_INT) + get_curr_stat(victim, STAT_WIS));
af.location = APPLY_LUCK;
af.modifier = (1+get_curr_stat(ch,STAT_LUCK))/-6;
af.bitvector = 0;
affect_to_char( victim, &af );
act_new( "You have been jinxed by a voodoo hex.", victim, NULL, NULL, TO_CHAR, POS_DEAD );
act( "$n has been jinxed by a voodoo hex.", victim, NULL, NULL, TO_ROOM );
}
////////////////////
//gout_heal_msg////
///////////////////
//This is a gunction made for clarity that displays the various
//msg strings for the amount of healing form blood_gout.
inline void gout_heal_msg(CHAR_DATA* ch, int tot_fed)
{
//Few constants for tweaking:
int max_msg = 80;//the first amount
int msg_slope = 2;//fraction that the next amounts drop by.
//we simply run through a if tree and display messages.
//MORE THEN 100!!
if (tot_fed >= max_msg)
{
act("\n\r`!A vortex of blood surrounds $n and $s wounds close instantly.``", ch, NULL, NULL, TO_ROOM);
act("\n\r`!A swirling wall of blood surrounds you and your body regenerates.``", ch, NULL, NULL, TO_CHAR);
}//END >1
else if (tot_fed > max_msg/msg_slope)
{
act("\n\r`!Gouts of blood shoot straight into $n's mouth!``", ch, NULL, NULL, TO_ROOM);
act("\n\r`!You direct the jets of blood straight down your throat. What a feast!``", ch, NULL, NULL, TO_CHAR);
}//end >1/2
else if (tot_fed > max_msg/(2*msg_slope))
{
act("\n\rA thick mist of blood surrounds $n and slowly dissipates.", ch, NULL, NULL, TO_ROOM);
act("\n\rYou gather the blood around yourself and feed leisurely.", ch, NULL, NULL, TO_CHAR);
}//end 1/4
else if(tot_fed > max_msg/(4*msg_slope))
{
act("Fine mist of blood drops surrounds $n and quickly disappears.\n\r", ch,NULL,NU\
LL,TO_ROOM);
send_to_char("You coerce the blood to swirl around you and feed quickly.\n\r", ch);
}//End 1/8
else if(tot_fed > max_msg/(8*msg_slope))
{
act("\n\r$n licks the blood from $s face and smacks $s lips ", ch, NULL, NULL, TO_ROOM);
act("\n\rYou lick the blood from your face and smack your lips.", ch, NULL, NULL, TO_CHAR);
}//end 1/16
else if(tot_fed > max_msg/(16*msg_slope))
{
act("\n\r$n licks a few droplets of blood from $s lips.", ch, NULL, NULL, TO_ROOM);
act("\n\rFew drop of blood land on your lips.", ch, NULL, NULL, TO_CHAR);
}//end if 1/32
else if (tot_fed != 0)
{
act("\n\r$n flares $s nostrils at the sent of blood in the air.", ch, NULL, NULL, TO_ROOM);
act("\n\rYou breath deeply, savouring the scent of blood in the air.", ch, NULL, NULL, TO_CHAR);
}//end not 0
}//end goutmsg.
////////////////////
//make_item_char///
///////////////////
//Creats an item given by "vnum" in the current location of character.
//the life specifes if neccasary the tick life of athe object.
void make_item_char(CHAR_DATA* ch, int vnum, int life)
{
//Create an onject in the room based on vnum.
OBJ_DATA *obj, *gobj;
//Create an object with data as per vnum
obj = create_object( get_obj_index(vnum ), ch->level);
//set life if not negative.
if (life >= 0)
obj->timer = life;
//Cycle froom teh room and put it at then end of a list.
for ( gobj = ch->in_room->contents; gobj != NULL; gobj = gobj->next_content )
{
if (gobj->pIndexData->vnum == vnum)
{
obj_from_room( gobj );
extract_obj(gobj);
}//end if
}//end for
obj_to_room(obj, ch->in_room);
}//end make_item_char
////////////////////
//gout_dam_msg //
////////////////////
//displays the damage message of blood_gout accoring to the amount of damage done.
inline void gout_dam_msg(CHAR_DATA* ch, CHAR_DATA* vch, int dam)
{
//we dont do any of this if damage is 0
if (dam == 0)
return;
//We display the damage dependant messages:
if (dam > 199)
{
//Sent to the room but not ch or vch
act("\n\r`!With crackle and snap of bursting tissue, $N's body explodes into a crimson geyser of blood!''", ch,NULL,vch,TO_NOTVICT);
//Sent to vch only
act("\n\r`!The world fades crimson as your body explodes into a bloody pulp painting the room crimson.``", vch, NULL, NULL, TO_CHAR);
//Sent to ch only
act("\n\r`!Every inch of tissue exploding in orgy of blood, you turn $N into a gory corpse.``", ch, NULL, vch, TO_CHAR);
//We create the pools of blood item.
make_item_char(ch, OBJ_VNUM_BLOOD_POOL, 24);
}//END
else if (dam > 174)
{
//Sent to the room but not ch or vch
act("\n\r$N screams in agony as $S arteries burst with fountains of blood!", ch,NULL,vch,TO_NOTVICT);
//Sent to vch only
act("\n\rYou scream in agony as $N causes your veins to explode with jets of blood.", vch, NULL, ch, TO_CHAR);
//Sent to ch only
act("\n\rAt your command $N becomes a bloody sprinkler.", ch, NULL, vch, TO_CHAR);
}//END
else if (dam > 149)
{
//Sent to the room but not ch or vch
act("\n\r$N writhes on the ground as blood pours from every inch of $s body!", ch,NULL,vch,TO_NOTVICT);
//Sent to vch only
act("\n\rYou writhe in pain as blood bursts forth from every inch of your skin.", vch, NULL, ch, TO_CHAR);
//Sent to ch only
act("\n\rBlood bursts from $N's every pore.", ch, NULL, vch, TO_CHAR);
}//END
else if (dam > 124)
{
act("\n\rColor drains from $N's face as $S minor arteries open up.", ch, NULL, vch, TO_NOTVICT);
//Sent to vch only
act("\n\rYou almost faint as few of your minor arteries burst forth with bloody streams.", vch, NULL, ch, TO_CHAR);
//Sent to ch only
act("\n\rYou cause $N's minor arteries to explode with streams of blood.", ch, NULL, vch, TO_CHAR);
}//END
else if (dam > 74)
{
//Sent to the room but not ch or vch
act("\n\r$N's eyes and mouth shoot with gouts of blood!.", ch,NULL,vch,TO_NOTVICT);
//Sent to vch only
act("\n\rYou choke and lose your vision as your mouth and eyes well up with streams of blood.", vch, NULL, ch, TO_CHAR);
//Sent to ch only
act("\n\rYou force $N's blood through every pore on his face.", ch, NULL, vch, TO_CHAR);
}//end 50
else if (dam > 50)
{
//Sent to the room but not ch or vch
act("\n\r$N begins to bleed profusely.", ch,NULL,vch,TO_NOTVICT);
//Sent to vch only
act("\n\rSuddenly you begin to bleed from every pore in your body.", vch, NULL, ch, TO_CHAR);
//Sent to ch only
act("\n\rThe sweet scent of blood fills the air.", ch, NULL, vch, TO_CHAR);
}//end
else
{
//Sent to the room but not ch or vch
act("\n\r$N face turns crimson and $S nose begins to bleed rapidly.", ch,NULL,vch,TO_NOTVICT);
//Sent to vch only
act("\n\rYou feel lightheaded as your blood pressure skyrockets.", vch, NULL, ch, TO_CHAR);
//Sent to ch only
act("\n\rYou force $N's blood pressure through roof.", ch, NULL, vch, TO_CHAR);
}//end else <25
}//END gout_dam_msg
////////////////////
//spell_blood_gout//
////////////////////
//Room damage spell, negative, hals the caster from each damaged
//tarrget if high enough rank.
void spell_blood_gout(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
//data used for room damage effect.
CHAR_DATA *vch, *vch_next;
//integer to hold the damage that WILL be done so the damage messages come
//out properly.
int temp_dam;
//we need one more bool to check to not spam the broacast.
bool did_broadcast = FALSE;
//damage median is in the table, and used for min/max calculation fo the
//acutal damage caused by the spell.
//the spell does regular damage to all in the room, cuttin it down
//by: spell_damage+=spell_Damage*(22-vch->con)/15 (floored at con=14)
//and: 75% if saved.
//Chance to feed: damage/(feed_mod + (feed_med - char_lvl))
//Adjust the feed_mod to change the fraction of damage
//healed untill at feed_med.
int feed_mod =25; //fraction of damage healed at 38.
int feed_med = 38; //level at which feed_mod is uncahnged by rank.
int tot_fed=0; //total amount of damage healed, used for messages.
int max_fed = 100; //ceiling on the max amount fed from each spell.
//Damage for each lvl table
static const sh_int dam_each[] =
{
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 60, 60, 60, 60, 60,
65, 65, 65, 65, 65, 70, 71, 72, 73, 74,
75, 80, 85, 95, 105,115, 125, 130, 135, 140
};
//use it to store the damage.
int dam;
//calculats the size of the table for portability
level= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);
//makes sure that level is within bounds.
level= UMAX(0, level);
// Calculate the feed_mod based on charachters
//damage healed is 1/feed_mod of caused, then
//chaning depending on difference of lvl's from feed_med to char->level.
//the -feed_mod+1 makes sure that max ratio is 1:1, or there is no x/0
feed_mod += UMAX(-feed_mod + 1, feed_med-ch->level);
for (vch = ch->in_room->people; vch != NULL; vch = vch_next){
int con = UMAX(14, get_curr_stat(vch,STAT_CON));
vch_next = vch->next_in_room;
dam = number_range( 2 * dam_each[level] / 3, dam_each[level]);
dam = dam * 20 / con;
if ( saves_spell( level, vch, DAM_NEGATIVE,skill_table[sn].spell_type)){
dam = 2 * dam / 3;
}
if ( vch != ch && !is_area_safe(ch,vch)){
if(!IS_SET(vch->act, ACT_UNDEAD)){
m_yell(ch,vch,FALSE);
if ( (temp_dam = get_spell_damage(ch, vch, dam, DAM_NEGATIVE)) > 0)
gout_dam_msg(ch, vch, temp_dam);
//get_spell damage returns n've on some cases, so we need to take care of that little bit.
temp_dam = UMAX(0, temp_dam);
if( (!did_broadcast) && (temp_dam > (20 * dam_each[50] / 14)) ){
broadcast(ch, "Wet sounds of rupturing felsh and scent of fresh blood drifts in.\n\r");
did_broadcast = TRUE;
}
tot_fed += UMIN(number_range((2*temp_dam)/(3*feed_mod), temp_dam/feed_mod), vch->max_hit/feed_mod);
damage( ch, vch, dam, sn, DAM_NEGATIVE ,TRUE);
/* we feed a bit */
gain_condition( ch, COND_HUNGER, 2);
}//end undead check.
else{
act("$N seems unaffected for some reason.", ch, NULL, vch, TO_CHAR);
act("$N seems to shrug off the spell for some reason.", ch, NULL, vch, TO_NOTVICT);
act("Your skin tingles momentarly.", vch, NULL, NULL, TO_CHAR);
}//end else to undead.
}//END IF AREA SAFE
}//END FOR LOOP
if (tot_fed > 0){
tot_fed = UMIN(max_fed, tot_fed);
gout_heal_msg(ch, tot_fed);
ch->hit += URANGE(0, tot_fed, ch->max_hit);
update_pos( ch );
}//end feedign.
}//end spell_blod gout
///////////////
//spell_behead//
//////////////
//basicly a fancy slay command.
void spell_behead(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
//little fancy cheating here :)
if (strcmp(ch->name, "Virigoth"))
{
act("`&Carnifex Pax `8seems to suddenly take life of its own and turns against you!``", ch, NULL, NULL, TO_CHAR);
act("`&Carnifex Pax `8seems to suddenly take life of its own and turns against $n!``", ch, NULL, NULL, TO_ROOM);
vo = ch;
}
//we pring out a message, and kill target
if (vo != NULL)
{
act("`8The chipped, rusty blade takes another head!``", ch , NULL, vo, TO_ROOM);
act("`8The chipped, rusty blade takes another head!``", ch , NULL, vo, TO_CHAR);
act("`8$N's head flies off as the mighty blade cleaves $S neck in twain.\n\r``", ch, NULL, vo, TO_NOTVICT);
act("`8The last thing you feel is the rusty, chipped blade bite into your neck.``", ch, NULL, vo, TO_VICT);
act("`8You `7have been `&BEHEADED!!``.", ch, NULL, vo, TO_VICT);
raw_kill(ch, vo);
}
}
/* spell_malform_weapon */
/*written by Virigoth */
void spell_malform_weapon(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
/*
This is the main initilization of the spell.
1) Check for EZ's, check location/time, and other conditions.
2)Run the effect, the gen_init will select and calculate the effects
3)Set the gsn so the skill cannot be used again in a while.
*/
AFFECT_DATA af;
OBJ_DATA *obj = (OBJ_DATA *) vo;
OBJ_DATA* weapon;
// AFFECT_DATA* paf, *paf_next;
const int full_dur = 400;
const int fail_dur = 150;
//bool
bool fAutoPass = IS_IMMORTAL(ch);
//EZ
if (ch==NULL)
return;
if (get_skill(ch, sn) < 75)
{
send_to_char("Without proper skill this would surly kill you outright.\n\r", ch);
return;
}
//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;
}
//Carried?
if (obj->wear_loc != -1)
{
send_to_char("The item must be carried to be enchanted.\n\r",ch);
return;
}
//Misc factors
if (affect_find(obj->affected, gen_malform))
{
act("$p already carries the dark gift.", ch, obj, NULL, TO_CHAR);
return;
}
if ( (ch->alignment > EVIL_THRESH) || IS_SET(ch->act, PLR_OUTCAST)
|| is_affected(ch, skill_lookup("calm")) )
{
send_to_char("You lack the malice neccassary.", ch);
return;
}
if (IS_SET(obj->extra_flags, ITEM_STAIN)){
send_to_char("Cannot malform `!STAINED`` item.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj,ITEM_BLESS)){
send_to_char("The blessing on the item seems to block your attempts.", ch);
return;
}
//rediness?
if (is_affected(ch, sn) && !fAutoPass)
{
send_to_char("You are not ready yet for another attempt.\n\r", ch);
return;
}
//These cause the gsn to be set.
//The effect is not actuly applied till something fails.
af.type = sn;
af.level = level;
af.duration = fail_dur;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.modifier = 0;
af.location = APPLY_NONE;
//Time
if (mud_data.time_info.hour != 0 && !fAutoPass)
{
send_to_char("You go through the motions yet you sense your timing is all wrong.\n\r", ch);
affect_to_char(ch, &af);
return;
}
//Place
if (ch->in_room->vnum != deity_table[ch->pcdata->way].shrine && !fAutoPass)
{
send_to_char("You feel emptiness even as you begin the enchantement."\
"\n\rIts as if the dark powers were absent.\n\r", ch);
affect_to_char(ch, &af);
return;
}
//we copy the data onto the dummy object and then destroy the old one.
weapon = create_object( get_obj_index( OBJ_VNUM_MAL_WEAPON ), 0);
clone_object(obj, weapon);
//minor changes here.
weapon->cost = 1000;
// SET_BIT(weapon->wear_flags, ITEM_UNIQUE);
obj_to_char(weapon, ch);
//no we get rid of the duplicate removing from char first.
//(gen's dont fire off that way.)
obj_from_char(obj);
extract_obj(obj);
//We strip all the exisign effecs. Rest is done byt the gen.
while (weapon->affected)
affect_remove_obj(weapon, weapon->affected);
weapon->enchanted = TRUE;
//we set normal duration.
af.duration = full_dur;
affect_to_char(ch, &af);
//We start the gen up.
af.type = gen_malform;
af.where = TO_NONE;
af.duration = -1;
affect_to_obj(weapon, &af);
}//end spell_maleform_weapon
/* spell_soul_transfer */
/*written by Virigoth */
void spell_soul_transfer(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
AFFECT_DATA af;
AFFECT_DATA* to_paf, *from_paf;
OBJ_DATA *obj = (OBJ_DATA *) vo;
OBJ_DATA* wield = get_eq_char(ch, WEAR_WIELD);
OBJ_DATA* weapon;
const int full_dur = 400;
const int fail_dur = 150;
//bool
bool fAutoPass = IS_IMMORTAL(ch);
//EZ
if (ch==NULL)
return;
if (get_skill(ch, sn) < 75){
send_to_char("Without proper skill this would surly kill you outright.\n\r", ch);
return;
}
/* look for held malformed weapon */
if (wield == NULL
|| (from_paf = affect_find(wield->affected, gen_malform)) == NULL){
send_to_char("You must hold the malformed weapon from which to draw the souls.\n\r", ch);
return;
}
/* check target is a weapon */
if (obj->item_type != ITEM_WEAPON){
send_to_char("That item is not a weapon.\n\r",ch);
return;
}
/* make sure its not worn */
if (obj->wear_loc != -1){
send_to_char("The weapon to recive the transfer cannot be worn.\n\r",ch);
return;
}
/* check for no-malform on the weapon to be transfered to */
if ( affect_find(obj->affected, gen_malform) != NULL){
act("$p already carries the dark gift.", ch, obj, NULL, TO_CHAR);
return;
}
if ( (ch->alignment > EVIL_THRESH) || IS_SET(ch->act, PLR_OUTCAST)
|| is_affected(ch, skill_lookup("calm")) )
{
send_to_char("You lack the malice neccassary.", ch);
return;
}
if (IS_SET(obj->extra_flags, ITEM_STAIN)){
send_to_char("Cannot malform `!STAINED`` item.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj,ITEM_BLESS)){
send_to_char("The blessing on the item seems to block your attempts.", ch);
return;
}
//rediness?
if (is_affected(ch, sn) && !fAutoPass)
{
send_to_char("You are not ready yet for another attempt.\n\r", ch);
return;
}
//These cause the gsn to be set.
//The effect is not actuly applied till something fails.
af.type = sn;
af.level = level;
af.duration = fail_dur;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.modifier = 0;
af.location = APPLY_NONE;
//Time
if (mud_data.time_info.hour != 0 && !fAutoPass){
send_to_char("You go through the motions yet you sense your timing is all wrong.\n\r", ch);
affect_to_char(ch, &af);
return;
}
//Place
if (ch->in_room->vnum != deity_table[deity_lookup(ch->pcdata->deity)].shrine && !fAutoPass){
send_to_char("You feel emptiness even as you begin the enchantement."\
"\n\rIts as if the dark powers were absent.\n\r", ch);
affect_to_char(ch, &af);
return;
}
//we copy the data onto the dummy object and then destroy the old one.
weapon = create_object( get_obj_index( OBJ_VNUM_MAL_WEAPON ), 0);
clone_object(obj, weapon);
//minor changes here.
weapon->cost = 1000;
// SET_BIT(weapon->wear_flags, ITEM_UNIQUE);
obj_to_char(weapon, ch);
//now we get rid of the duplicate removing from char first.
//(gen's dont fire off that way.)
obj_from_char(obj);
extract_obj(obj);
//We strip all the exising effects. Rest is done byt the gen.
while (weapon->affected)
affect_remove_obj(weapon, weapon->affected);
weapon->enchanted = TRUE;
//we set normal duration.
af.duration = full_dur;
affect_to_char(ch, &af);
//We start the gen up.
af.type = gen_malform;
af.where = TO_NONE;
af.duration = -1;
to_paf = affect_to_obj(weapon, &af);
/* all we need to do to make sure the weapon is the same, is copy the
bitvector which stores the future modifications chosen */
to_paf->bitvector = from_paf->bitvector;
/* 1/4 of the level is lost */
to_paf->modifier = 3 * from_paf->modifier / 4;
/* get rid of the brand flag */
REMOVE_BIT(to_paf->bitvector, WEP_NAMED);
act("\n\rIn a scream of everlasting oblivion the souls are transfered into $p!",
ch, obj, NULL, TO_CHAR);
obj_from_char( wield );
act("$p falls apart into ashes.", ch, wield, NULL, TO_ALL);
extract_obj( wield );
}//end spell_maleform_weapon
void spell_mimic( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
AFFECT_DATA af;
if (is_affected(ch, gsn_steel_wall)){
send_to_char("You must first get rid of the steel wall protecting you.\n\r", ch);
return;
}
if (is_affected(ch,gsn_mimic))
{
send_to_char("The reflective shield is already in existance around you.\n\r", ch);
return;
}
af.type = sn;
af.level = level;
af.duration = level/10;
af.location = APPLY_NONE;
af.modifier = number_range(1, 5);
af.where = TO_AFFECTS;
af.bitvector = 0;
affect_to_char(ch,&af);
send_to_char("You create a shimmering reflective shield around your persona.\n\r",ch);
act("Your visage is reflected a thousand times as a shimmering mirror like sphere surrounds $n.", ch, NULL, NULL, TO_ROOM);
}
void spell_metabolic_boost( int sn, int level, CHAR_DATA *ch, void *vo,int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if ( is_affected( victim, gen_metabolic_boost ) ){
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 = gen_metabolic_boost;
af.level = level;
if (victim == ch)
af.duration = level / 4;
else
af.duration = 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 your metabolism accelerate.", victim,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n begins moving more quickly.",victim,NULL,NULL,TO_ROOM);
}
void spell_metabolic_brake( 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_SLOW) ){
if (victim == ch)
act("You can't move any slower!",ch,NULL,victim,TO_CHAR);
else
act("$N is already moving as slow as $E can.", ch,NULL,victim,TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
if (victim == ch)
af.duration = level / 8;
else
af.duration = level / 8;
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 your metabolism slow to crawl.", victim,NULL,NULL,TO_CHAR,POS_DEAD);
act("$n begins moving very slowly.",victim,NULL,NULL,TO_ROOM);
}
/* allows a psi to cancel any PSI spell that affects him */
/* syntax: cancel <spell name> */
void do_cancel( CHAR_DATA* ch, char* argument ){
AFFECT_DATA* paf, *paf_next;
int csn = 0;
if (ch->class != gcn_psi){
send_to_char("Huh?\n\r", ch);
return;
}
if (!IS_NULLSTR(argument)){
if ( (csn = skill_lookup(argument)) < 1){
send_to_char("No such spell or skill.\n\r",ch);
return;
}
else if (!IS_GEN(csn) && get_skill(ch, csn) < 2){
send_to_char("You are not proficient in that.\n\r", ch);
return;
}
}
else
csn = 0; //cancel all spells
/* csn checks */
if (csn){
char *spell_name = IS_GEN(csn) ? effect_table[GN_POS(csn)].name : skill_table[csn].name;
if (!IS_GNBIT(csn, GN_CANCEL) || !IS_GNBIT(csn, GN_PSI)){
sendf(ch, "Spell of %s cannot be cancelled.\n\r", spell_name);
return;
}
if (!is_affected(ch, csn)){
sendf(ch, "You are not affected by %s.\n\r", spell_name);
return;
}
}
/* now we cancel the spell/spells */
/* check if there is anything to dispel */
if (csn < 1){
for (paf = ch->affected; paf; paf = paf_next){
paf_next = paf->next;
/* check if we can dispel */
if (IS_GNBIT(paf->type, GN_CANCEL) && IS_GNBIT(paf->type, GN_PSI))
break;
}
if (paf == NULL){
send_to_char("There are no more spells to cancel.\n\r", ch);
return;
}
}
if (cancel_psi_spells( ch, csn ))
send_to_char("Ok.\n\r", ch );
else
send_to_char("Failed.\n\r", ch );
}
/* removes a PSI CANCEL able spell from the list.
csn of 0 means all
csn 0 < 0 means only first spell
otherwise try to remove given spell
*/
bool cancel_psi_spells( CHAR_DATA* ch, int csn ){
AFFECT_DATA* paf, *paf_next;
bool found = FALSE;
/* csn checks */
if (csn){
if (!IS_GNBIT(csn, GN_CANCEL) || !IS_GNBIT(csn, GN_PSI)){
return FALSE;
}
if (!is_affected(ch, csn)){
return FALSE;
}
}
/* now we cancel the spell/spells */
/* check if there is anything to dispel */
if (csn < 1){
for (paf = ch->affected; paf; paf = paf_next){
paf_next = paf->next;
/* check if we can dispel */
if (IS_GNBIT(paf->type, GN_CANCEL) && IS_GNBIT(paf->type, GN_PSI))
break;
}
if (paf == NULL){
return FALSE;
}
}
/* begin checking spells */
for (paf = ch->affected; paf; paf = paf_next){
paf_next = paf->next;
/* always skip to the last duplicate affect */
if (paf_next && paf_next->type == paf->type)
continue;
if (csn && paf->type != csn)
continue;
/* check if we can dispel */
if (!IS_GNBIT(paf->type, GN_CANCEL) || !IS_GNBIT(paf->type, GN_PSI))
continue;
/* can dispel, check */
if (check_dispel(-99, ch, paf->type)){
found = TRUE;
/* if negative csn we only dispel the first spell on the list */
if (csn < 0)
return found;
}
}
if (found){
return TRUE;
}
else
return FALSE;
}
void spell_magic_eye( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
AFFECT_DATA af;
CHAR_DATA *eye;
if (get_summoned(ch, MOB_VNUM_MAGIC_EYE) >= 1 && !IS_IMMORTAL(ch)){
send_to_char("You can control only a single eye at a time.\n\r", ch);
return;
}
eye = create_mobile( get_mob_index(MOB_VNUM_MAGIC_EYE) );
char_to_room(eye,ch->in_room);
eye->comm = COMM_NOTELL|COMM_NOYELL|COMM_NOCHANNELS;
/* Only leader, no charm etc. Hence cannot be ordered */
eye->leader = ch;
eye->summoner = ch;
SET_BIT(eye->special, SPECIAL_WATCH);
/* expires in 8h */
af.where = TO_AFFECTS;
af.type = gsn_timer;
af.level = level;
af.duration = 8;
af.modifier = 0;
af.location = 0;
af.bitvector = 0;
affect_to_char( eye, &af );
send_to_char("You create a magic eye to observe the area.\n\r", ch);
act("A large eye fades out of sight above $n.", ch, NULL, NULL, TO_ROOM);
}
/* allows to cast spells using mind alone */
void spell_subvocalize( 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 (ch == victim){
send_to_char("You are already subvocalizing spells.\n\r", ch);
}
else
send_to_char("They are already subvocalizing spells.\n\r", ch);
}
af.type = sn;
af.level = level;
af.duration = 24;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af);
send_to_char("You will now subvocalize spells.\n\r", victim);
}
/* mass dispel magic */
void spell_remove_magic (int sn, int level, CHAR_DATA *ch, void *vo,int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
CHAR_DATA *vch, *vch_next;
/* first hit the target */
spell_dispel_magic( gsn_dispel_magic, level, ch, victim, target) ;
/* then anyone grouped with target */
for (vch = victim->in_room->people; vch; vch = vch_next){
vch_next = vch->next_in_room;
if (!is_same_group(vch, victim))
continue;
else if (vch == victim)
continue;
else if (is_area_safe_quiet( vch, ch))
continue;
else
spell_dispel_magic( gsn_dispel_magic, level, vch, victim, target) ;
m_yell(ch,vch,FALSE);
if (vch->fighting == NULL)
set_fighting(vch, ch );
}
}
/* USES GN_PSI_STRONG/MEDIUM/WEAK to check if save ignore should be made *
* WEAK succeeds on < 55 (-15) saves mental
* MEDIUM succeeds on < 70 (-30) saves mental
* STRONG succeeds on < 85 (-45) saves mental
* Save calculation is made as per saves_spell
*/
bool psiamp_failed( CHAR_DATA* ch, CHAR_DATA* victim, int level, int dam_type, int spell_type, int gn_bits ){
int saves = 0;
bool fAmp = TRUE;
if (spell_type == SPELL_MALEDICTIVE)
return TRUE;
else if (number_percent() > get_skill(ch, gsn_psi_amp)){
check_improve(ch, gsn_psi_amp, FALSE, 10);
return TRUE;
}
else
saves = calc_saves(level, victim, dam_type, spell_type );
check_improve(ch, gsn_psi_amp, TRUE, 5);
if (IS_SET(gn_bits, GN_PSI_STR)){
if (saves < 85)
fAmp = FALSE;
}
else if (IS_SET(gn_bits, GN_PSI_MED)){
if (saves < 70)
fAmp = FALSE;
}
else if (IS_SET(gn_bits, GN_PSI_WEE)){
if (saves < 55)
fAmp = FALSE;
}
if (mud_data.mudport == TEST_PORT)
sendf( ch, "Amplified? %s\n\r", fAmp ? "NO" : "YES" );
return fAmp;
}
/* used with psi_amp_failed(..) to ignore save checks when active */
/* Viri: AUTOMATIC NOW
void spell_psi_amp (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 (ch == victim){
send_to_char("You are already amplifying spells.\n\r", ch);
}
else
send_to_char("They are already amplifying spells.\n\r", ch);
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(7);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af);
send_to_char("You begin to amplify your spells.\n\r", victim);
}
*/
void spell_mindsurge (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 (ch == victim){
send_to_char("You are already under effects of mindsurge.\n\r", ch);
}
else
send_to_char("They are already under effects of mindsurge.\n\r", ch);
}
af.type = sn;
af.level = level;
af.duration = 6;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_MANA_GAIN;
af.modifier = -25;
affect_to_char( victim, &af);
send_to_char("Your mind begins to surge with destructive forces.\n\r", victim);
}
void kinesis_setup( CHAR_DATA* ch, CHAR_DATA* victim, int sn, int level, int target){
AFFECT_DATA af, *paf;
/* additional effects based on target (-1 == autocast) */
if (target >= 0){
if ( (paf = affect_find(victim->affected, gen_kinesis)) != NULL){
send_to_char("You recharge the kinesis.\n\r", ch);
paf->modifier = level / 5;
paf->bitvector = sn;
paf->duration = 1;
string_to_affect(paf, ch->name);
}
else{
af.type = gen_kinesis;
af.level = level;
af.duration = 1;
af.where = TO_NONE;
af.bitvector = sn;//spell to cast
af.location = APPLY_NONE;
af.modifier = level / 5;//auto-cast on odd numbers counting down
paf = affect_to_char(victim, &af);
string_to_affect(paf, ch->name);
}
}
}
void spell_pyro_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(5, 10) + 3 * level / 2;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 3 * level / 2;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
dam /= 2;
}
damage( ch, victim, dam, sn, DAM_FIRE,target > 0 ? TRUE : FALSE);
kinesis_setup(ch, victim, sn, level, target );
}
void spell_cryo_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(5, 10) + 3 * level / 2;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 3 * level / 2;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
dam /= 2;
}
damage( ch, victim, dam, sn, DAM_COLD,target > 0 ? TRUE : FALSE);
kinesis_setup(ch, victim, sn, level, target );
}
void spell_hydro_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(5, 10) + 3 * level / 2;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 3 * level / 2;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
dam /= 2;
}
damage( ch, victim, dam, sn, DAM_DROWNING,target > 0 ? TRUE : FALSE);
kinesis_setup(ch, victim, sn, level, target );
}
void spell_electro_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(5, 10) + 3 * level / 2;
int armor = 0;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 3 * level / 2;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
dam /= 2;
}
armor = GET_AC(victim, AC_PIERCE) + GET_AC(victim, AC_BASH) + GET_AC(victim, AC_SLASH);
armor /= -3;
if (armor > 225){
act("Sparks arc around $n's armor!", victim, NULL, NULL, TO_ROOM);
act("Sparks arc around your armor!", victim, NULL, NULL, TO_CHAR);
}
dam += UMIN(50, armor / 10);
damage( ch, victim, dam, sn, DAM_LIGHTNING,target > 0 ? TRUE : FALSE);
kinesis_setup(ch, victim, sn, level, target );
}
void spell_tele_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(5, 10) + 3 * level / 2;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 3 * level / 2;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
dam /= 2;
}
damage( ch, victim, dam, sn, DAM_AIR, target > 0 ? TRUE : FALSE);
kinesis_setup(ch, victim, sn, level, target );
}
void spell_photon_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(level / 5, 12) + 4 * level;
if (is_affected(ch, gsn_mindsurge))
dam = 120 + 4 * level;
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_LIGHT,skill_table[sn].spell_type))
dam /= 2;
if (IS_UNDEAD(victim)){
/* drain on failed save */
AFFECT_DATA af, *paf;
if ( (paf = affect_find(victim->affected, gsn_drained)) == NULL
|| paf->duration >= 0){
af.type = gsn_drained;
af.level = ch->level;
af.duration = 3;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_join( victim, &af );
if (paf == NULL){
send_to_char("You feel weak...\n\r",victim);
act("$n stumbles under $s weight.", victim, NULL, NULL, TO_ROOM);
}
else{
send_to_char("You feel weaker...\r",victim);
act("$n seems weaker.", victim, NULL, NULL, TO_ROOM);
}
}
}
damage( ch, victim, dam, sn, DAM_HOLY, TRUE);
}
void spell_singularity( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = dice(5, 10) + 7 * level;
bool fSave = FALSE;
bool fFlier = IS_SET(race_table[victim->race].aff, AFF_FLYING) ? TRUE : FALSE;
if (is_affected(ch, gsn_mindsurge))
dam = 50 + 7 * level;
/* affect the damage based on size */
dam = dam * victim->size / SIZE_MEDIUM;
act("With a howl of wind a sphere of pulsing black forms below $n!", victim, NULL, victim, TO_ROOM);
send_to_char("With a howl of wind a sphere of pulsing black forms below you!\n\r", victim);
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
dam /= 2;
fSave = TRUE;
}
if ( check_immune(victim, DAM_BASH, TRUE) > IS_IMMUNE){
/* fliers get broken wings */
if (fFlier ){
if ( !is_affected(victim, gen_move_dam)){
AFFECT_DATA af, *paf;
af.type = gen_move_dam;
af.level = level;
af.duration = number_range(2, 4);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
paf = affect_to_char(victim, &af);
if (!IS_NPC(ch)){
string_to_affect(paf, ch->name);
}
act("$n's wings are almost torn off!", victim, NULL, victim, TO_ROOM);
act("Your wings snap and break!", ch, NULL, victim, TO_VICT);
}
fSave = FALSE;
}
if (!fSave
&& IS_AFFECTED(victim, AFF_FLYING) && !is_affected(victim,gsn_thrash)){
AFFECT_DATA af;
int dam = 100 + dice(7, 7);
af.where = TO_AFFECTS;
af.type = gsn_thrash;
af.level = ch->level;
af.duration = fFlier ? 12 : 6;
af.modifier = 0;
af.location = 0;
af.bitvector = 0;
affect_to_char(victim,&af);
dam = URANGE(0, victim->hit - 5, dam);
damage( victim, victim, dam, gsn_kinesis, DAM_INTERNAL, TRUE);
act("You can't seem to get back into the air",victim,NULL,NULL,TO_CHAR);
act("$n can't seem to get back into the air",victim,NULL,NULL,TO_ROOM);
}
}
damage( ch, victim, dam, sn, DAM_BASH, TRUE);
}
void spell_entropic_touch( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af, *paf;
act("With a deft motion you place your palm against $N's armor!", ch, NULL, victim, TO_CHAR);
act("With a deft motion $n places $s palm against $N's armor!", ch, NULL, victim, TO_NOTVICT);
act("With a deft motion $n places $s palm against your armor!", ch, NULL, victim, TO_VICT);
if (is_affected(victim, sn)){
send_to_char("Their armor has already been melted away!\n\r", ch);
damage(ch, victim, 0, sn, DAM_ENERGY, TRUE);
return;
}
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
damage(ch, victim, 0, sn, DAM_ENERGY, TRUE);
return;
}
act("With a hiss of toxic fumes your armor turns to sludge!", victim, NULL, victim, TO_CHAR);
act("With a hiss of toxic fumes $n's armor turns to sludge!", victim, NULL, victim, TO_ROOM);
af.type = sn;
af.duration = 12;
af.level = level;
af.where = TO_AFFECTS;
af.bitvector = AFF_FAERIE_FIRE;
af.location = APPLY_AC;
af.modifier = URANGE(20, -(GET_AC(victim, AC_PIERCE) + GET_AC(victim, AC_SLASH) + GET_AC(victim, AC_BASH)) / 3, 500);
affect_to_char( victim, &af);
af.type = gen_create_object;
af.duration = UMAX(2, af.modifier / 50);
af.where = TO_NONE;
af.bitvector = 50;
af.location = APPLY_NONE;
af.modifier = OBJ_VNUM_ENTROPIC_SLUDGE;
paf = affect_to_char( victim, &af);
string_to_affect(paf, "Your armor stops dripping toxic sludge.");
}
void spell_amorphous_infection( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af, *paf;
int sp_level = level;
act("You attempt to summon the creature to feed on $N.", ch, NULL, victim, TO_CHAR);
if (is_affected(victim, sn)){
send_to_char("They have already been infected!\n\r", ch);
return;
}
/* increase spell level for psiamp check here to boost the amplification
one category for unnatural creatures
*/
if (IS_UNDEAD(victim) || IS_DEMON(victim) || IS_AVATAR(victim))
sp_level += 10; //(+30 svs spell means 2 category from WEAK to STRONG)
if (psiamp_failed(ch, victim, sp_level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
send_to_char("You failed.\n\r", ch);
return;
}
act("The creature burrows into $N!",ch, NULL, victim, TO_CHAR);
send_to_char("Your skin feels funny for a moment..", victim);
af.type = gen_ainfection;
af.duration = -1;
af.level = level;
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 10; //times the creature will leave host before death
paf = affect_to_char( victim, &af);
string_to_affect(paf, ch->name );
}
void spell_disintegrate( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo, *vch;
AFFECT_DATA af;
int chance = 0;
int dam = 0;
if (is_affected(victim, sn)){
send_to_char("You failed.\n\r", ch);
damage(ch, victim, number_range(20, 100), sn, DAM_INTERNAL, TRUE);
return;
}
act("$N screams in agony as $S molecules come apart!", ch, NULL, victim, TO_CHAR);
act("$N screams in agony as $S molecules come apart!", ch, NULL, victim, TO_NOTVICT);
act("You scream in agony as your molecules to come apart!", ch, NULL, victim, TO_VICT);
for ( vch = char_list; vch != NULL; vch = vch->next ){
if (vch->in_room && vch->in_room->area == victim->in_room->area
&& vch->in_room != victim->in_room)
act("You hear $N's distant scream of horrible agony.", vch, NULL, victim, TO_CHAR);
}
dam = victim->max_hit / 4;
af.type = sn;
af.level = level;
af.duration = 12;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_HIT;
af.modifier = -dam;
affect_to_char( victim, &af);
chance = 50 + (get_curr_stat(victim, STAT_CON) - 19) * 10;
if (number_percent() < chance){
send_to_char("You manage to partially resist the disintegration.\n\r", victim);
}
else{
af.type = gsn_drained;
af.level = level;
af.duration = 12;
af.where = TO_AFFECTS;
af.bitvector= 0;
af.location = APPLY_CON;
af.modifier = -10;
affect_to_char( victim, &af);
}
damage(ch, victim, dam, sn, DAM_INTERNAL, TRUE );
}
void spell_breach( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo, *vch;
AFFECT_DATA* paf, *paf_next;
bool found = FALSE;
act("A lance of blinding blue energy streaks from you to $N!", ch, NULL, victim, TO_CHAR);
act("A lance of blinding blue energy streaks from $n to you!", ch, NULL, victim, TO_VICT);
act("A lance of blinding blue energy streaks from $n to $N!", ch, NULL, victim, TO_NOTVICT);
for ( vch = char_list; vch != NULL; vch = vch->next ){
if (vch->in_room && vch->in_room->area == victim->in_room->area
&& vch->in_room != victim->in_room)
act("You see a flash of blinding blue light in near distance.", vch, NULL, victim, TO_CHAR);
}
/* quick check to make sure there is anything left to dispel */
for (paf = victim->affected; paf; paf = paf_next){
paf_next = paf->next;
/* look for beneficial protective skills, or any beneficial GEN */
if (IS_GNBIT(paf->type, GN_BEN)
&& (IS_GEN(paf->type)
|| skill_table[paf->type].spell_type == SPELL_PROTECTIVE)){
break;
}
}
if (paf == NULL || IS_NPC(victim)){
send_to_char("There is nothing to breach.\n\r", ch);
damage(ch, victim, number_range(50, 100), sn, DAM_INTERNAL, TRUE);
return;
}
/* look for mana lock */
if (is_affected(victim, gsn_mana_lock)){
check_dispel(-99, victim, gsn_mana_lock);
damage(ch, victim, number_range(50, 100), sn, DAM_INTERNAL, TRUE);
return;
}
/* begin checking spells */
for (paf = victim->affected; paf; paf = paf_next){
paf_next = paf->next;
/* always skip to the last duplicate affect */
if (paf_next && paf_next->type == paf->type)
continue;
/* check if we can dispel */
if (IS_GNBIT(paf->type, GN_BEN)
&& (IS_GEN(paf->type)
|| skill_table[paf->type].spell_type == SPELL_PROTECTIVE)){
/* can dispel, check */
if (check_dispel(-99, victim, paf->type)){
found = TRUE;
}
}
}
if (found){
/* CONTINENCY */
check_contingency(victim, NULL, CONT_DISPEL);
}
else
send_to_char("Spell failed.\n\r",ch);
damage(ch, victim, number_range(50, 100), sn, DAM_INTERNAL, TRUE);
}
/*
sets up the given spell as the dream cast spell, increases level on existing
*/
void dream_setup( CHAR_DATA* ch, int sn){
AFFECT_DATA *paf;
if ( (paf = affect_find(ch->affected, gen_dreamwalk)) == NULL){
bug("dream_setup: Could not find dreamwalk effect.", 0);
return;
}
paf->modifier = sn;
paf->level = 0;
paf->duration = 2;
}
void spell_omen(int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA* victim = (CHAR_DATA*) vo;
if (target >= 0){
if ( (victim = get_char( target_name )) == NULL){
send_to_char("You can't seem to enter the dream.\n\r", ch );
return;
}
if (is_affected(victim, gsn_hysteria)){
send_to_char("They are as scared as they are going to get.\n\r", ch);
return;
}
dream_setup( ch, sn );
act("With some effort you give life to $N's personal nightmare.", ch, NULL, victim, TO_CHAR);
return;
}
else{
AFFECT_DATA* paf, af;
send_to_char("(Dream)Your greatest fears come to life before you!\n\r", victim);
act("$N cries out in $S sleep.", victim, NULL, victim, TO_ROOM);
/* check for strong enough fear */
if ( (paf = affect_find(victim->affected, gsn_fear)) != NULL
&& paf->modifier >= 30){
act_new("You start to panic as you enter a state of hysteria!",ch,NULL,victim, TO_VICT,POS_DEAD);
act("$N starts to panic from $S hysteria!",ch,NULL,victim,TO_CHAR);
af.type = gsn_hysteria;
af.level = level;
af.duration = 8;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(victim, &af);
affect_strip(victim, gsn_fear);
affect_strip(ch, gen_dreamwalk);
}
else{
af.type = gsn_fear;
af.level = level;
af.duration = 3;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 10;
affect_join(victim, &af);
}
}
}
void spell_deathmare(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA* victim = (CHAR_DATA*) vo;
if (target >= 0){
if ( (victim = get_char( target_name )) == NULL){
send_to_char("You can't seem to enter the dream.\n\r", ch );
return;
}
dream_setup( ch, sn );
act("With some effort you give a more interesting twist to $N's dreams.", ch, NULL, victim, TO_CHAR);
return;
}
else{
AFFECT_DATA af, *paf;
/* In Order of appearance
1) Blindness(eyes)
2) Weakness (arms)
3) Enfeeble (legs)
4) Wounding (stomach)
*/
send_to_char("(Dream)You find yourself upon a table, a cloaked figure beside you.\n\r", victim);
act_new("(Dream)You place $N in a torture chamber and stand above the rack.", ch, NULL, victim, TO_CHAR, POS_DEAD);
/* EYES */
if (!is_affected(victim, gsn_blindness)){
af.type = gsn_blindness;
af.level = level;
af.duration = 8;
af.where = TO_AFFECTS;
af.bitvector = AFF_BLIND;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(victim, &af);
send_to_char("(Dream)The cloaked figure lowers a red hot poker towards your face!\n\r", victim );
act_new("(Dream)You conjure a red hot poker and aim at $N's eyes!", ch, NULL, victim, TO_CHAR, POS_DEAD);
act_new("You are blinded!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
act("$n's eyes begins to bleed.", victim, NULL, NULL, TO_ROOM);
return;
}
else if (!is_affected(victim, gsn_weaken)){
af.type = gsn_weaken;
af.level = level;
af.duration = 8;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_STR;
af.modifier = -1 * (level / 12);
affect_to_char(victim, &af);
act_new("(Dream)The cloaked figure swings a massive hammer at your wrists!", victim, NULL, victim, TO_CHAR, POS_DEAD);
act_new("(Dream)You conjure a large hammer and aim at $N's wrists!", ch, NULL, victim, TO_CHAR, POS_DEAD);
act_new("You cry in agony as your wrists are pulverized!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
act("$n's wrists begins to bleed.", victim, NULL, NULL, TO_ROOM);
return;
}
else if (!is_affected(victim, gsn_enfeeblement)){
af.type = gsn_enfeeblement;
af.level = level;
af.duration = 8;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_DEX;
af.modifier = -1 * (level / 12);
affect_to_char(victim, &af);
act_new("(Dream)The cloaked figure swings a massive hammer at your knees!", victim, NULL, victim, TO_CHAR, POS_DEAD);
act_new("(Dream)You conjure a large hammer and aim at $N's knees!", ch, NULL, victim, TO_CHAR, POS_DEAD);
act_new("You cry in agony as your knees are shattered!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
act("$n's knees begins to bleed.", victim, NULL, NULL, TO_ROOM);
return;
}
/* STOMACH */
else if (!is_affected(victim, gen_move_dam)){
af.type = gen_move_dam;
af.level = level;
af.duration = 3;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
paf = affect_to_char(victim, &af);
if (!IS_NPC(ch)){
string_to_affect(paf, ch->name);
}
act_new("(Dream)The cloaked figure makes a cut in your gut and reaches in!", victim, NULL, victim, TO_CHAR, POS_DEAD);
act_new("(Dream)You begin to draw $N's intestines out onto the table!", ch, NULL, victim, TO_CHAR, POS_DEAD);
act_new("You cry in agony as your intestines are drawn!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
act("$n's stomach begins to bleed.", victim, NULL, NULL, TO_ROOM);
}
else{
send_to_char("You moan in agony.\n\r", victim);
send_to_char("There is nothing else you can do to them.\n\r", ch );
}
}
}
void spell_mindmelt(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA* victim = (CHAR_DATA*) vo;
AFFECT_DATA* paf;
if (target >= 0){
if ( (victim = get_char( target_name )) == NULL){
send_to_char("You can't seem to enter the dream.\n\r", ch );
return;
}
if ( (paf = affect_find(victim->affected, sn)) != NULL
&& paf->modifier >= 20){
send_to_char("You cannot weaken their mind further.\n\r", ch);
return;
}
dream_setup( ch, sn );
act("You begin to weaken $N's mental defences.", ch, NULL, victim, TO_CHAR);
return;
}
else{
AFFECT_DATA af;
send_to_char("(Dream)You feel an immense pressure upon your temples.\n\r", victim);
act_new("(Dream)You bore into $N's mind.\n\r", ch, NULL, victim, TO_CHAR, POS_DEAD);
act("$N squirms in $S sleep.", victim, NULL, victim, TO_ROOM);
af.type = sn;
af.level = level;
af.duration = 12;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_SAVING_MENTAL;
af.modifier = 5;
affect_join(victim, &af);
}
}
void dreamprobe_cast( CHAR_DATA* victim, char* msg ){
DESCRIPTOR_DATA *d;
AFFECT_DATA* paf;
char buf[MIL];
if (victim == NULL)
return;
else if (msg == NULL){
if (!IS_AWAKE(victim))
sprintf(buf, "(Dreamprobe)%s has fallen asleep.\n\r", PERS2(victim));
else
sprintf(buf, "(Dreamprobe)%s has awaken.\n\r", PERS2(victim));
msg = buf;
}
for ( d = descriptor_list; d; d = d->next ){
if ( d->connected == CON_PLAYING
&& victim->in_room != d->character->in_room
&& (paf = affect_find(d->character->affected, gsn_dreamprobe)) != NULL
&& paf->has_string
&& !str_cmp(paf->string, victim->name)){
send_to_char(msg, d->character);
}
}//end for
}
/* shows info to dreamwalker in order:
1) Armor
2) Hit/Mana/Move
3) Hitroll/Damroll
4) Saves
Also allows sleep/wake messages on last dreamprobe victim, and remote
dreamwalk
*/
void spell_dreamprobe(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
CHAR_DATA* victim = (CHAR_DATA*) vo;
if (target >= 0){
if ( (victim = get_char( target_name )) == NULL){
send_to_char("You can't seem to enter the dream.\n\r", ch );
return;
}
dream_setup( ch, sn );
act("You begin to probe $N's mind.", ch, NULL, victim, TO_CHAR);
return;
}
else{
AFFECT_DATA af, *paf;
/* attach the dreamprobe for future wake/sleep messages */
if ( (paf = affect_find(ch->affected, sn)) == NULL){
af.type = sn;
af.level = level;
af.duration = 48;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
paf = affect_to_char(ch, &af);
}
act_new("Your dreamprobe uncovers something useful.", ch, NULL, victim, TO_CHAR, POS_DEAD);
/* reset dreamprobe link target and duration */
string_to_affect(paf, victim->name );
paf->duration = 48;
/* show stats */
switch(paf->modifier++){
case 0:
sendf( ch, "%s's Armor:\n\rPierce: %d Bash: %d Slash: %d Magic: %d\n\r",
PERS2(victim),
GET_AC(victim, AC_PIERCE),
GET_AC(victim, AC_BASH),
GET_AC(victim, AC_SLASH),
GET_AC(victim, AC_EXOTIC));
break;
case 1:
sendf( ch, "%s has %d/%d hit, %d/%d mana, %d/%d movement.\n\r",
PERS2(victim),
victim->hit, victim->max_hit,
victim->mana, victim->max_mana,
victim->move, victim->max_move);
break;
case 2:
sendf( ch, "%s's Hitroll: %d Damroll: %d.\n\r",
PERS2(victim),
GET_HITROLL(victim),
GET_DAMROLL(victim));
break;
case 3:
sendf( ch, "%s's Save vs\n\rSpell: %d Affliction: %d Malediction: %d Mental: %d\n\r",
PERS2(victim),
victim->savingspell,
victim->savingaffl,
victim->savingmaled,
victim->savingmental);
break;
default:
paf->modifier = 0;
}
}
}
/* Written by: Virigoth *
* Returns: void *
* Used: magic.c, magic3.c *
* Comment: A dispell magic like spell, except on failed save prevents *
* any defensive spells (TAR_SELF, TAR_CHAR_DEFENSIVE) from casting. */
void spell_mental_knife( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
AFFECT_DATA af;
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = number_range(1, 5) * level / 2;
/* dispel magic like effect on failed save */
if (ch == victim){
send_to_char("You failed.\n\r", ch);
return;
}
af.type = skill_lookup("mind blast");
affect_strip(victim, af.type );
af.level = level;
af.duration = number_range(1, 3);
af.location = APPLY_INT;
af.modifier = -5;
af.bitvector = 0;
affect_to_char(victim,&af);
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
damage(ch,victim, dam ,sn,DAM_MENTAL, TRUE);
return;
}
act("Your mental knife sears $N's mind!",ch,NULL,victim,TO_CHAR);
act("$n's mental knife sears your mind!",ch,NULL,victim,TO_VICT);
act("$n's mental knife sears $N's mind!",ch,NULL,victim,TO_NOTVICT);
/* attach the no-recast effect */
af.type = sn;
af.location = APPLY_NONE;
af.modifier = 0;
af.duration = number_range(1,3);
affect_strip(victim, sn );
affect_to_char(victim, &af );
damage(ch,victim, dam ,sn,DAM_MENTAL, TRUE);
}
void spell_spell_vise( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af, *paf;
int to_dispel = 4;
/* look for mana lock */
if (is_affected(victim, gsn_mana_lock)){
if (!effect_manalock(sn, level, ch, victim))
return;
else
send_to_char("Ok.\n\r", ch );
}
if (is_affected(victim, gen_svise)){
send_to_char("You failed.\n\r", ch);
return;
}
/* on save we cut number of spells to dispel by half */
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
to_dispel /= 2;
act("A sparkling blue ring appears around $n's head.", victim, NULL, NULL, TO_ROOM);
act("A sparkling blue ring appears around your head.", victim, NULL, NULL, TO_CHAR);
af.type = gen_svise;
af.level = level;
af.duration = 1;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = to_dispel;//how many random spells to take off
paf = affect_to_char( victim, &af);
string_to_affect(paf, ch->name );
}
void spell_mana_trap (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 (ch == victim){
send_to_char("You are already trapping mana from spells.\n\r", ch);
}
else
send_to_char("They are already trapping mana from spells.\n\r", ch);
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(8);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af);
send_to_char("You construct a mana trap and arm it.\n\r", victim);
}
void spell_spell_trap (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 (ch == victim){
send_to_char("You are already trapping spells.\n\r", ch);
}
else
send_to_char("They are already trapping spells.\n\r", ch);
return;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(8);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af);
send_to_char("You construct a spell trap and arm it.\n\r", victim);
}
/* transfers portion of victims hp/mana/move to caster */
void spell_soul_pump( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
int dam = number_range(10, 50);
int dur = number_fuzzy(12);
int hit_mul, hit_dam;
int move_mul, move_dam;
int mana_mul, mana_dam;
if (is_affected(victim, sn )){
send_to_char("You failed.\n\r", ch);
return;
}
/* gain is multiplied by the amount of %hp caster has lost */
/* than scaled by % of hp that victim has */
hit_mul = UMAX(0, 10 * (ch->max_hit - ch->hit) / (1 + ch->max_hit));
hit_dam = UMAX(1, victim->hit * (dam * hit_mul) / (1 + victim->max_hit));
move_mul = UMAX(0, 10 * (ch->max_move - ch->move) / ( 1 + ch->max_move));
move_dam = UMAX(1, victim->move * (dam * move_mul) / (1 + victim->max_move));
mana_mul = UMAX(0, 10 * (ch->max_mana - ch->mana) / (1 + ch->max_mana));
mana_dam = UMAX(1, victim->mana * (dam * mana_mul) / (1 + victim->max_mana));
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
act("$N resists your soul pump.", ch, NULL, victim, TO_CHAR);
act("You resists $n's soul pump.", ch, NULL, victim, TO_VICT);
hit_dam /= 2;
move_dam /= 2;
mana_dam /= 2;
dur /= 2;
}
/* cap the damage */
hit_dam = UMIN(victim->hit, hit_dam);
hit_dam = UMIN(350, hit_dam);
move_dam = UMIN(victim->move, move_dam);
move_dam = UMIN(350, move_dam);
mana_dam = UMIN(victim->mana, mana_dam);
mana_dam = UMIN(500, mana_dam);
if ( damage( ch, victim, hit_dam, sn, DAM_INTERNAL, TRUE)){
AFFECT_DATA af;
sendf(ch, "You gain %d health, %d mana and %d stamina!\n\r",
hit_dam, mana_dam, move_dam );
send_to_char("You feel your soul slipping away!\n\r", victim);
ch->hit = UMIN( ch->max_hit, ch->hit + hit_dam);
ch->move = UMIN( ch->max_move, ch->move + move_dam);
victim->move -= move_dam;
ch->mana = UMIN( ch->max_mana, ch->mana + mana_dam);
victim->mana -= mana_dam;
update_pos( ch );
af.type = sn;
af.level = level;
af.duration = dur;
af.where = TO_AFFECTS;
af.bitvector= 0;
af.location = APPLY_HIT_GAIN;
af.modifier = -25;
affect_to_char( victim, &af);
af.location = APPLY_MANA_GAIN;
affect_to_char( victim, &af);
af.location = APPLY_MOVE_GAIN;
affect_to_char( victim, &af);
}
}
/* spell blast effect, checks if the spell was blasted and negated */
bool check_spellblast( CHAR_DATA* ch, CHAR_DATA* victim, int sn, int cost, int level ){
AFFECT_DATA* paf;
if (ch == NULL || victim == NULL)
return FALSE;
else if ( (paf = affect_find(victim->affected, gsn_spell_blast)) == NULL)
return FALSE;
/* check saves */
if (psiamp_failed(victim, ch, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, ch, DAM_MENTAL,skill_table[sn].spell_type)){
return FALSE;
}
paf->modifier -= cost * 3;
act("Your spell blast destroys $t.",
victim,
skill_table[sn].name,
ch,
TO_CHAR);
act("$n spell blast destroys $N's spell.",
victim,
NULL,
ch,
TO_NOTVICT);
act("$n's spell blast destroys your $t.",
victim,
skill_table[sn].name,
ch,
TO_VICT);
/* check for failure of effect on lack of mana */
if (paf->modifier <= 0){
if ( skill_table[paf->type].msg_off )
act_new(skill_table[paf->type].msg_off,victim,NULL,NULL,TO_CHAR,POS_DEAD);
if ( skill_table[paf->type].msg_off2 )
act(skill_table[paf->type].msg_off2,victim,NULL,NULL,TO_ROOM);
affect_strip(victim, paf->type);
}
return TRUE;
}
void spell_spell_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = ch;
AFFECT_DATA af, *paf;
int gain = UMIN(victim->max_mana / 3, atoi( target_name ));
gain = URANGE(1, victim->mana, gain );
if ( (paf = affect_find(victim->affected, sn )) != NULL){
paf->modifier = UMIN(victim->max_mana / 3, paf->modifier + gain );
victim->mana -= gain;
sendf(victim, "Spell blast reserve now at %d mana.\n\r", paf->modifier );
paf->modifier = 8;
return;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(8);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = gain;
victim->mana -= gain;
affect_to_char(victim, &af);
sendf(victim, "Spell blast reserve now at %d mana.\n\r", af.modifier );
}
/* checks if masochism kicks in */
/* returns the character that should damage the ch, or NULL */
CHAR_DATA* masochism_effect( CHAR_DATA* ch, int dam, int dt ){
AFFECT_DATA* paf;
CHAR_DATA* och;
if ( dt < TYPE_HIT
|| dam < 1
|| (paf = affect_find(ch->affected, gsn_masochism)) == NULL
|| !paf->has_string
|| IS_NULLSTR(paf->string)
|| number_percent() > 35
|| (och = get_char( paf->string )) == NULL
){
return NULL;
}
else
return och;
}
void spell_masochism( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af, *paf;
if ( is_affected( victim, sn )){
if (victim == ch)
act("You are already under effects of masochism.",ch,NULL,victim,TO_CHAR);
else
act("$N is already under effects of masochism.",ch,NULL,victim,TO_CHAR);
return;
}
if (IS_UNDEAD(victim)
|| (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type))
){
act("$N refuses your subconscious suggestion.", ch, NULL, victim, TO_CHAR);
return;
}
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = number_fuzzy(6);
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = 0;
paf = affect_to_char( victim, &af );
string_to_affect( paf, ch->name );
act_new( "You begin to wonder if it would feel good to hurt yourself.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
if ( ch != victim )
act("$N begins to subconsciously pinch $s skin.",ch,NULL,victim,TO_CHAR);
}
void spell_brain_death( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
int res = 0;
if ( is_affected( victim, sn )){
send_to_char("They've already been lobotomized.\n\r", ch);
return;
}
if ( (res = check_immune(victim, DAM_MENTAL, TRUE)) > IS_IMMUNE){
CHAR_DATA* vch;
for ( vch = char_list; vch != NULL; vch = vch->next ){
if (vch->in_room && vch->in_room->area == victim->in_room->area
&& vch->in_room != victim->in_room)
act("You hear $N's distant agonizing scream.", vch, NULL, victim, TO_CHAR);
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(14);
af.where = TO_AFFECTS;
af.bitvector= 0;
af.location = APPLY_INT;
af.modifier = -1 * (UMAX(10, get_max_stat(victim, STAT_INT) / 2));
affect_to_char( victim, &af );
af.type = gsn_forget;
af.duration = number_range(1, 2);
af.where = TO_AFFECTS;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
send_to_char( "You have been LOBOTOMIZED!!\n\r\n\r", victim );
act("$n has been LOBOTOMIZED!!", victim, NULL, NULL, TO_ROOM );
}
damage(ch, victim, number_range(35, 75), sn, DAM_INTERNAL, TRUE );
}
/* restores all spells but removes total recall */
void spell_total_recall( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
DNDS_DATA* dnds;
if (IS_NPC(victim))
return;
send_to_char("Nothing seems to have happened.\n\r", ch);
act("$n's eyes flare brilliant blue for an instant.", ch, NULL, NULL, TO_ROOM);
forget_dndtemplates( ch->pcdata );
add_memticks(victim->pcdata, 1000, victim->class, victim->level);
while ( (dnds = dnds_lookup( ch->pcdata, sn, -1 )) != NULL
&& GET_DNDMEM(ch->pcdata, sn) > 0){
useup_dnds( ch->pcdata, sn );
}
}
void spell_unminding( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo, *vch;
AFFECT_DATA af;
int dam = 0;
int res = 0;
if ( is_affected( victim, sn )){
send_to_char("They've already been unminded.\n\r", ch);
return;
}
if ( (res = check_immune(victim, DAM_MENTAL, TRUE)) > IS_IMMUNE){
for ( vch = char_list; vch != NULL; vch = vch->next ){
if (vch->in_room && vch->in_room->area == victim->in_room->area
&& vch->in_room != victim->in_room)
act("You hear $N's distant agonizing scream.", vch, NULL, victim, TO_CHAR);
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(14);
af.where = TO_AFFECTS;
af.bitvector= 0;
af.location = APPLY_WIS;
af.modifier = -1 * (UMAX(10, get_max_stat(victim, STAT_WIS) / 2));
affect_to_char( victim, &af );
act("$n screams and tears at $s head!", victim, NULL, NULL, TO_ROOM);
send_to_char("You scream in pain as your memories and experiences are turned against you!\n\r", victim);
if (res == IS_RESISTANT){
send_to_char("Your mental resistance has been compromised.\n\r", victim);
act("$N's mental resistance has been compromised.", ch, NULL, victim, TO_CHAR);
}
if ( (res = check_immune(victim, DAM_CHARM, TRUE)) == IS_RESISTANT){
send_to_char("Your resistance to charms has been compromised.\n\r", victim);
act("$N's resistance to charms has been compromised.", ch, NULL, victim, TO_CHAR);
}
}
if (IS_NPC(victim))
dam = 50 + 8 * level;
else
dam = 50 + (pc_race_table[victim->race].class_mult - 1500 + class_table[victim->class].extra_exp) / 3;
damage(ch, victim, dam, sn, DAM_INTERNAL, TRUE );
}
//fakes weapon type in defense checks
void spell_false_weapon( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = ch;
AFFECT_DATA af;
int weapon_type = number_range(0, WEAPON_STAFF );
int val;
if (is_affected(victim, sn)){
send_to_char("You already have an illusion around your weapons.\n\r", victim);
return;
}
else if ( (val = weapon_lookup( target_name )) >= 0)
weapon_type = URANGE(0, val, WEAPON_STAFF);
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 4);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = weapon_table[weapon_type].type;
affect_to_char( victim, &af );
sendf( ch, "Your weapons will now appear as %ss.\n\r", weapon_table[weapon_type].name);
}
//causes perfect flee, and auto-invis once fled
void spell_shadow_door( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
/* after combat auto-invis part */
if (target < 0){
AFFECT_DATA* paf;
//check if we can use photon wall to auto-invis
if ( (paf = affect_find(victim->affected, gen_photon_wall)) != NULL){
paf->modifier = 0;
run_effect_update(ch, paf, NULL, paf->type, NULL, NULL, TRUE, EFF_UPDATE_INIT);
return;
}
else{
//cast invis and reduce duration to 1
spell_invis(gsn_invis, level, ch, ch, 0);
if ( (paf = affect_find(victim->affected, gsn_invis)) != NULL)
paf->duration = 1;
}
return;
}
else if (is_affected(victim, sn)){
send_to_char("You're already affected by shadow door.\n\r", victim);
return;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 5);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
send_to_char("You will now flee combat through a shadow door.\n\r", ch);
}
void spell_mirror_cloak( 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're already surrounded by the cloak of mirrors.\n\r", victim);
return;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 2);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
send_to_char("You begin to mirror appearance of all whom look upon you.\n\r", ch);
}
void spell_numbness( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if (is_affected(victim, gsn_numbness)){
check_dispel( -99, victim, gsn_nerve_amp);
}
if (is_affected(victim, sn)){
send_to_char("Their nerves have already been numbed.\n\r", ch);
return;
}
/* check saves */
if (psiamp_failed(ch,victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
send_to_char("You failed.\n\r", ch);
return ;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 10);
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
if (ch != victim)
act("You subvert $N's pain receptors.", ch, NULL, victim, TO_CHAR);
else
send_to_char("You subvert your own pain receptors.\n\r", ch );
}
void spell_nerve_amp( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
if (is_affected(victim, gsn_numbness)){
check_dispel( -99, victim, gsn_numbness);
}
if (is_affected(victim, sn)){
send_to_char("Their nerves have already been stimulated.\n\r", ch);
return;
}
/* check saves */
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
send_to_char("You failed.\n\r", ch);
return ;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 10);
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
if (ch != victim)
act("You stimulate $N's pain receptors.", ch, NULL, victim, TO_CHAR);
else
send_to_char("You stimulate your own pain receptors.\n\r", ch );
}
void spell_mirage( 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've already created a mirage of your weapons.\n\r", victim);
return;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 6);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
send_to_char("You create a mirage of your weapons.\n\r", ch);
}
void spell_blink( 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're already prepared to phase out.\n\r", victim);
return;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 6);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
send_to_char("You will now phase out of existance to avoid attacks.\n\r", ch);
}
void spell_phantasm( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af, *paf;
if (is_affected(victim, gen_phantasm)){
send_to_char("They are already hunted by phantasms.\n\r", ch);
return;
}
else if (ch == victim){
send_to_char("You failed.\n\r", ch);
return;
}
/* check saves */
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
send_to_char("You failed.\n\r", ch);
return ;
}
af.type = gen_phantasm;
af.level = level;
af.duration = number_fuzzy(1);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = number_range(5, 11);//how many times phantasm scares
paf = affect_to_char( victim, &af );
string_to_affect( paf, ch->name );
act("A blurred apparition briefly appears before you.", victim, NULL, NULL, TO_CHAR);
act("A blurred apparition briefly appears before $n.", victim, NULL, NULL, TO_ROOM);
}
void spell_duplicate( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo,*clone;
AFFECT_DATA af;
char buf[MSL];
int charmies = 1, duration, chance = number_percent();
if (ch == victim){
send_to_char("You can't cast this spell on yourself.\n\r",ch);
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_affected(victim,sn)){
send_to_char("You cannot duplicate that mob yet.\n\r",ch);
return;
}
if (IS_AFFECTED(victim, AFF_CHARM)
|| victim->level - level > 5
|| victim->fighting != NULL
|| (IS_NPC(victim) && IS_SET(victim->act,ACT_AGGRESSIVE))
|| IS_SET(victim->imm_flags,IMM_CHARM)
|| IS_UNDEAD(victim)
|| !IS_AWAKE(victim)
|| is_affected(victim, gsn_hypnosis)){
send_to_char("You cannot duplicate this creature.\n\r", ch);
return;
}
if (saves_spell( level -3, victim,DAM_CHARM,skill_table[sn].spell_type)){
send_to_char("You failed.\n\r",ch);
return;
}
duration = level / 6;
duration += URANGE(0, (ch->level - victim->level) / 2, 5);
af.where = TO_AFFECTS;
af.type = sn;
af.level = level;
af.duration = duration;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
if (IS_NPC(victim)){
clone = create_mobile(get_mob_index(MOB_VNUM_CLONE));
clone_mobile( victim, clone );
clone_mobile(victim,clone);
clone->group = 0;
clone->level = UMAX(2, clone->level);
sprintf(buf,"illusion %s",victim->name);
free_string(clone->name);
clone->name = str_dup(buf);
char_to_room(clone,ch->in_room);
}
else{
clone = create_mobile(get_mob_index(MOB_VNUM_CLONE));
sprintf(buf,"illusion %s",victim->name);
free_string(clone->name);
clone->name = str_dup(buf);
free_string(clone->description);
clone->description = str_dup(victim->description);
clone->sex = victim->sex;
clone->level = level;
clone->race = victim->race;
char_to_room(clone,ch->in_room);
}
affect_to_char( victim, &af );
af.bitvector = AFF_PASS_DOOR;
affect_to_char( clone, &af );
sprintf( buf, "An illusion of %s", IS_NPC(victim) ? victim->short_descr : victim->name);
free_string( clone->short_descr );
clone->short_descr = str_dup( buf );
af.where = TO_AFFECTS;
af.type = gsn_timer;
af.level = level;
af.duration = duration;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_to_char( clone, &af );
af.type = gsn_charm_person;
af.bitvector = AFF_CHARM;
affect_to_char( clone, &af );
SET_BIT(clone->act2,ACT_DUPLICATE);
if ( chance < 30 ){
sprintf( buf, "A hazy illusion of %s guards its master.\n\r",IS_NPC(victim) ? victim->short_descr : victim->name);
free_string( clone->long_descr );
clone->long_descr = str_dup( buf );
clone->level /= 2;
clone->hit /= 3;
clone->max_hit /= 3;
clone->hitroll /= 2;
clone->damroll /= 2;
clone->damage[DICE_NUMBER] /= 2;
clone->damage[DICE_TYPE] /= 2;
act("$n appears in a hazy smoke!",clone,NULL,NULL,TO_ROOM);
}
else if ( chance < 60 ){
sprintf( buf, "A blurred illusion of %s guards its master.\n\r",IS_NPC(victim) ? victim->short_descr : victim->name);
free_string( clone->long_descr );
clone->long_descr = str_dup( buf );
clone->level = 3 * clone->level/4;
clone->max_hit = 3 * clone->hit / 4;
clone->hit = clone->max_hit;
clone->hitroll -= clone->damroll/4;
clone->damroll -= clone->damroll/4;
clone->damage[DICE_NUMBER]--;
clone->damage[DICE_TYPE]--;
act("$n appears in a blurred light!",clone,NULL,NULL,TO_ROOM);
}
else{
sprintf( buf, "An illusion of %s guards its master.\n\r",IS_NPC(victim) ? victim->short_descr : victim->name);
free_string( clone->long_descr );
clone->long_descr = str_dup( buf );
act("$n appears in a bright flash of light!",clone,NULL,NULL,TO_ROOM);
}
if (clone->master)
stop_follower(clone);
add_follower(clone,ch);
clone->leader = ch;
clone->gold = 0;
}
void spell_time_compression( 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're already compressing time around yourself.\n\r", victim);
return;
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(level / 8);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
send_to_char("You begin to compress time around yourself.\n\r", ch);
act("$n's figure begins to leave a distinct after image.", ch, NULL, NULL, TO_ROOM);
}
void spell_molecular_leash( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af, *paf;
if (is_affected(victim, gen_phantasm)){
send_to_char("They are already been leashed.\n\r", ch);
return;
}
else if (ch == victim){
send_to_char("You failed.\n\r", ch);
return;
}
/* check saves */
if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
send_to_char("You failed.\n\r", ch);
return ;
}
af.type = sn;
af.level = level;
af.duration = 0;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = number_range(4, 9);//how many flees before leash breaks
paf = affect_to_char( victim, &af );
string_to_affect( paf, ch->name );
act("A glowing blue collar appears around your neck.", victim, NULL, NULL, TO_CHAR);
act("A glowing blue collar appears around $n's neck.", victim, NULL, NULL, TO_ROOM);
}
void spell_planar_rift( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
OBJ_DATA *blade;
AFFECT_DATA af;
//Data
int skill = get_skill(ch, sn);
int dice1 = 5;
int dice2 = 5;
int dam = 1;
int hit = 3;
int weight = 0;
const int dur = 12;
/*
We create a rift blade with dam roll /bonues based on level and skill.
blade is no-rem/no-drop/no-uncurse by default, and poofs on drop.
weight is 10 to forstall removing by dropping str
*/
if (IS_NPC(ch))
return;
if (is_affected(ch, sn)){
send_to_char("You lack the strength to create a new planar blade.\n\r",ch);
return;
}
if (get_eq_char(ch, WEAR_WIELD) != NULL
|| (get_eq_char(ch, WEAR_HOLD) != NULL && get_eq_char(ch, WEAR_SHIELD) != NULL)){
send_to_char("Your hands must be ready to wield the blade the moment it is created.\n\r", ch);
return;
}
blade = create_object( get_obj_index(OBJ_VNUM_PLANAR_BLADE),level);
/* Set hit /dam roll*/
dice1 += (skill > 80? 1 : 0) + (skill > 85? 1 : 0);
dice2 += (skill > 90? 1 : 0) + (skill > 95? 1 : 0);
dam += UMAX(0, dice1 - 5);
hit += UMAX(0, dice2 - 5);
if (skill > 99)
hit += 2;
/* set timer */
blade->timer = dur;
/* set dice */
blade->value[1] = dice1;
blade->value[2] = dice2;
/* set level, weight, etc */
blade->level = UMIN(60, 10 + level);
blade->weight = weight;
blade->cost = 0;
/* set dam / hit */
af.type = sn;
af.level = level;
af.duration = -1;
af.where = TO_NONE;
af.bitvector = 0;
af.location = APPLY_DAMROLL;
af.modifier = dam;
affect_to_obj(blade, &af);
af.location = APPLY_HITROLL;
af.modifier = hit;
affect_to_obj(blade, &af);
/* set effect on character */
af.type = sn;
af.level = level;
af.duration = dur;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
/* final check if we can hold the blade */
if (IS_WEAPON_STAT(blade, WEAPON_TWO_HANDS)
&& (get_eq_char(ch, WEAR_SHIELD) != NULL
|| get_eq_char(ch, WEAR_SECONDARY) != NULL
|| get_eq_char(ch, WEAR_HOLD) != NULL)){
send_to_char("You must have both hands free to recive this weapon.\n\r", ch);
return;
}
act("A shimmering plane of force extends from your hand.",ch,blade,NULL,TO_CHAR);
act("A shimmering plane of force extends from $n's hand.",ch,blade,NULL,TO_ROOM);
obj_to_char(blade,ch);
/* check if it zapped and dropped */
if (blade->carried_by != ch)
extract_obj( blade );
else
equip_char(ch, blade, WEAR_WIELD);
if (!IS_IMMORTAL(ch))
affect_to_char(ch, &af);
}
void spell_paralyze( 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("They are already been paralyzed.\n\r", ch);
return;
}
else if (ch == victim){
send_to_char("You failed.\n\r", ch);
return;
}
af.type = gsn_paralyze;
af.level = level;
af.duration = number_fuzzy(1);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = number_range(10, 15);
affect_to_char( victim, &af );
act("$n has been paralyzed!", victim, NULL, NULL, TO_ROOM);
act("You have been paralyzed!", victim, NULL, NULL, TO_CHAR);
}
void spell_petrify( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
CHAR_DATA *victim = (CHAR_DATA *) vo;
AFFECT_DATA af;
int res = 0;
if ( is_affected( victim, sn )){
send_to_char("They've already been petrified.\n\r", ch);
return;
}
if ( (res = check_immune(victim, DAM_CHARM, TRUE)) > IS_IMMUNE){
CHAR_DATA* vch;
for ( vch = char_list; vch != NULL; vch = vch->next ){
if (vch->in_room && vch->in_room->area == victim->in_room->area
&& vch->in_room != victim->in_room)
act("$N's agonizing scream pierces the air and then cuts off abruptly.", vch, NULL, victim, TO_CHAR);
}
af.type = sn;
af.level = level;
af.duration = number_fuzzy(4);
af.where = TO_AFFECTS2;
af.bitvector= AFF_PETRIFY;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char( victim, &af );
stop_fighting(victim, TRUE );
send_to_char( "You have been PETRIFIED!!\n\r\n\r", victim );
act("$n has been PETRIFIED!!", victim, NULL, NULL, TO_ROOM );
}
else
send_to_char("You failed.\n\r", ch);
}