/* ************************************************************************ * file: magic.c , Implementation of spells. Part of DIKUMUD * * Usage : The actual effect of magic. * * Copyright (C) 1990, 1991 - see 'license.doc' for complete information. * ************************************************************************* */ #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <assert.h> #include "structs.h" #include "utility.h" #include "comm.h" #include "db.h" #include "handler.h" #include "limits.h" #include "constants.h" #include "fight.h" #include "act.h" #include "ansi.h" #include "spells.h" int magic_fails(struct char_data *ch, struct char_data *tar_ch){ /* check for magic resistance/wards/immunity */ if ((tar_ch) && (IS_AFFECTED(tar_ch, AFF_MAGIC_IMMUNE))) { if (ch) { ansi(CLR_ERROR, ch); send_to_char("The magic is nullified somehow.\n\r", ch); ansi(END, ch); } return TRUE; } else if ((tar_ch) && (IS_AFFECTED(tar_ch, AFF_MAGIC_RESIST)) && (number(0,101)<GET_LEVEL(tar_ch)+25)) { if (ch) { ansi(CLR_ERROR, ch); send_to_char("The magic fizzles unspectacularly.\n\r", ch); ansi(END, ch); } return TRUE; } return FALSE; } /* Offensive Spells */ void spell_magic_missile(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(MINV(level,4),3)+MINV(level,4); if ( saves_spell(victim, SAVING_SPELL) ) dam >>= 1; DAMAGE(ch, victim, dam, SPELL_MAGIC_MISSILE); } void spell_chill_touch(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(MINV(level>>1,6),6)+MINV((level+1)>>1,12); if ( !saves_spell(victim, SAVING_SPELL) ) { af.type = SPELL_CHILL_TOUCH; af.duration = 6; af.modifier = -2; af.location = APPLY_STR; af.bitvector = 0; affect_join(victim, &af, TRUE, FALSE); } else { dam >>= 1; } DAMAGE(ch, victim, dam, SPELL_CHILL_TOUCH); } void spell_burning_hands(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(MINV(level>>1,10),6)+10; if ( saves_spell(victim, SAVING_SPELL) ) dam >>= 1; DAMAGE(ch, victim, dam, SPELL_BURNING_HANDS); } void spell_shocking_grasp(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(MINV(level>>1,10),8)+level; DAMAGE(ch, victim, dam, SPELL_SHOCKING_GRASP); } void spell_lightning_bolt(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(MINV(level,20),6)+20; if ( saves_spell(victim, SAVING_SPELL) ) dam >>= 1; DAMAGE(ch, victim, dam, SPELL_LIGHTNING_BOLT); } void spell_colour_spray(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(MINV(level,20),8)+level; if ( saves_spell(victim, SAVING_SPELL) && !(af.bitvector = AFF_BLIND) ) { dam >>= 1; ansi_act("$n seems to be blinded!", TRUE, victim, 0, 0, TO_ROOM,CLR_DAM); ansi(CLR_ERROR, victim); send_to_char("You have been blinded!\n\r", victim); ansi(END, victim); af.type = SPELL_BLINDNESS; af.location = APPLY_HITROLL; af.modifier = -4; /* Make hitroll worse */ af.duration = 1; af.bitvector = AFF_BLIND; affect_to_char(victim, &af); af.location = APPLY_AC; af.modifier = +40; /* Make AC Worse! */ affect_to_char(victim, &af); } DAMAGE(ch, victim, dam, SPELL_COLOUR_SPRAY); } /* Drain XP, MANA, HP - caster gains HP and MANA */ void spell_energy_drain(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam, xp, mana; void set_title(struct char_data *ch); void gain_exp(struct char_data *ch, int gain); assert(victim && ch); if (magic_fails(ch,victim)) return; if ( !saves_spell(victim, SAVING_SPELL) ) { GET_ALIGNMENT(ch) = MINV(-1000, GET_ALIGNMENT(ch)-200); if (GET_LEVEL(victim) <= 5) { DAMAGE(ch, victim, 150, SPELL_ENERGY_DRAIN); /* Kill the sucker */ } else { xp = number(level>>1,level)*1000; gain_exp(victim, -xp); dam = dice(1,30); mana = GET_MANA(victim)>>1; GET_MOVE(victim) >>= 1; GET_MANA(victim) = mana; GET_MANA(ch) += mana>>1; GET_HIT(ch) += dam; ansi(CLR_DAM, victim); send_to_char("Your life energy is drained!\n\r", victim); ansi(END, ch); DAMAGE(ch, victim, dam, SPELL_ENERGY_DRAIN); } } else { DAMAGE(ch, victim, 0, SPELL_ENERGY_DRAIN); /* Miss */ } } void spell_fireball(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); if (magic_fails(ch,victim)) return; dam = dice(MINV(level,25),10)+2*level; if ( saves_spell(victim, SAVING_SPELL) ) dam >>= 1; DAMAGE(ch, victim, dam, SPELL_FIREBALL); } void spell_turn_undead(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); if (IS_NPC(victim) && IS_SET(victim->specials.act, CLASS_UNDEAD)) { dam = dice(level,4)+level; DAMAGE(ch, victim, dam, SPELL_TURN_UNDEAD); } else DAMAGE(ch, victim, 0, SPELL_TURN_UNDEAD); } void spell_earthquake(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; struct char_data *tmp_victim, *temp, *leader; assert(ch); assert((level >= 1) && (level <= NPC_LEV)); dam = dice(3,8)+2*level; ansi_act("The earth trembles beneath your feet!", FALSE, ch, 0, 0, TO_CHAR,CLR_ACTION); ansi_act("$n makes the earth tremble and shiver!", FALSE, ch, 0, 0, TO_ROOM,CLR_ACTION); if (ch->master) leader = ch->master; else leader = ch; for(tmp_victim = character_list; tmp_victim; tmp_victim = temp) { temp = tmp_victim->next; if ( (ch->in_room == tmp_victim->in_room) && (ch != tmp_victim) ) { if (tmp_victim->master != leader) DAMAGE(ch, tmp_victim, dam, SPELL_EARTHQUAKE); } else if (world[ch->in_room].zone == world[tmp_victim->in_room].zone) { ansi_act("The earth trembles and shiver!", FALSE, tmp_victim, 0, 0, TO_CHAR,CLR_ACTION); } } } void spell_dispel_evil(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(ch && victim); assert((level >= 1) && (level<=NPC_LEV)); if (magic_fails(ch,victim)) return; if (IS_EVIL(ch)) { victim = ch; ansi(CLR_DAM, ch); send_to_char("You are PRIME EVIL yourself!!!\n\r", ch); ansi(END, ch); } else if (IS_GOOD(victim)) { ansi_act("God protects $N.", FALSE, ch, 0, victim, TO_CHAR,CLR_ERROR); return; } if ((GET_LEVEL(victim) < level) || (victim == ch)) dam = 100; else { dam = dice(level,4); if ( saves_spell(victim, SAVING_SPELL) ) dam >>= 1; } DAMAGE(ch, victim, dam, SPELL_DISPEL_EVIL); } void spell_call_lightning(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; extern struct weather_data weather_info; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(MINV(level,15), 8); if (OUTSIDE(ch) && (weather_info.sky>=SKY_RAINING)) { if ( saves_spell(victim, SAVING_SPELL) ) dam >>= 1; DAMAGE(ch, victim, dam, SPELL_CALL_LIGHTNING); } else { ansi(CLR_ERROR, ch); send_to_char("Try later when bad weather.\n\r", ch); ansi(END, ch); } } void spell_harm(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = GET_HIT(victim) - dice(1,4); dam = MINV(100+2*GET_LEVEL(ch),dam); if (dam < 0) dam = 0; /* Kill the suffering bastard */ else { if ( saves_spell(victim, SAVING_SPELL) ) dam = MINV(20, dam/2); } DAMAGE(ch, victim, dam, SPELL_HARM); } void spell_conflagration(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; dam = dice(level, 14)+level; if (dam < 0) dam = 0; /* Toast 'em off... */ else { /* Hey GP forgot the open brace */ if (saves_spell(victim, SAVING_SPELL)) dam = dam/2; } dam = MAXV(250,dam); DAMAGE(ch, victim, dam, SPELL_CONFLAGRATION); } /* spells2.c - Not directly offensive spells */ void spell_armor(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if (!affected_by_spell(victim, SPELL_ARMOR)) { af.type = SPELL_ARMOR; af.duration = 24; af.modifier = -1*(MINV(20,level*2)); af.location = APPLY_AC; af.bitvector = 0; affect_to_char(victim, &af); if (victim->desc) { ansi(CLR_ACTION, victim); send_to_char("You feel someone protecting you.\n\r", victim); ansi(END, victim); } ansi_act("$n glows white for a moment.",FALSE,victim,0,0,TO_ROOM,WHITE); } else { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); } } void spell_teleport_zone(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int to_room,i,x,y,num,no; assert(ch); i = world[ch->in_room].zone; x = zone_table[i].real_bottom; y = zone_table[i].real_top; num = number(0, MAXV(1,y-x)); for (no = 0; no < num; no++) { /* what am I doing here */ to_room = world[to_room].next; if (IS_SET(world[to_room].room_flags, PRIVATE)) to_room = world[to_room].next; if (world[to_room].zone != i) { to_room = zone_table[i].real_top; break; } } if (IS_SET(world[to_room].room_flags, PRIVATE)) to_room = ch->in_room; if (world[to_room].zone != i) to_room = ch->in_room; ansi_act("$n suddenly winks out of existence.", FALSE, ch,0,0,TO_ROOM,CLR_ACTION); char_from_room(ch); char_to_room(ch, to_room); ansi_act("$n suddenly winks into existence.", FALSE, ch,0,0,TO_ROOM,CLR_ACTION); do_look(ch, "", 0); if (!IS_NPC(ch) && IS_SET(world[to_room].room_flags, DEATH) && GET_LEVEL(ch) < IMO_LEV) { death_cry(ch); extract_char(ch); } } void spell_teleport(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { void do_look(struct char_data *ch, char *argument, int cmd); int to_room; extern int top_of_world; /* ref to the top element of world */ assert(ch); do { to_room = number(0, top_of_world); } while (IS_SET(world[to_room].room_flags, PRIVATE)); ansi_act("$n suddenly winks out of existence.", FALSE, ch,0,0,TO_ROOM,CLR_ACTION); char_from_room(ch); char_to_room(ch, to_room); ansi_act("$n suddenly winks into existence.", FALSE, ch,0,0,TO_ROOM,CLR_ACTION); do_look(ch, "", 0); if (!IS_NPC(ch) && IS_SET(world[to_room].room_flags, DEATH) && GET_LEVEL(ch) < IMO_LEV) { death_cry(ch); extract_char(ch); } } void spell_bless(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(ch && (victim || obj)); assert((level >= 0) && (level <= NPC_LEV)); if (obj) { if ( (5*GET_LEVEL(ch) > GET_OBJ_WEIGHT(obj)) && (GET_POS(ch) != POSITION_FIGHTING) && !IS_OBJ_STAT(obj, ITEM_EVIL)) { SET_BIT(obj->obj_flags.extra_flags, ITEM_BLESS); ansi_act("$p briefly glows.",FALSE,ch,obj,0,TO_CHAR,WHITE); } } else { if ((GET_POS(victim) != POSITION_FIGHTING) && (!affected_by_spell(victim, SPELL_BLESS))) { if (magic_fails(ch,victim)) return; send_to_char("You feel righteous.\n\r", victim); af.type = SPELL_BLESS; af.duration = 6; af.modifier = 1; af.location = APPLY_HITROLL; af.bitvector = 0; affect_to_char(victim, &af); af.location = APPLY_SAVING_SPELL; af.modifier = -1; /* Make better */ affect_to_char(victim, &af); } else if (affected_by_spell(victim, SPELL_BLESS)) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); } } } void spell_blindness(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(ch && victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if (saves_spell(victim, SAVING_SPELL) || affected_by_spell(victim, SPELL_BLINDNESS)) { ansi_act("$N shrugs off your spell with an effort of will.",FALSE,ch,0,victim,TO_CHAR,CLR_ERROR); return; } ansi_act("$n seems to be blinded!", TRUE, victim, 0, 0, TO_ROOM,CLR_ACTION); ansi(CLR_ERROR, victim); send_to_char("You have been blinded!\n\r", victim); ansi(END, victim); af.type = SPELL_BLINDNESS; af.location = APPLY_HITROLL; af.modifier = -4; /* Make hitroll worse */ af.duration = 3; af.bitvector = AFF_BLIND; affect_to_char(victim, &af); af.location = APPLY_AC; af.modifier = +40; /* Make AC Worse! */ affect_to_char(victim, &af); ansi_act("You successfully blind $N.",FALSE,ch,0,victim,TO_CHAR,CLR_ACTION); } void spell_control_weather(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { /* Control Weather is not possible here!!! */ /* Better/Worse can not be transferred */ } void spell_create_food(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct obj_data *tmp_obj; assert(ch); assert((level >= 0) && (level <= NPC_LEV)); CREATE(tmp_obj, struct obj_data, 1); clear_object(tmp_obj); tmp_obj->name = str_alloc("mushroom"); tmp_obj->short_description = str_alloc("A Magic Mushroom"); tmp_obj->description = str_alloc("A really delicious looking magic mushroom lies here."); tmp_obj->obj_flags.type_flag = ITEM_FOOD; tmp_obj->obj_flags.wear_flags = ITEM_TAKE; tmp_obj->obj_flags.value[0] = 5+level; tmp_obj->obj_flags.weight = 1; tmp_obj->obj_flags.cost = 10; tmp_obj->obj_flags.cost_per_day = 1; tmp_obj->next = object_list; object_list = tmp_obj; obj_to_room(tmp_obj,ch->in_room); tmp_obj->item_number = -1; ansi_act("$p suddenly appears.",TRUE,ch,tmp_obj,0,TO_ROOM,CLR_ACTION); ansi_act("$p suddenly appears.",TRUE,ch,tmp_obj,0,TO_CHAR,CLR_ACTION); } void spell_sustenance(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(ch && victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; victim->specials.conditions[THIRST] = MAXV(victim->specials.conditions[THIRST],24); victim->specials.conditions[FULL] = MAXV(victim->specials.conditions[FULL],24); if (GET_LEVEL(victim)>=IMO_LEV) { victim->specials.conditions[THIRST] = -1; victim->specials.conditions[FULL] = -1; } ansi_act("You feel your hunger and thirst decrease.",TRUE,victim,0,0,TO_CHAR,CLR_ACTION); ansi_act("$n glows yellow for a moment.",FALSE,victim,0,0,TO_ROOM,YELLOW); ansi(CLR_ACTION, ch); send_to_char("You have just given a feast!\n\r", ch); ansi(END, ch); } void spell_create_water(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int water; extern struct weather_data weather_info; void name_to_drinkcon(struct obj_data *obj,int type); void name_from_drinkcon(struct obj_data *obj); assert(ch && obj); if (GET_ITEM_TYPE(obj) == ITEM_DRINKCON) { if ((obj->obj_flags.value[2] != LIQ_WATER) && (obj->obj_flags.value[1] != 0)) { name_from_drinkcon(obj); obj->obj_flags.value[2] = LIQ_SLIME; name_to_drinkcon(obj, LIQ_SLIME); } else { water = 2*level * ((weather_info.sky >= SKY_RAINING) ? 2 : 1); /* Calculate water it can contain, or water created */ water = MINV(obj->obj_flags.value[0]-obj->obj_flags.value[1], water); if (water > 0) { obj->obj_flags.value[2] = LIQ_WATER; obj->obj_flags.value[1] += water; weight_change_object(obj, water); name_from_drinkcon(obj); name_to_drinkcon(obj, LIQ_WATER); ansi_act("$p is filled.", FALSE, ch, obj, 0,TO_CHAR,CLR_ACTION); ansi_act("$n magically fills $p with water.", TRUE, ch, obj , 0, TO_ROOM,CLR_ACTION); } } } } void spell_cure_blind(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if (affected_by_spell(victim, SPELL_BLINDNESS)) { affect_from_char(victim, SPELL_BLINDNESS); ansi(CLR_ACTION, victim); send_to_char("Your vision returns!\n\r", victim); ansi(END, victim); ansi_act("$n's vision returns.",FALSE,victim,0,0,TO_ROOM,CLR_ACTION); } else { ansi(CLR_ERROR, ch); send_to_char("But your friend isn't blind!\n\r", ch); ansi(END, ch); } } void spell_cure_critic(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int healpoints; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; healpoints = dice(3,5)+2*level; healpoints = MAXV(40, healpoints); if ( (healpoints + GET_HIT(victim)) > hit_limit(victim) ) GET_HIT(victim) = hit_limit(victim); else GET_HIT(victim) += healpoints; ansi(CLR_ACTION, victim); send_to_char("You feel better!\n\r", victim); ansi(END, victim); ansi_act("$n starts to look a little better.",FALSE,victim,0,0,TO_ROOM,CLR_ACTION); update_pos(victim); } void spell_donate_mana(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( (15 + GET_MANA(victim)) > mana_limit(victim) ) GET_MANA(victim) = mana_limit(victim); else GET_MANA(victim) += 15; ansi(CLR_ACTION, victim); send_to_char("You feel mana flow into you!\n\r", victim); ansi(END, victim); if (victim != ch) ansi_act("You feel some of your mana flow to $N.",FALSE,ch,0,victim,TO_CHAR,CLR_ACTION); } void spell_cause_critic(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int healpoints; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; healpoints = dice(3,8)+3; DAMAGE(ch,victim,healpoints,SPELL_CAUSE_CRITIC); update_pos(victim); } void spell_cure_light(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int healpoints; assert(ch && victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; healpoints = dice(1,8) + level; healpoints = MAXV(20, healpoints); if ( (healpoints+GET_HIT(victim)) > hit_limit(victim) ) GET_HIT(victim) = hit_limit(victim); else GET_HIT(victim) += healpoints; update_pos( victim ); ansi(CLR_ACTION, victim); send_to_char("You feel slightly better!\n\r", victim); ansi(END, victim); ansi_act("$n looks slightly better.",FALSE,victim,0,0,TO_ROOM,CLR_ACTION); } void spell_cause_light(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int healpoints; assert(ch && victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; healpoints = dice(1,8)+1; DAMAGE(ch,victim,healpoints,SPELL_CAUSE_LIGHT); update_pos( victim ); } void spell_curse(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim || obj); assert((level >= 0) && (level <= NPC_LEV)); if (obj) { SET_BIT(obj->obj_flags.extra_flags, ITEM_EVIL); SET_BIT(obj->obj_flags.extra_flags, ITEM_NODROP); /* LOWER ATTACK DICE BY -1 */ if(obj->obj_flags.type_flag == ITEM_WEAPON) obj->obj_flags.value[2]--; ansi_act("$p glows red.", FALSE, ch, obj, 0, TO_CHAR,LRED); } else { if (magic_fails(ch,victim)) return; if (saves_spell(victim, SAVING_SPELL)) { ansi(CLR_ERROR, ch); send_to_char("You failed.\n\r", ch); ansi(END, ch); return; } else if (affected_by_spell(victim, SPELL_CURSE)) { ansi(CLR_ERROR, ch); send_to_char("Your enemy is already badly cursed!\n\r", ch); ansi(END, ch); return; } else { af.type = SPELL_CURSE; af.duration = 24*7; /* 7 Days */ af.modifier = -1; af.location = APPLY_HITROLL; af.bitvector = AFF_CURSE; affect_to_char(victim, &af); af.location = APPLY_SAVING_PARA; af.modifier = 1; /* Make worse */ affect_to_char(victim, &af); ansi_act("$n is surrounded red aura!", FALSE, victim, 0, 0, TO_ROOM,LRED); ansi_act("You feel very UNCOMFORTABLE.",FALSE,victim,0,0,TO_CHAR,CLR_DAM); } } } void spell_detect_evil(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_DETECT_EVIL) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_DETECT_EVIL; af.duration = level*5; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_EVIL; affect_to_char(victim, &af); ansi(YELLOW, victim); send_to_char("You can now distinguish evil from good.\n\r", victim); ansi(END, victim); } void spell_detect_invisibility(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_DETECT_INVISIBLE) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_DETECT_INVISIBLE; af.duration = level*5; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_INVISIBLE; affect_to_char(victim, &af); ansi(YELLOW, victim); send_to_char("Your eyes tingle.\n\r", victim); ansi(END, victim); } void spell_detect_magic(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_DETECT_MAGIC) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_DETECT_MAGIC; af.duration = level*5; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DETECT_MAGIC; affect_to_char(victim, &af); ansi(YELLOW, victim); send_to_char("Your eyes tingle with magical glow.\n\r", victim); ansi(END, victim); } void spell_breathwater(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_BREATHWATER) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_BREATHWATER; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_BREATHWATER; affect_to_char(victim, &af); ansi(CLR_ACTION, victim); send_to_char("You breath easier.\n\r", victim); ansi(END, victim); if (victim != ch) ansi_act("$N starts to breath a little easier.",FALSE,ch,0,victim,TO_CHAR,CLR_ACTION); } void spell_darksight(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_DARKSIGHT) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_DARKSIGHT; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_DARKSIGHT; affect_to_char(victim, &af); ansi(CLR_ACTION, victim); send_to_char("You see easier in darkness.\n\r", victim); ansi(END, victim); ansi_act("$n's eyes begin to glow with an eerie light.",FALSE,victim,0,0,TO_ROOM,LGREEN); } void spell_regeneration(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_REGENERATION) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_REGENERATION; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_REGENERATION; affect_to_char(victim, &af); ansi(CLR_ACTION, victim); send_to_char("You begin to regenerate.\n\r", victim); ansi(END, victim); ansi_act("$n glows white for a moment.",FALSE,victim,0,0,TO_ROOM,WHITE); } void spell_magic_resist(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_MAGIC_RESIST) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_MAGIC_RESIST; af.duration = level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_MAGIC_RESIST; affect_to_char(victim, &af); ansi(CLR_ACTION, victim); send_to_char("You begin to resist the effects of magic.\n\r", victim); ansi(END, victim); ansi_act("$n glows black for a moment.",FALSE,victim,0,0,TO_ROOM,DGRAY); } void spell_magic_immune(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if ( affected_by_spell(victim, SPELL_MAGIC_IMMUNE) ) { ansi(CLR_ERROR, ch); send_to_char("Nothing new happens.\n\r", ch); ansi(END, ch); return; } af.type = SPELL_MAGIC_IMMUNE; af.duration = level>>2; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_MAGIC_IMMUNE; affect_to_char(victim, &af); ansi(CLR_ACTION, victim); send_to_char("All magic near you now fails.\n\r", victim); ansi(END, victim); ansi_act("$n glows black for a moment.",FALSE,victim,0,0,TO_ROOM,DGRAY); } void spell_restoration(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(victim); assert((level >= 0) && (level <= NPC_LEV)); if (magic_fails(ch,victim)) return; if (IS_NPC(victim)) { ansi(CLR_ERROR, ch); send_to_char("You can restore players only.\n\r", ch); ansi(END, ch); return; } GET_EXP(victim) = MAXV(GET_EXP(victim),titles[GET_CLASS(victim)-1][GET_LEVEL(victim)].exp); ansi(CLR_ACTION, victim); send_to_char("You have been magically restored.\n\r", victim); ansi(END, victim); ansi_act("$n is surrounded by white light for a moment.",FALSE,victim,0,0,TO_ROOM,WHITE); } void spell_detect_poison(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(ch && (victim || obj)); if (victim) { if (victim == ch) if (IS_AFFECTED(victim, AFF_POISON)) { ansi(CLR_DAM, ch); send_to_char("You can sense poison in your blood.\n\r", ch); ansi(END, ch); } else { ansi(CLR_ACTION, ch); send_to_char("You feel healthy.\n\r", ch); ansi(END, ch); } else if (IS_AFFECTED(victim, AFF_POISON)) { ansi_act("You sense that $E is poisoned.",FALSE,ch,0,victim,TO_CHAR,CLR_DAM); } else { ansi_act("You sense that $E is healthy.",FALSE,ch,0,victim,TO_CHAR,CLR_ACTION); } } else { /* It's an object */ if ((obj->obj_flags.type_flag == ITEM_DRINKCON) || (obj->obj_flags.type_flag == ITEM_FOOD)) { if (obj->obj_flags.value[3]) ansi_act("Poisonous fumes are revealed.",FALSE, ch, 0, 0, TO_CHAR,CLR_DAM); else { ansi(CLR_ACTION, ch); send_to_char("It looks very delicious.\n\r", ch); ansi(END, ch); } } } } void spell_enchant_weapon(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int i; assert(ch && obj); assert(MAX_OBJ_AFFECT >= 2); if (GET_ITEM_TYPE(obj) != ITEM_WEAPON) { ansi(CLR_ERROR, ch); send_to_char("You can enchant weapons only.\n\r", ch); ansi(END, ch); return; } else if (!IS_SET(obj->obj_flags.extra_flags, ITEM_MAGIC)) { ansi(CLR_ERROR, ch); send_to_char("You can enchant non-magical weapons only.\n\r", ch); ansi(END, ch); return; } else { for (i=0; i < MAX_OBJ_AFFECT; i++) if (obj->affected[i].location != APPLY_NONE) { ansi(CLR_ERROR, ch); send_to_char("This weapon isn't suitable for enchantment.\n\r", ch); ansi(END, ch); return; } } SET_BIT(obj->obj_flags.extra_flags, ITEM_MAGIC); obj->affected[0].location = APPLY_HITROLL; obj->affected[0].modifier = 1 + (level / 10); obj->affected[1].location = APPLY_DAMROLL; obj->affected[1].modifier = 1 + (level / 15); if (IS_GOOD(ch)) { SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_EVIL); ansi_act("$p glows blue.",FALSE,ch,obj,0,TO_CHAR,LBLUE); } else if (IS_EVIL(ch)) { SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_GOOD); ansi_act("$p glows red.",FALSE,ch,obj,0,TO_CHAR,LRED); } else ansi_act("$p glows yellow.",FALSE,ch,obj,0,TO_CHAR,YELLOW); } void spell_heal(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(victim); if (magic_fails(ch,victim)) return; if (affected_by_spell(victim, SPELL_BLINDNESS)) spell_cure_blind(level, ch, victim, obj); if (affected_by_spell(victim, SPELL_POISON)) spell_remove_poison(level, ch, victim, obj); GET_HIT(victim) += 100; if (GET_HIT(victim) >= hit_limit(victim)) GET_HIT(victim) = hit_limit(victim)-dice(1,4); update_pos( victim ); /* ansi(CLR_ACTION, victim); */ send_to_char("A warm feeling fills your body.\n\r", victim); /* ansi(END, victim); */ ansi_act("$n suddenly looks a lot better.",FALSE,victim,0,0,TO_ROOM,CLR_ACTION); } void spell_invisibility(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert((ch && obj) || victim); if (magic_fails(ch,victim)) return; if (obj) { if (IS_SET(obj->obj_flags.extra_flags, ITEM_INVISIBLE)) { ansi(CLR_ERROR, ch); send_to_char("It is already invisible.\n\r", ch); ansi(END, ch); return; } else { ansi_act("$p turns invisible.",FALSE,ch,obj,0,TO_CHAR,CLR_ACTION); ansi_act("$p turns invisible.",TRUE,ch,obj,0,TO_ROOM,CLR_ACTION); SET_BIT(obj->obj_flags.extra_flags, ITEM_INVISIBLE); } } else { /* Then it is a PC | NPC */ if (magic_fails(ch,victim)) return; if (!(IS_SET(victim->specials.affected_by, AFF_INVISIBLE))) { ansi_act("$n slowly fades out of existence.", TRUE, victim,0,0,TO_ROOM,CLR_ACTION); ansi(CLR_ACTION, victim); send_to_char("You vanish.\n\r", victim); ansi(END, victim); af.type = SPELL_INVISIBLE; af.duration = 24; af.modifier = -40; af.location = APPLY_AC; af.bitvector = AFF_INVISIBLE; affect_to_char(victim, &af); } else ansi_act("$N is already invisible.", TRUE,ch,0,victim,TO_CHAR,CLR_ERROR); } } void spell_improved_invis(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert((ch) || victim); if (magic_fails(ch,victim)) return; /* Then it is a PC | NPC */ if ((!affected_by_spell(victim, SPELL_INVISIBLE)) && (!affected_by_spell(victim, SPELL_IMPROVED_INVIS))) { ansi_act("$n slowly fades out of existence.", TRUE, victim,0,0,TO_ROOM,CLR_ACTION); ansi(CLR_ACTION, victim); send_to_char("You vanish.\n\r", victim); ansi(END, victim); af.type = SPELL_IMPROVED_INVIS; af.duration = level/3+3; af.modifier = -40; af.location = APPLY_AC; af.bitvector = AFF_INVISIBLE; affect_to_char(victim, &af); } else ansi_act("$N is already invisible.", FALSE,ch,0,victim,TO_CHAR,CLR_ERROR); } void spell_locate_object(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct obj_data *i,*next; char name[256]; char buf[MAX_STRING_LENGTH]; int j; assert(ch); strcpy(name, fname(obj->name)); j=level>>1; ansi(CLR_ACTION, ch); for (i=object_list; i && (j>0); i = next){ next = i->next; if (isname(name, i->name)) { if(i->carried_by) { sprintf(buf,"%s carried by %s.\n\r", i->short_description,PERS(i->carried_by,ch)); send_to_char(buf,ch); } else if (i->in_obj) { sprintf(buf,"%s in %s.\n\r",i->short_description, i->in_obj->short_description); send_to_char(buf,ch); } else { sprintf(buf,"%s in %s.\n\r",i->short_description, (i->in_room == NOWHERE ? "NOWHERE!?!(bug)" : world[i->in_room].name)); send_to_char(buf,ch); } j--; } } ansi(CLR_ERROR, ch); if(j==0) send_to_char("You are very confused.\n\r",ch); if(j==level>>1) send_to_char("No such object.\n\r",ch); ansi(END, ch); } void spell_poison(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim || obj); if (victim) { if(!saves_spell(victim, SAVING_PARA)) { if (magic_fails(ch,victim)) return; af.type = SPELL_POISON; af.duration = level*2; af.modifier = -2; af.location = APPLY_STR; af.bitvector = AFF_POISON; affect_join(victim, &af, FALSE, FALSE); ansi(CLR_DAM, victim); send_to_char("You feel very sick.\n\r", victim); ansi(END, victim); ansi_act("You have poisoned $N!", FALSE, ch, 0, victim, TO_CHAR,CLR_ACTION); } } else { /* Object poison */ if ((obj->obj_flags.type_flag == ITEM_DRINKCON) || (obj->obj_flags.type_flag == ITEM_FOOD)) { obj->obj_flags.value[3] = 1; ansi_act("You poison $o!", FALSE, ch, obj, victim, TO_CHAR,CLR_ACTION); } else ansi_act("You can't poison $o!", FALSE, ch, obj, victim, TO_CHAR,CLR_ERROR); } } void spell_protection_from_evil(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); if (magic_fails(ch,victim)) return; if (!affected_by_spell(victim, SPELL_PROTECT_FROM_EVIL) ) { af.type = SPELL_PROTECT_FROM_EVIL; af.duration = 24; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_PROTECT_EVIL; affect_to_char(victim, &af); ansi(CLR_ACTION, victim); send_to_char("You have a righteous feeling!\n\r", victim); ansi(END, victim); ansi_act("$n briefly glows with a white light!", FALSE, victim, 0, 0, TO_ROOM,WHITE); } } void spell_remove_curse(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(ch && (victim || obj)); if (obj) { if ( IS_SET(obj->obj_flags.extra_flags, ITEM_EVIL) || IS_SET(obj->obj_flags.extra_flags, ITEM_NODROP)) { ansi_act("$p briefly glows blue.", TRUE, ch, obj, 0, TO_CHAR,LBLUE); REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_EVIL); REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_NODROP); } } else { /* Then it is a PC | NPC */ if (magic_fails(ch,victim)) return; if (affected_by_spell(victim, SPELL_CURSE) ) { ansi_act("$n briefly glows red, then blue.",FALSE,victim,0,0,TO_ROOM,PURPLE); ansi_act("You feel better.",FALSE,victim,0,0,TO_CHAR,CLR_ACTION); affect_from_char(victim, SPELL_CURSE); } } } void spell_remove_poison(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { assert(ch && (victim || obj)); if (victim) { if (magic_fails(ch,victim)) return; if(affected_by_spell(victim,SPELL_POISON)) { affect_from_char(victim,SPELL_POISON); ansi_act("A warm feeling runs through your body.",FALSE,victim,0,0,TO_CHAR,CLR_ACTION); ansi_act("$n looks better.",FALSE,ch,0,victim,TO_ROOM,CLR_ACTION); } } else { if ((obj->obj_flags.type_flag == ITEM_DRINKCON) || (obj->obj_flags.type_flag == ITEM_FOOD)) { obj->obj_flags.value[3] = 0; ansi_act("The $p steams briefly.",FALSE,ch,obj,0,TO_CHAR,CLR_ACTION); } } } void spell_sanctuary(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; if (magic_fails(ch,victim)) return; if (!IS_AFFECTED(victim, AFF_SANCTUARY) ) { ansi_act("$n is surrounded by a bright aura.",TRUE,victim,0,0,TO_ROOM,CLR_SANC); ansi_act("You start glowing.",TRUE,victim,0,0,TO_CHAR,CLR_SANC); af.type = SPELL_SANCTUARY; af.duration = (level<=IMO_LEV) ? 2+level/10 : level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_SANCTUARY; affect_to_char(victim, &af); } } void spell_sleep(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); if (magic_fails(ch,victim)) return; if ( !saves_spell(victim, SAVING_SPELL) ) { af.type = SPELL_SLEEP; af.duration = MAXV(24,4+(level>>1)); af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_SLEEP; affect_join(victim, &af, FALSE, FALSE); if (GET_POS(victim)>POSITION_SLEEPING) { ansi_act("You feel very sleepy ..... zzzzzz",FALSE,victim,0,0,TO_CHAR,CLR_DAM); ansi_act("$n suddenly falls asleep.",TRUE,victim,0,0,TO_ROOM,CLR_DAM); GET_POS(victim)=POSITION_SLEEPING; } return; } else { /* made their save */ if (!number(0,5)) hit(ch,victim,TYPE_UNDEFINED); ansi_act("$N resists the effect of your magic!",TRUE,ch,0,victim,TO_CHAR,CLR_ERROR); } } void spell_strength(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); if (magic_fails(ch,victim)) return; ansi_act("You feel stronger.", FALSE, victim,0,0,TO_CHAR,CLR_ACTION); if (victim != ch) ansi_act("You magically strengthen $N.", FALSE, ch, 0, victim,TO_CHAR,CLR_ACTION); af.type = SPELL_STRENGTH; af.duration = level; af.modifier = 1+(level>18); af.location = APPLY_STR; af.bitvector = 0; affect_join(victim, &af, TRUE, FALSE); } void spell_ventriloquate(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { /* Not possible!! No argument! */ } void spell_word_of_recall(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { extern int top_of_world; int loc_nr,location,was_in; bool found = FALSE; void do_look(struct char_data *ch, char *argument, int cmd); assert(victim); if (magic_fails(ch,victim)) return; if (IS_NPC(victim)) return; if ((ch != victim) && IS_SET(victim->specials.act, PLR_NOSUMMON) && saves_spell(victim, SAVING_SPELL) ) { ansi(CLR_ERROR, ch); send_to_char("You failed.\n\r",ch); ansi(END, ch); ansi_act("$n just attempted to summon you!",FALSE,ch,0,victim,TO_VICT,CLR_ACTION); return; } /* loc_nr = GET_HOME(ch); */ loc_nr = 3001; for (location = 0; location <= top_of_world; location++) if (world[location].number == loc_nr) { found = TRUE; break; } if ((location == top_of_world) || !found) { ansi(CLR_ERROR, victim); send_to_char("You are completely lost.\n\r", victim); ansi(END, victim); return; } /* a location has been found. */ was_in = ch->in_room; ansi_act("$n disappears.", TRUE, victim, 0, 0, TO_ROOM,CLR_ACTION); char_from_room(victim); char_to_room(victim, location); ansi_act("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM,CLR_ACTION); do_look(victim, "",15); if (IS_SET(zone_table[world[was_in].zone].flags, ZONE_TESTING)) char_del_zone_objs(ch); } void spell_summon(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { void do_look(struct char_data *ch, char *argument, int cmd); sh_int target; assert(ch && victim); if (magic_fails(ch,victim)) return; if (GET_LEVEL(victim) > MINV(41,level+10)) { ansi(CLR_ERROR, ch); send_to_char("They are too high in level for YOU to summon.\n\r",ch); ansi(END, ch); return; } if ((IS_SET(zone_table[world[victim->in_room].zone].flags, ZONE_NOENTER) || IS_SET(zone_table[world[victim->in_room].zone].flags, ZONE_TESTING) || IS_SET(zone_table[world[ch->in_room].zone].flags, ZONE_NOENTER) || IS_SET(zone_table[world[ch->in_room].zone].flags, ZONE_TESTING)) && (GET_LEVEL(ch) < IMO_LEV2)) { ansi(CLR_ERROR, ch); send_to_char("A strange power surge interferes!\n\r",ch); ansi(END, ch); return; } if (IS_SET(victim->specials.act, PLR_NOSUMMON) && saves_spell(victim, SAVING_SPELL) ) { ansi(CLR_ERROR, ch); send_to_char("You failed.\n\r",ch); ansi(END, ch); ansi_act("$n just attempted to summon you!", FALSE,ch,0,victim,TO_VICT,CLR_ACTION); return; } if (IS_NPC(victim) && saves_spell(victim, SAVING_SPELL) ) { ansi(CLR_ERROR, ch); send_to_char("You failed.\n\r", ch); ansi(END, ch); return; } ansi_act("$n disappears suddenly.",TRUE,victim,0,0,TO_ROOM,CLR_ACTION); target = ch->in_room; char_from_room(victim); char_to_room(victim,target); ansi_act("$n arrives suddenly.",TRUE,victim,0,0,TO_ROOM,CLR_ACTION); ansi_act("$n has summoned you!",FALSE,ch,0,victim,TO_VICT,CLR_ACTION); do_look(victim,"",15); } void spell_succor(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { void do_look(struct char_data *ch, char *argument, int cmd); sh_int target; assert(ch && victim); if (magic_fails(ch,victim)) return; if (GET_LEVEL(victim) > MINV(40,level+10)) { ansi(CLR_ERROR, ch); send_to_char("They are too high in level for YOU to succor.\n\r",ch); ansi(END, ch); return; } if ((IS_SET(zone_table[world[victim->in_room].zone].flags, ZONE_NOENTER) || IS_SET(zone_table[world[victim->in_room].zone].flags, ZONE_TESTING) || IS_SET(zone_table[world[ch->in_room].zone].flags, ZONE_NOENTER) || IS_SET(zone_table[world[ch->in_room].zone].flags, ZONE_TESTING)) && (GET_LEVEL(ch) < IMO_LEV2)) { ansi(CLR_ERROR, ch); send_to_char("A strange power surge interferes!\n\r",ch); ansi(END, ch); return; } if (IS_NPC(victim) || (IS_SET(victim->specials.act, PLR_NOSUMMON) && saves_spell(victim, SAVING_SPELL)) ) { ansi(CLR_ERROR, ch); send_to_char("You failed.\n\r",ch); ansi(END, ch); ansi_act("$n just attempted to succor you!", FALSE,ch,0,victim,TO_VICT,CLR_ACTION); return; } if (IS_NPC(victim) && saves_spell(victim, SAVING_SPELL) ) { ansi(CLR_ERROR, ch); send_to_char("You failed.\n\r", ch); ansi(END, ch); return; } ansi_act("$n disappears suddenly.",TRUE,ch,0,0,TO_ROOM,CLR_ACTION); target = victim->in_room; char_from_room(ch); char_to_room(ch,target); ansi_act("$n arrives suddenly.",TRUE,ch,0,0,TO_ROOM,CLR_ACTION); ansi_act("$n has succored you!",FALSE,ch,0,victim,TO_VICT,CLR_ACTION); do_look(ch,"",15); } void spell_charm_person(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; void add_follower(struct char_data *ch, struct char_data *leader); bool circle_follow(struct char_data *ch, struct char_data *victim); void stop_follower(struct char_data *ch); assert(ch && victim); if (magic_fails(ch,victim)) return; /* By testing for IS_AFFECTED we avoid ei. Mordenkainens sword to be */ /* abel to be "recharmed" with duration */ if (victim == ch) { ansi(CLR_ACTION, ch); send_to_char("You like yourself even better!\n\r", ch); ansi(END, ch); return; } if (((IS_NPC(victim))&&(IS_SET(victim->specials.act, ACT_NOCHARM))) ||(level < GET_LEVEL(victim))) { ansi_act("$N prefers to be $S own master.", FALSE, ch, 0, victim, TO_CHAR, CLR_ERROR); if (!number(0,5)) hit(ch,victim,TYPE_UNDEFINED); return; } if (!IS_AFFECTED(victim, AFF_CHARM) && !IS_AFFECTED(ch, AFF_CHARM)) { if (circle_follow(victim, ch)) { ansi(CLR_ERROR, ch); send_to_char("Sorry, following in circles can not be allowed.\n\r", ch); ansi(END, ch); return; } if (saves_spell(victim, SAVING_SPELL)) { ansi_act("$N prefers to be $S own master.", FALSE, ch, 0, victim, TO_CHAR, CLR_ERROR); if (!number(0,5)) hit(ch,victim,TYPE_UNDEFINED); return; } if (victim->master) stop_follower(victim); add_follower(victim, ch); af.type = SPELL_CHARM_PERSON; if (GET_INT(victim)) af.duration = 24*18/GET_INT(victim); else af.duration = 24*18; af.modifier = 0; af.location = 0; af.bitvector = AFF_CHARM; affect_to_char(victim, &af); ansi_act("Isn't $n just such a nice fellow?",FALSE,ch,0,victim,TO_VICT,CLR_ACTION); } } void spell_sense_life(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; assert(victim); if (magic_fails(ch,victim)) return; if (!affected_by_spell(victim, SPELL_SENSE_LIFE)) { ansi(CLR_ACTION, ch); send_to_char("Your feel your awareness improve.\n\r", ch); ansi(END, ch); af.type = SPELL_SENSE_LIFE; af.duration = 5*level; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_SENSE_LIFE; affect_to_char(victim, &af); } } void spell_identify(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { char buf[256], buf2[256]; int i; bool found; struct time_info_data age(struct char_data *ch); /* Spell Names */ extern const char *spells[]; assert(ch && (obj || victim)); if (obj) { ansi(CLR_ACTION, ch); send_to_char("You feel informed:\n\r", ch); sprintf(buf, "Object '%s', Item type: ", obj->name); sprinttype(GET_ITEM_TYPE(obj),item_types,buf2); strcat(buf,buf2); strcat(buf,"\n\r"); send_to_char(buf, ch); if (obj->obj_flags.bitvector) { send_to_char("Item will give you following abilities: ", ch); sprintbit(obj->obj_flags.bitvector,affected_bits,buf); strcat(buf,"\n\r"); send_to_char(buf, ch); } send_to_char("Item is: ", ch); sprintbit(obj->obj_flags.extra_flags,extra_bits,buf); strcat(buf,"\n\r"); send_to_char(buf,ch); sprintf(buf,"Weight: %d, Value: %d\n\r", obj->obj_flags.weight, obj->obj_flags.cost); send_to_char(buf, ch); switch (GET_ITEM_TYPE(obj)) { case ITEM_SCROLL : case ITEM_POTION : sprintf(buf, "Level %d spells of:\n\r", obj->obj_flags.value[0]); send_to_char(buf, ch); if (obj->obj_flags.value[1] >= 1) { sprinttype(obj->obj_flags.value[1]-1,spells,buf); strcat(buf,"\n\r"); send_to_char(buf, ch); } if (obj->obj_flags.value[2] >= 1) { sprinttype(obj->obj_flags.value[2]-1,spells,buf); strcat(buf,"\n\r"); send_to_char(buf, ch); } if (obj->obj_flags.value[3] >= 1) { sprinttype(obj->obj_flags.value[3]-1,spells,buf); strcat(buf,"\n\r"); send_to_char(buf, ch); } break; case ITEM_WAND : case ITEM_STAFF : sprintf(buf, "Has %d charges, with %d charges left.\n\r", obj->obj_flags.value[1], obj->obj_flags.value[2]); send_to_char(buf, ch); sprintf(buf, "Level %d spell of:\n\r", obj->obj_flags.value[0]); send_to_char(buf, ch); if (obj->obj_flags.value[3] >= 1) { sprinttype(obj->obj_flags.value[3]-1,spells,buf); strcat(buf,"\n\r"); send_to_char(buf, ch); } break; case ITEM_WEAPON : send_to_char("Weapons bits: ",ch); sprintbit(obj->obj_flags.value[0],weapon_bits,buf); strcat(buf,"\n\r"); send_to_char(buf,ch); sprintf(buf, "Damage Dice is '%dD%d'\n\r", obj->obj_flags.value[1], obj->obj_flags.value[2]); send_to_char(buf, ch); break; case ITEM_ARMOR : sprintf(buf, "AC-apply is %d\n\r", obj->obj_flags.value[0]); send_to_char(buf, ch); break; } found = FALSE; for (i=0;i<MAX_OBJ_AFFECT;i++) { if ((obj->affected[i].location != APPLY_NONE) && (obj->affected[i].modifier != 0)) { if (!found) { send_to_char("Can affect you as :\n\r", ch); found = TRUE; } sprinttype(obj->affected[i].location,apply_types,buf2); sprintf(buf," Affects : %s By %d\n\r", buf2,obj->affected[i].modifier); send_to_char(buf, ch); } } } else { /* victim */ if (!IS_NPC(victim)) { sprintf(buf,"%d Years, %d Months, %d Days, %d Hours old.\n\r", age(victim).year, age(victim).month, age(victim).day, age(victim).hours); send_to_char(buf,ch); /* sprintf(buf,"Height %dcm Weight %dpounds \n\r", GET_HEIGHT(victim), GET_WEIGHT(victim)); send_to_char(buf,ch); */ sprintf(buf,"Str %d/%d, Int %d, Wis %d, Dex %d, Con %d\n\r", GET_STR(victim), GET_ADD(victim), GET_INT(victim), GET_WIS(victim), GET_DEX(victim), GET_CON(victim) ); send_to_char(buf,ch); } else { /* is a mob */ ansi(CLR_ERROR, ch); send_to_char("You learn nothing new.\n\r", ch); } } ansi(END, ch); } void spell_fire_breath(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; struct obj_data *burn; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (IS_NPC(ch)) dam = dice(level,10) + 3*level; else dam = dice(level>>1,10)+2*level; if ( saves_spell(victim, SAVING_BREATH) ) dam >>= 1; /* And now for the damage on inventory */ if(number(0,50)>GET_LEVEL(ch)){ if (!saves_spell(victim, SAVING_BREATH) ){ for(burn=victim->carrying ; burn && (burn->obj_flags.type_flag!=ITEM_SCROLL) && (burn->obj_flags.type_flag!=ITEM_WAND) && (burn->obj_flags.type_flag!=ITEM_STAFF) && (burn->obj_flags.type_flag!=ITEM_NOTE) && (number(0,2)==0) ; burn=burn->next_content); if(burn){ /* if we found one thing to burn its gone */ ansi_act("$o burns!",0,victim,burn,0,TO_CHAR,CLR_DAM); extract_obj(burn); } } } DAMAGE(ch, victim, dam, SPELL_FIRE_BREATH); } void spell_frost_breath(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; struct obj_data *frozen; struct affected_type af; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if ( !saves_spell(victim, SAVING_BREATH) ) { af.type = SPELL_CHILL_TOUCH; af.duration = 1; af.modifier = -1; af.location = APPLY_STR; af.bitvector = 0; affect_join(victim, &af, TRUE, FALSE); send_to_char("The intense cold saps your strength.\n\r", victim); } if (IS_NPC(ch)) dam = dice(level,8) + 3*level; else dam = dice(MINV(level>>1,6),6)+MINV((level+1)>>1,12); if ( saves_spell(victim, SAVING_BREATH) ) dam >>= 1; DAMAGE(ch, victim, dam, SPELL_FROST_BREATH); /* And now for the damage on inventory */ if(number(0,50)<GET_LEVEL(ch)) { if (!saves_spell(victim, SAVING_BREATH) ) { for(frozen=victim->carrying ; frozen && (frozen->obj_flags.type_flag!=ITEM_DRINKCON) && (frozen->obj_flags.type_flag!=ITEM_FOOD) && (frozen->obj_flags.type_flag!=ITEM_POTION) && (number(0,2)==0) ; frozen=frozen->next_content); if(frozen) { ansi_act("$o breaks.",0,victim,frozen,0,TO_CHAR,CLR_DAM); extract_obj(frozen); } } } } void spell_acid_breath(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; int damaged; int apply_ac(struct char_data *ch, int eq_pos); assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (IS_NPC(ch)) dam = dice(level,6) + 3*level; else dam = dice(MINV(level>>1,10),6)+10; if ( saves_spell(victim, SAVING_BREATH) ) dam >>= 1; /* And now for the damage on equipment */ if(number(0,50)<GET_LEVEL(ch)) { if (!saves_spell(victim, SAVING_BREATH) ) { for(damaged = 0; damaged<MAX_WEAR && (victim->equipment[damaged]) && (victim->equipment[damaged]->obj_flags.type_flag==ITEM_ARMOR) && (victim->equipment[damaged]->obj_flags.value[0]>0) && (number(0,2)==0) ; damaged++) { ansi_act("$o is damaged.",0,victim,victim->equipment[damaged],0,TO_CHAR,CLR_DAM); GET_AC(victim)-=apply_ac(victim,damaged); ch->equipment[damaged]->obj_flags.value[0]-=number(1,7); GET_AC(victim)+=apply_ac(victim,damaged); ch->equipment[damaged]->obj_flags.cost = 0; } } } DAMAGE(ch, victim, dam, SPELL_ACID_BREATH); } void spell_gas_breath(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { struct affected_type af; int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (IS_NPC(ch)) dam = dice(level,4) + 3*level; else dam = dice(MINV(level>>1,4),3)+MINV(level>>1,4); if ( saves_spell(victim, SAVING_BREATH) ) dam >>= 1; if(!saves_spell(victim, SAVING_PARA)) { af.type = SPELL_POISON; af.duration = level*2; af.modifier = -2; af.location = APPLY_STR; af.bitvector = AFF_POISON; affect_join(victim, &af, FALSE, FALSE); ansi_act("$n starts choking on the toxic fumes!!", TRUE, victim, 0, 0,TO_ROOM,CLR_DAM); ansi(CLR_ERROR, victim); send_to_char("You feel very sick.\n\r", victim); ansi(END, victim); } if(!saves_spell(victim, SAVING_BREATH)&&(!affected_by_spell(victim, SPELL_BLINDNESS))) { af.type = SPELL_BLINDNESS; af.location = APPLY_HITROLL; af.modifier = -4; /* Make hitroll worse */ af.duration = 3; af.bitvector = AFF_BLIND; affect_to_char(victim, &af); af.location = APPLY_AC; af.modifier = +40; /* Make AC Worse! */ affect_to_char(victim, &af); ansi_act("$n seems to have been blinded by the gas!", TRUE, victim, 0, 0, TO_ROOM,CLR_DAM); ansi(CLR_DAM, victim); send_to_char("You have been blinded!\n\r", victim); ansi(END, victim); } DAMAGE(ch, victim, dam, SPELL_GAS_BREATH); } void spell_lightning_breath(sbyte level, struct char_data *ch, struct char_data *victim, struct obj_data *obj) { int dam; assert(victim && ch); assert((level >= 1) && (level <= NPC_LEV)); if (IS_NPC(ch)) dam = dice(level,5) + 3*level; else dam = dice(MINV(level>>1,20),6)+20; if ( saves_spell(victim, SAVING_BREATH) ) dam >>= 1; DAMAGE(ch, victim, dam, SPELL_LIGHTNING_BREATH); }