/* ************************************************************************
* 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 <assert.h>
#include <malloc.h>
#include <stdlib.h>
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "spells.h"
#include "handler.h"
#include "limits.h"
#include "db.h"
/* Extern structures */
extern int nokillflag;
extern struct room_data *world;
extern struct obj_data *object_list;
extern struct char_data *character_list;
extern struct index_data *mob_index;
extern struct index_data *obj_index;
/* Extern procedures */
void do_look(struct char_data *ch, char *argument, int cmd);
void damage(struct char_data *ch, struct char_data *victim,
int damage, int weapontype);
bool saves_spell(struct char_data *ch, sh_int spell);
void weight_change_object(struct obj_data *obj, int weight);
char *strdup(char *source);
int dice(int number, int size);
void hit(struct char_data *ch, struct char_data *victim, int type);
void add_follower(struct char_data *ch, struct char_data *leader);
void spell_remove_poison(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj);
void banish(struct char_data *vict)
{
int location;
extern int top_of_world;
SET_BIT(vict->specials.act, PLR_BANISHED);
for(location = 0; location < top_of_world; location++)
if(world[location].number == 6999)
break;
act("$n disappears in a puff of smoke.",FALSE,vict,0,0,TO_ROOM);
char_from_room(vict);
char_to_room(vict,location);
act("$n appears with an ear-splitting bang.",FALSE,vict,0,0,TO_ROOM);
send_to_char("You smell fire and brimstone?\n\r", vict);
}
/* Offensive Spells */
void spell_magic_missile(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,50);
if ( saves_spell(victim, SAVING_SPELL) )
dam >>= 1;
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_MAGIC_MISSILE_WPN);
else
damage(ch, victim, dam, SPELL_MAGIC_MISSILE);
}
void spell_chill_touch(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
int dam;
assert(victim && ch);
dam = number(1,100);
if(nokillflag && !IS_NPC(ch) && !IS_NPC(victim))
return;
if(IS_AFFECTED(victim,SPELL_CHILL_TOUCH))
return;
if ( !saves_spell(victim, SAVING_SPELL) ) {
af.type = SPELL_CHILL_TOUCH;
af.duration = 6+level/10;
af.modifier = -2 - level/100;
af.location = APPLY_STR;
af.bitvector = 0;
affect_join(victim, &af, TRUE, FALSE);
} else {
dam >>= 2;
}
damage(ch, victim, dam, SPELL_CHILL_TOUCH);
}
void spell_burning_hands(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,200);
if(saves_spell(victim, SAVING_SPELL))
dam >>= 1;
damage(ch, victim, dam, SPELL_BURNING_HANDS);
}
void spell_shocking_grasp(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,400);
if(saves_spell(victim, SAVING_SPELL))
dam >>= 1;
else if(obj)
spell_burning_hands(level,ch,victim,obj);
damage(ch, victim, dam, SPELL_SHOCKING_GRASP);
}
void spell_lightning_bolt(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,800);
if ( saves_spell(victim, SAVING_SPELL) )
dam >>= 1;
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_BOLT_WPN);
else
damage(ch, victim, dam, SPELL_LIGHTNING_BOLT);
}
void spell_colour_spray(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,1600);
if ( saves_spell(victim, SAVING_SPELL) )
dam >>= 1;
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_COLOUR_SPRAY_WPN);
else
damage(ch, victim, dam, SPELL_COLOUR_SPRAY);
}
/* Drain XP, MANA, HP - caster gains HP and MANA */
void spell_energy_drain(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam, xp, mana;
void gain_exp(struct char_data *ch, int gain);
assert(victim && ch);
if(IS_SET(world[ch->in_room].room_flags,LAWFUL))
return;
if( !saves_spell(victim, SAVING_SUNBURST) ) {
if (GET_LEVEL(victim) <= 2) {
damage(ch,victim, 100, SPELL_ENERGY_DRAIN); /* Kill the sucker */
} else {
if((GET_LEVEL(ch) < IMO) && !IS_NPC(ch) && !IS_NPC(victim))
victim = ch;
xp = number(level>>1,level)*5000;
gain_exp(victim, -xp);
dam = dice(1,10);
mana = GET_MANA(victim)>>1;
GET_MOVE(victim) >>= 1;
GET_MANA(victim) = mana;
GET_MANA(ch) += mana>>1;
GET_HIT(ch) += dam;
send_to_char("Your life energy is drained!\n\r", victim);
damage(ch, victim, dam, SPELL_ENERGY_DRAIN);
}
} else {
damage(ch, victim, 0, SPELL_ENERGY_DRAIN); /* Miss */
hit(victim,ch,TYPE_UNDEFINED);
}
}
void spell_fireball(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam,lev;
assert(victim && ch);
lev = GET_LEVEL(ch);
dam = number(1,100+((lev*lev)>>3));
if (saves_spell(victim, SAVING_SPELL) )
dam >>= 1;
if(GET_LEVEL(victim) > (IMO>>1))
dam >>= 1;
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_FIREBALL_WPN);
else
damage(ch, victim, dam, SPELL_FIREBALL);
}
void spell_sunburst(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,6400);
if(saves_spell(victim,SAVING_SPELL))
dam >>= 1;
if(GET_LEVEL(victim) > (IMO>>1))
dam >>= 1;
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_SUNBURST_WPN);
else
damage(ch, victim, dam, SPELL_SUNBURST);
}
void spell_doppelganger(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,102400);
if(saves_spell(victim,SAVING_SPELL))
dam >>= 1;
if(GET_LEVEL(victim) > (IMO>>1))
dam >>= 1;
damage(ch, victim, dam, SPELL_DOPPELGANGER);
}
void spell_jingle(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = number(1,100000);
if(saves_spell(victim,SAVING_SPELL))
dam >>= 1;
if(GET_LEVEL(victim) > (IMO>>1))
dam >>= 1;
damage(ch, victim, dam, SPELL_JINGLE);
}
void spell_nova(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam,manaloss,rat,tmp,m;
struct obj_data *sh;
assert(victim && ch);
if(IS_NPC(ch)){
dam=number(1,GET_HIT(ch));
} else if(GET_LEVEL(ch) < 999){
dam=number(1,GET_MANA(ch));
GET_MANA(ch) -= dam;
if(GET_MANA(ch) < 100)
GET_MANA(ch)=100;
} else {
dam=2000000000;
}
if(saves_spell(victim, SAVING_SUNBURST)){
act("But $N avoids the worst of the nova...",FALSE,ch,0,victim,TO_NOTVICT);
act("But you avoid the worst of the nova...",FALSE,ch,0,victim,TO_VICT);
dam >>= 4;
}
if((sh=victim->equipment[WEAR_SHIELD])&&
(sh->obj_flags.value[1]==SHIELD_NOVA)){
dam >>= 4;
act("$N's shield deflects most of the nova.",FALSE,ch,0,victim,TO_NOTVICT);
act("Your shield deflects most of the nova from $n.",
FALSE, ch, 0, victim, TO_VICT);
}
damage(ch, victim, dam, SPELL_NOVA);
}
void spell_dispel_evil(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(ch && victim);
if (IS_EVIL(ch))
victim = ch;
else
if (IS_GOOD(victim)) {
act("God protects $N.", FALSE, ch, 0, victim, TO_CHAR);
return;
}
if ((GET_LEVEL(victim) < level) || (victim == ch))
dam = 50;
else {
dam = dice(level,5);
if ( saves_spell(victim, SAVING_SPELL) )
dam >>= 1;
}
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_DISPEL_EVIL_WPN);
else
damage(ch, victim, dam, SPELL_DISPEL_EVIL);
}
void spell_morphia(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
struct char_data *tmp;
assert(victim && ch);
dam = number(1,12800);
if ( saves_spell(victim, SAVING_SPELL) )
dam >>= 2;
damage(ch, victim, dam, SPELL_MORPHIA);
}
void spell_slime(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
struct char_data *tmp;
struct obj_data *sh;
assert(victim && ch);
dam = number(1,25600);
if((sh=victim->equipment[WEAR_SHIELD])&&
(sh->obj_flags.value[1]==SHIELD_SLIME)){
dam >>= 4;
act("$N's shield deflects most of the slime.",
FALSE, ch, 0, victim, TO_NOTVICT);
act("Your shield deflects most of the slime from $n.",
FALSE, ch, 0, victim, TO_VICT);
}
if ( saves_spell(victim, SAVING_SPELL) )
dam >>= 2;
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_SLIME_WPN);
else
damage(ch, victim, dam, SPELL_SLIME);
}
void spell_gas(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
struct char_data *tmp;
struct obj_data *sh;
assert(victim && ch);
dam = number(1,51200);
if((sh=victim->equipment[WEAR_SHIELD])&&
(sh->obj_flags.value[1]==SHIELD_GAS)){
dam >>= 4;
act("$N's shield absorbs most of the gas.",
FALSE, ch, 0, victim, TO_NOTVICT);
act("Your shield absorbs most of the gas from $n.",
FALSE, ch, 0, victim, TO_VICT);
}
if(saves_spell(victim, SAVING_SPELL) )
dam >>= 1;
if((obj) && (GET_ITEM_TYPE(obj) == ITEM_WEAPON))
damage(ch, victim, dam, SPELL_GAS_WPN);
else
damage(ch, victim, dam, SPELL_GAS);
}
void spell_harm(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
struct obj_data *sh;
assert(victim && ch);
dam = number(1,GET_MOVE(ch));
if (dam < 0)
dam = 0;
else if(!IS_NPC(ch)){
if(saves_spell(victim,SAVING_SPELL))
dam >>= 1;
if(saves_spell(victim,SAVING_SPELL))
dam >>= 1;
}
if((sh=victim->equipment[WEAR_SHIELD])&&
(sh->obj_flags.value[1]==SHIELD_HARM)){
dam >>= 2;
act("$N's shield reduces the harm.", FALSE, ch, 0, victim, TO_NOTVICT);
act("Your shield reduces the harm.", FALSE, ch, 0, victim, TO_VICT);
}
damage(ch, victim, dam, SPELL_HARM);
GET_MOVE(ch) -= (dam>>1);
}
void spell_barf(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
assert(victim && ch);
dam = GET_COND(ch,THIRST)+GET_COND(ch,FULL);
if(IS_AFFECTED(ch,AFF_POISON))
dam <<= 1;
GET_COND(ch,THIRST) = GET_COND(ch,FULL) = 0;
damage(ch, victim, dam, SPELL_BARF);
}
void spell_armor(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim);
if (!affected_by_spell(victim, SPELL_ARMOR)) {
af.type = SPELL_ARMOR;
af.duration = 24;
af.modifier = (number(1,25) + (level/50));
af.location = APPLY_AC;
af.bitvector = 0;
affect_to_char(victim, &af);
send_to_char("You feel someone protecting you.\n\r", victim);
}
}
void spell_relocate(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
char buf[MAX_INPUT_LENGTH];
int location,i;
struct char_data *pers, *mnt;
assert(ch);
if (CAN_SEE(ch,victim)){
i=level-GET_LEVEL(victim);
if(i < 0){
send_to_char("Your spell is not powerful enough for that.\n\r",ch);
return;
} else if(number(0,2) > i){
send_to_char("You make a valiant effort, but barely fail.\n\r",ch);
return;
}
location = victim->in_room;
} else {
send_to_char("No such creature around, what a waste.\n\r", ch);
return;
}
if (IS_SET(world[location].room_flags, PRIVATE) ||
IS_SET(world[location].room_flags, NORELOCATE) ||
IS_SET(world[location].room_flags, OFF_LIMITS)) {
send_to_char( "You fail miserably.\n\r", ch);
return;
}
if(IS_SET(victim->specials.act,PLR_NORELO)){
act("$N seems to be resisting your efforts.",TRUE,ch,0,victim, TO_CHAR);
return;
}
act("$n disappears in a puff of purple smoke.", FALSE,ch,0,0,TO_ROOM);
char_from_room(ch);
char_to_room(ch, location);
act("$n appears with a modest poof.",FALSE,ch,0,0,TO_ROOM);
do_look(ch,"",15);
}
void spell_bless(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(ch && (victim || obj));
if (obj) {
if(GET_POS(ch) != POSITION_FIGHTING){
SET_BIT(obj->obj_flags.extra_flags, ITEM_BLESS);
act("$p briefly glows.",FALSE,ch,obj,0,TO_CHAR);
}
} else {
if ((GET_POS(victim) != POSITION_FIGHTING) &&
(!affected_by_spell(victim, SPELL_BLESS))) {
send_to_char("You feel righteous.\n\r", victim);
af.type = SPELL_BLESS;
af.duration = 6;
af.modifier = 1+(level/25);
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);
if (!affected_by_spell(victim, SPELL_HOLDALIGN))
GET_ALIGNMENT(victim) = (1000);
}
}
}
static int wps[]=
{2,4,8,16,32,64,128,256,512,1024,2048,4096,16384,131072,262144};
void spell_transmutation(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(ch && obj);
if (obj) {
if(IS_OBJ_STAT(obj,ITEM_MUTABLE)){
obj->obj_flags.wear_flags = 1 + wps[number(0,14)];
REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_MUTABLE);
act("$p briefly flashes gold.",FALSE,ch,obj,0,TO_CHAR);
} else {
obj->obj_flags.wear_flags = 1;
act("$p briefly flashes silver.",FALSE,ch,obj,0,TO_CHAR);
}
}
}
void spell_blindness(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct obj_data *o;
struct affected_type af;
assert(ch && victim);
if(level < IMO){
if(!IS_NPC(ch) && !IS_NPC(victim) &&
!IS_SET(world[ch->in_room].room_flags,PK_ROOM))
return;
if(saves_spell(victim, SAVING_SPELL) ||
affected_by_spell(victim, SPELL_BLINDNESS))
return;
if((o=victim->equipment[WEAR_FACE]) && (o->obj_flags.value[2]==5))
return;
} else {
return;
}
act("$n seems to be blinded!", TRUE, victim, 0, 0, TO_ROOM);
send_to_char("You have been blinded!\n\r", victim);
af.type = SPELL_BLINDNESS;
af.location = APPLY_HITROLL;
af.modifier = -(3+(level>>6)); /* Make hitroll worse */
af.duration = 1;
af.bitvector = AFF_BLIND;
affect_to_char(victim, &af);
af.location = APPLY_AC;
af.modifier = -(5+(level>>3)); /* Make AC Worse! */
affect_to_char(victim, &af);
}
void spell_create_food(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct obj_data *tmp_obj;
assert(ch);
CREATE(tmp_obj, struct obj_data, 1);
clear_object(tmp_obj);
tmp_obj->name = strdup("mushroom");
tmp_obj->short_description = strdup("A Magic Mushroom");
tmp_obj->description = strdup("A really delicious looking magic mushroom lies here.");
tmp_obj->obj_flags.type_flag = ITEM_FOOD;
tmp_obj->obj_flags.wear_flags = ITEM_TAKE | ITEM_HOLD;
tmp_obj->obj_flags.value[0] = 5+level;
tmp_obj->obj_flags.weight = 1;
tmp_obj->obj_flags.cost = 10;
tmp_obj->next = object_list;
object_list = tmp_obj;
obj_to_room(tmp_obj,ch->in_room);
tmp_obj->item_number = -1;
act("$p suddenly appears.",TRUE,ch,tmp_obj,0,TO_ROOM);
act("$p suddenly appears.",TRUE,ch,tmp_obj,0,TO_CHAR);
}
void spell_create_water(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int weight;
assert(ch && obj);
if(GET_ITEM_TYPE(obj) == ITEM_DRINKCON) {
weight = obj->obj_flags.value[0] - obj->obj_flags.value[1];
obj->obj_flags.value[1] += weight;
weight_change_object(obj, weight);
act("$p is filled.", FALSE, ch,obj,0,TO_CHAR);
}
}
void spell_cure_blind(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
assert(victim);
if (affected_by_spell(victim, SPELL_BLINDNESS)) {
affect_from_char(victim, SPELL_BLINDNESS);
send_to_char("Your vision returns!\n\r", victim);
}
}
void spell_cure_critic(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int healpoints;
assert(victim);
if(IS_NPC(ch))
healpoints = GET_MAX_HIT(ch) / 100;
else
healpoints = 20+((level*level)>>7);
if ( (healpoints + GET_HIT(victim)) > hit_limit(victim) )
GET_HIT(victim) = hit_limit(victim);
else
GET_HIT(victim) += healpoints;
send_to_char("You feel better!\n\r", victim);
update_pos(victim);
}
void spell_cure_light(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int healpoints;
assert(ch && victim);
healpoints = dice(1,8)+3;
if ( (healpoints+GET_HIT(victim)) > hit_limit(victim) )
GET_HIT(victim) = hit_limit(victim);
else
GET_HIT(victim) += healpoints;
update_pos( victim );
send_to_char("You feel better!\n\r", victim);
}
void spell_curse(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim || obj);
if (obj) {
SET_BIT(obj->obj_flags.extra_flags, ITEM_HUM);
SET_BIT(obj->obj_flags.extra_flags, ITEM_NODROP);
if(obj->obj_flags.type_flag == ITEM_WEAPON){
if(obj->obj_flags.value[2] > 0)
obj->obj_flags.value[2]--;
else
obj->obj_flags.value[2]=0;
}
act("$p glows red.", FALSE, ch, obj, 0, TO_CHAR);
} else {
if ( saves_spell(victim, SAVING_SPELL) ||
affected_by_spell(victim, SPELL_CURSE))
return;
af.type = SPELL_CURSE;
af.duration = 24*7; /* 7 Days */
af.modifier = -(1+(level>>6));
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);
if (!affected_by_spell(victim, SPELL_HOLDALIGN))
GET_ALIGNMENT(victim) = (-1000);
act("$n briefly reveals a red aura!", FALSE, victim, 0, 0, TO_ROOM);
act("You feel very uncomfortable.",FALSE,victim,0,0,TO_CHAR);
}
}
void spell_detect_invisibility(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim);
if ( affected_by_spell(victim, SPELL_DETECT_INVISIBLE) )
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);
send_to_char("Your eyes tingle.\n\r", victim);
}
void spell_infravision(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim);
if ( affected_by_spell(victim, SPELL_INFRAVISION) )
return;
af.type = SPELL_INFRAVISION;
af.duration = level*3;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_INFRAVISION;
affect_to_char(victim, &af);
send_to_char("Your eyes glow red.\n\r", victim);
}
static char *colors[]={
"green", "blue", "red", "pink", "purple", "red", "yellow", "orange"
};
static char *awes[]={
"amazed", "awestruck", "astounded", "impressed", "inspired"
};
void spell_kerplunk(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
char buf[MAX_STRING_LENGTH];
int n;
if((!victim) || (ch==victim)){
sprintf(buf,"A huge %s cloud envelops $n. You have witnessed a miracle.",
colors[number(0,7)]);
act(buf, TRUE,ch,0,0,TO_ROOM);
act("You do some really cool magical stuff, impressing everyone in the room.",
TRUE,ch,0,0,TO_CHAR);
} else {
sprintf(buf,"$n creates a large %s cloud, which envelops $N. You are %s.",
colors[n=number(0,7)],awes[number(0,4)]);
act(buf,TRUE,ch,0,victim,TO_NOTVICT);
sprintf(buf,"$n does something magical to you. You feel %s.",
colors[n]);
act(buf,TRUE,ch,0,victim,TO_VICT);
act("You do some really cool magical stuff to $N.",TRUE,ch,0,victim,TO_CHAR);
}
}
#define N_ENCH_LOCS 11
int enchant_locs[]={1,2,3,4,5,12,13,14,17,18,19};
void spell_enchant(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int i;
assert(ch && obj);
if(!IS_SET(obj->obj_flags.extra_flags,ITEM_MAGIC)){
for (i=0; i < MAX_OBJ_AFFECT; i++){
if (obj->affected[i].location == APPLY_NONE){
obj->affected[i].location = enchant_locs[number(0,N_ENCH_LOCS-1)];
obj->affected[i].modifier = 1+number(0,level/100);
if(IS_GOOD(ch)) {
SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_EVIL);
act("$p smells a little funny.",FALSE,ch,obj,0,TO_CHAR);
} else if (IS_EVIL(ch)) {
SET_BIT(obj->obj_flags.extra_flags, ITEM_ANTI_GOOD);
act("$p makes a tinkling sound.",FALSE,ch,obj,0,TO_CHAR);
} else {
act("$p flashes brightly.",FALSE,ch,obj,0,TO_CHAR);
}
if(number(1,10)==3){
act("$p emits an acrid smoke.",FALSE,ch,obj,0,TO_CHAR);
SET_BIT(obj->obj_flags.extra_flags, ITEM_MAGIC);
}
return;
}
}
} else {
act("$p is already magical.",TRUE,ch,obj,0,TO_CHAR);
}
}
void spell_heal(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int boost;
assert(victim);
spell_cure_blind(level, ch, victim, obj);
if(number(0,99) < 10)
spell_remove_poison(level, ch, victim, obj);
if(level<=30)
boost = 100;
else if(level <= 70)
boost = 600;
else if(level <= 150)
boost = 1200;
else if(level <= 225)
boost = 3600;
else if(level <= 300)
boost = 10000;
else if(level <= 500)
boost = 50000;
else
boost = 90000;
GET_HIT(victim) += boost;
if(GET_HIT(victim) >= hit_limit(victim))
GET_HIT(victim) = hit_limit(victim);
update_pos( victim );
if(number(1,10)==7)
send_to_char("A warm body fills your feeling.\n\r", victim);
else
send_to_char("A warm feeling fills your body.\n\r", victim);
}
void spell_groupheal(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct char_data *k;
struct follow_type *f;
if(!IS_AFFECTED(ch,AFF_GROUP)){
send_to_char("You don't belong to a group!\n\r", ch);
return;
}
if(ch->master)
k = ch->master;
else
k = ch;
if(IS_AFFECTED(k,AFF_GROUP))
spell_heal(70,ch,k,obj);
for(f=k->followers; f; f=f->next)
if(IS_AFFECTED(f->follower,AFF_GROUP))
spell_heal(70,ch,f->follower,obj);
send_to_char("Nice work, Doc.\n\r",ch);
}
void spell_transmogrification(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
assert(victim);
if(GET_MOVE(victim) < 0)
return;
GET_HIT(victim) += GET_MOVE(victim);
GET_MOVE(victim) = 0;
if (GET_HIT(victim) >= hit_limit(victim))
GET_HIT(victim) = hit_limit(victim)-dice(1,3);
update_pos( victim );
send_to_char("You are transmogrified.\n\r", victim);
}
void spell_oesophagostenosis(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
assert(victim);
if(GET_MOVE(victim) < 0)
return;
GET_MANA(victim) += GET_MOVE(victim);
GET_MOVE(victim) = 0;
if (GET_MANA(victim) >= mana_limit(victim))
GET_MANA(victim) = mana_limit(victim)-dice(1,3);
send_to_char("You are oesophagostenated.\n\r", victim);
}
void spell_invisibility(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert((ch && obj) || victim);
if (obj) {
if(obj_index[obj->item_number].virtual == 1000)
return;
if( !IS_SET(obj->obj_flags.extra_flags, ITEM_INVISIBLE) ) {
act("$p turns invisible.",FALSE,ch,obj,0,TO_CHAR);
act("$p turns invisible.",TRUE,ch,obj,0,TO_ROOM);
SET_BIT(obj->obj_flags.extra_flags, ITEM_INVISIBLE);
} else {
act("$p turns visible.",FALSE,ch,obj,0,TO_CHAR);
act("$p turns visible.",TRUE,ch,obj,0,TO_ROOM);
REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_INVISIBLE);
}
} else {
if (!affected_by_spell(victim, SPELL_INVISIBLE)) {
act("$n slowly fade out of existence.", TRUE, victim,0,0,TO_ROOM);
send_to_char("You vanish.\n\r", victim);
af.type = SPELL_INVISIBLE;
af.duration = 24;
af.modifier = 10;
af.location = APPLY_AC;
af.bitvector = AFF_INVISIBLE;
affect_to_char(victim, &af);
}
}
}
void spell_stupidity(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int t;
struct affected_type af;
assert(victim || obj);
if (victim) {
if(IS_AFFECTED(victim,AFF_STUPIDITY))
return;
if(!IS_NPC(ch) && !IS_NPC(victim) && (GET_LEVEL(ch) < IMO))
victim=ch;
if((level > IMO) || (!saves_spell(victim, SAVING_PARA))){
af.type = SPELL_STUPIDITY;
t = (level>>5);
af.duration = number(2,level);
af.modifier = (-t);
af.location = APPLY_INT;
af.bitvector = AFF_STUPIDITY;
affect_join(victim, &af, FALSE, FALSE);
send_to_char("You feel very stupid.\n\r", victim);
}
}
}
void spell_poison(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int s,t;
struct affected_type af;
assert(victim || obj);
if (victim) {
if (IS_AFFECTED(victim, AFF_POISON))
return;
if(!IS_NPC(ch) && !IS_NPC(victim) && (GET_LEVEL(ch) < IMO))
victim=ch;
s = GET_STR(victim);
if((level > IMO) || (!saves_spell(victim, SAVING_PARA))){
af.type = SPELL_POISON;
t = 2+level/100;
af.duration = 10+t;
af.modifier = (s > t) ? (-t) : (-s);
af.location = APPLY_STR;
af.bitvector = AFF_POISON;
affect_join(victim, &af, FALSE, FALSE);
send_to_char("You feel very sick.\n\r", victim);
}
} else { /* Object poison */
if(obj_index[obj->item_number].virtual == 1000){
if(GET_LEVEL(ch) < IMO)
raw_kill(ch);
return;
}
if ((obj->obj_flags.type_flag == ITEM_DRINKCON) ||
(obj->obj_flags.type_flag == ITEM_FOOD)) {
obj->obj_flags.value[3] = 1;
}
}
}
void spell_regen(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
if(IS_NPC(victim)) return;
if (!affected_by_spell(victim, SPELL_REGEN) ) {
assert(victim);
af.type = SPELL_REGEN;
af.duration = level*2;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_REGEN;
affect_join(victim, &af, FALSE, FALSE);
send_to_char("You feel energized.\n\r", victim);
}
}
void spell_hyperregen(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
if(IS_NPC(victim)) return;
if (!affected_by_spell(victim, SPELL_HYPERREGEN) ) {
assert(victim);
af.type = SPELL_HYPERREGEN;
af.duration = level;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_HYPERREGEN;
affect_join(victim, &af, FALSE, FALSE);
send_to_char("You feel damn good!\n\r", victim);
}
}
void spell_farsee(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim);
af.type = SPELL_FARSEE;
af.duration = level*2;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_FARSEE;
affect_join(victim, &af, FALSE, FALSE);
send_to_char("You are less myopic.\n\r", victim);
}
void spell_protection_from_evil(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim);
if (!affected_by_spell(victim, SPELL_PROTECT_FROM_EVIL) ) {
af.type = SPELL_PROTECT_FROM_EVIL;
af.duration = 12;
af.modifier = 1;
af.location = APPLY_CON;
af.bitvector = AFF_PROTECT_EVIL;
affect_to_char(victim, &af);
send_to_char("You have a righteous feeling!\n\r", victim);
}
}
void spell_remove_curse(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(ch && (victim || obj));
if (obj) {
if(IS_SET(obj->obj_flags.extra_flags, ITEM_NODROP)){
act("$p briefly glows blue.", TRUE, ch, obj, 0, TO_CHAR);
REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_NODROP);
}
} else { /* Then it is a PC | NPC */
if (affected_by_spell(victim, SPELL_CURSE) ) {
act("$n briefly glows red, then blue.",FALSE,victim,0,0,TO_ROOM);
act("You feel better.",FALSE,victim,0,0,TO_CHAR);
affect_from_char(victim, SPELL_CURSE);
}
}
}
void spell_remove_poison(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type *hjp;
int rpvalue;
assert(ch && (victim || obj));
if (victim) {
if(affected_by_spell(victim,SPELL_POISON)) {
rpvalue=(level>>3);
for(hjp = victim->affected; hjp; hjp = hjp->next)
if (hjp->type == SPELL_POISON){
if(hjp->duration > rpvalue){
hjp->duration-=rpvalue;
act("You feel somewhat better.",FALSE,victim,0,0,TO_CHAR);
act("$N looks somewhat better.",FALSE,ch,0,victim,TO_ROOM);
return;
}
break;
}
affect_from_char(victim,SPELL_POISON);
act("A warm feeling runs through your body.",FALSE,victim,0,0,TO_CHAR);
act("$N looks better.",FALSE,ch,0,victim,TO_ROOM);
}
} else {
if ((obj->obj_flags.type_flag == ITEM_DRINKCON) ||
(obj->obj_flags.type_flag == ITEM_FOOD)) {
obj->obj_flags.value[3] = 0;
act("The $p steams briefly.",FALSE,ch,obj,0,TO_CHAR);
}
}
}
void spell_forgetfulness(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
assert(ch && victim && !obj);
if(IS_SET(world[ch->in_room].room_flags,LAWFUL))
return;
if(!IS_NPC(victim))
return;
if(saves_spell(victim, SAVING_PARA) && number(0,6)){
act("$N resists your spell.",FALSE,ch,0,victim,TO_CHAR);
hit(victim,ch,TYPE_UNDEFINED);
return;
}
if(victim->player.title){
free(victim->player.title);
victim->player.title = 0;
}
victim->specials.lastback = 0;
act("$N looks a little goofy.",FALSE,ch,0,victim,TO_ROOM);
}
void spell_sanctuary(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
if(IS_NPC(victim)) return;
if (!affected_by_spell(victim, SPELL_SANCTUARY) ) {
act("$n is surrounded by a white aura.",TRUE,victim,0,0,TO_ROOM);
act("You start glowing.",TRUE,victim,0,0,TO_CHAR);
af.type = SPELL_SANCTUARY;
af.duration = (level < 30) ? 3 : 3+(level-30);
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_SANCTUARY;
affect_to_char(victim, &af);
}
}
void spell_holdalign(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
if(IS_NPC(victim)) return;
if (!affected_by_spell(victim, SPELL_HOLDALIGN) ) {
act("$n looks like a complete idiot.",TRUE,victim,0,0,TO_ROOM);
act("You feel like an idiot.",TRUE,victim,0,0,TO_CHAR);
af.type = SPELL_HOLDALIGN;
af.duration = 24;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_HOLDALIGN;
affect_to_char(victim, &af);
}
}
void spell_clarity(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
if(IS_NPC(victim)) return;
if (!affected_by_spell(victim, SPELL_CLARITY) ) {
act("$n seems more purposeful.",TRUE,victim,0,0,TO_ROOM);
act("You feel focused.",TRUE,victim,0,0,TO_CHAR);
af.type = SPELL_CLARITY;
af.duration = (level < 100) ? 3 : 168;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_CLARITY;
affect_to_char(victim, &af);
}
}
void spell_sleep(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim);
if(IS_NPC(victim))
if(number(1,level) <= GET_LEVEL(victim))
return;
if((GET_LEVEL(ch) < IMO) && (ch != victim) && (!IS_NPC(ch)) &&
(!IS_NPC(victim))){
return;
}
if((GET_LEVEL(ch) < IMO)&&(GET_LEVEL(victim) > IMO)){
victim = ch;
send_to_char("Oh oh...\n\n",ch);
}
if((level > IMO) || (!saves_spell(victim, SAVING_PARA))) {
af.type = SPELL_SLEEP;
af.duration = number(1,4);
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_SLEEP;
affect_join(victim, &af, FALSE, FALSE);
if (GET_POS(victim)>POSITION_SLEEPING) {
act("You feel very sleepy ..... zzzzzz",FALSE,victim,0,0,TO_CHAR);
act("$n goes to sleep.",TRUE,victim,0,0,TO_ROOM);
GET_POS(victim)=POSITION_SLEEPING;
}
return;
} else if (IS_NPC(victim) && !IS_NPC(ch)) {
act("$n is very angry!",TRUE,victim,0,0,TO_ROOM);
hit(victim,ch,TYPE_UNDEFINED);
}
}
void spell_strength(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af, *afp;
int m,flag;
assert(victim);
if(IS_AFFECTED(victim, AFF_POISON)){
send_to_char("You lose your concentration!\n\r",ch);
return;
}
flag=0;
if(victim->affected) {
for(afp = victim->affected; afp; afp = afp->next)
if(afp->type==SPELL_STRENGTH){
flag=1; break;
}
}
if(flag)
m=number(-1,1);
else
m=1+(GET_INT(ch)+level)/10;
act("You feel stronger.",FALSE,victim,0,0,TO_CHAR);
af.type = SPELL_STRENGTH;
af.duration = level;
af.modifier = (m > 127) ? 127 : m;
af.location = APPLY_STR;
af.bitvector = 0;
affect_join(victim, &af, TRUE, FALSE);
}
void spell_fearlessness(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
if(IS_NPC(victim)) return;
if (!affected_by_spell(victim, SPELL_FEARLESSNESS) ) {
act("$n looks rather heroic!",TRUE,victim,0,0,TO_ROOM);
act("You feel heroic.",TRUE,victim,0,0,TO_CHAR);
af.type = SPELL_FEARLESSNESS;
af.duration = 2;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_FEARLESSNESS;
affect_to_char(victim, &af);
}
}
void spell_word_of_recall(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct char_data *mnt;
extern int top_of_world;
int loc_nr,tmp_loc;
static int location=0;
bool found = FALSE;
assert(victim);
if(ch != victim){
if(IS_NPC(victim)) return;
if(IS_SET(victim->specials.act,PLR_NOSUMMON)) return;
}
if(((GET_LEVEL(ch) < IMO) && (GET_LEVEL(victim) >= IMO)) ||
IS_SET(world[victim->in_room].room_flags,NO_MAGIC))
return;
if((ch!=victim) && (GET_POS(victim)==POSITION_FIGHTING) &&
(victim->desc) && (victim->desc->wait))
return;
if((level < IMO) && victim->specials.fighting &&
IS_AFFECTED(victim,AFF_HOLD)){
act("The power of $N negates the recall spell!",
FALSE,victim,0,victim->specials.fighting,TO_CHAR);
return;
}
if(victim->specials.recall_room){
tmp_loc=victim->specials.recall_room;
if(ch->in_room == tmp_loc){
send_to_char("You're already there!\n\r",ch);
WAIT_STATE(ch,PULSE_VIOLENCE);
return;
}
} else {
if(!location){
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) {
send_to_char("You are completely lost.\n\r", victim);
location=0;
return;
}
}
tmp_loc=location;
}
/* a location has been found. */
act("$n disappears.", TRUE, victim, 0, 0, TO_ROOM);
char_from_room(victim);
char_to_room(victim, tmp_loc);
act("$n appears in the middle of the room.", TRUE, victim, 0, 0, TO_ROOM);
do_look(victim, "",15);
victim->points.move=MAX((victim->points.move - 50) , 0 );
}
void spell_summon(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
sh_int target;
struct char_data *cons;
assert(ch && victim);
if(IS_NPC(victim)){
if(IS_AFFECTED(victim,AFF_NOSUMMON)){
send_to_char("You are a pathetic fool.\n\r",ch);
return;
}
if((2*GET_LEVEL(victim)) >= GET_LEVEL(ch)){
send_to_char("You failed.\n\r",ch);
return;
}
if(IS_SET(victim->specials.act,ACT_SPEC)){
send_to_char("You stink!\n\r",ch);
return;
}
if(GET_POS(victim)==POSITION_FIGHTING){
act("$n is busy now, sorry.",TRUE,victim,0,ch,TO_VICT);
return;
}
if(IS_AFFECTED(victim,AFF_CHARM)&&(victim->master != ch)){
act("$n is a loyal follower.",TRUE,victim,0,ch,TO_VICT);
return;
}
} else {
if(!victim->desc){
send_to_char("Sorry, your target is in limbo.\n\r",ch);
return;
}
if(level < GET_LEVEL(victim)){
send_to_char("You are too humble a soul.\n\r",ch);
return;
}
if((level < (IMO+1)) && IS_SET(victim->specials.act,PLR_NOSUMMON)){
send_to_char("Sorry.\n\r",ch);
return;
}
}
if(GET_LEVEL(ch) < (IMO+1)){
if(IS_SET(world[victim->in_room].room_flags,NOSUMMON)){
send_to_char("You nearly succeed, but not quite.\n\r",ch);
return;
}
if(IS_SET(world[ch->in_room].room_flags,NOSUMMON)){
send_to_char("Alas. No luck.\n\r",ch);
return;
}
}
if(!IS_NPC(ch)){
for(cons=world[ch->in_room].people; cons; cons = cons->next_in_room )
if(IS_NPC(cons) && IS_SET(cons->specials.act,ACT_AGGRESSIVE)){
send_to_char("You failed.\n\r", ch);
return;
}
}
if (IS_NPC(victim) && saves_spell(victim, SAVING_SPELL) ) {
send_to_char("You failed.\n\r", ch);
return;
}
if((!IS_NPC(victim))&&(GET_POS(victim)==POSITION_FIGHTING)&&number(0,2)){
send_to_char("You lost your concentration!\n\r",ch);
return;
}
if(IS_SET(victim->specials.act,ACT_AGGRESSIVE))
REMOVE_BIT(victim->specials.act,ACT_AGGRESSIVE);
act("$n disappears suddenly.",TRUE,victim,0,0,TO_ROOM);
target = ch->in_room;
char_from_room(victim);
char_to_room(victim,target);
act("$n arrives suddenly.",TRUE,victim,0,0,TO_ROOM);
act("$n has summoned you!",FALSE,ch,0,victim,TO_VICT);
do_look(victim,"",15);
}
void spell_charm_person(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct follow_type *j,*jt;
int k;
struct char_data *tmp;
struct affected_type af;
int maxcharmlevel;
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((GET_LEVEL(ch) < IMO) && (ch != victim) && (!IS_NPC(ch)) &&
(!IS_NPC(victim)) && (GET_LEVEL(victim) < IMO)){
return;
}
if (victim == ch) {
send_to_char("You like yourself even better!\n\r", ch);
return;
}
if (!IS_AFFECTED(victim, AFF_CHARM) && !IS_AFFECTED(ch, AFF_CHARM)){
if (circle_follow(victim, ch)) {
send_to_char("Sorry, following in circles can not be allowed.\n\r", ch);
return;
}
if(level > IMO)
maxcharmlevel = GET_LEVEL(ch)-1;
else
maxcharmlevel=(level < 55) ? 20 : 20+(level-50)/5;
if(GET_LEVEL(victim) > maxcharmlevel){
send_to_char("You fail miserably.\n\r",ch);
return;
}
if (victim->master)
stop_follower(victim);
if(level <= IMO)
if (saves_spell(victim, SAVING_PARA)){
if (IS_NPC(victim) && !IS_NPC(ch)) {
act("$n is very angry!",TRUE,victim,0,0,TO_ROOM);
hit(victim,ch,TYPE_UNDEFINED);
}
return;
}
if(IS_NPC(victim) && IS_SET(victim->specials.act,ACT_AGGRESSIVE)){
REMOVE_BIT(victim->specials.act,ACT_AGGRESSIVE);
act("$n seems calmer now.",FALSE,victim,0,0,TO_ROOM);
return;
}
k=0;
for(j=ch->followers;j;j=jt){
jt=j->next;
k++;
}
if(number(1,4) < k){
send_to_char("You fail MISERABLY.\n\r",ch);
return;
}
if(victim->specials.act & ACT_SPEC)
REMOVE_BIT(victim->specials.act, ACT_SPEC);
add_follower(victim, ch);
af.type = SPELL_CHARM_PERSON;
af.duration = 25-GET_LEVEL(victim)/2;
af.modifier = 0;
af.location = 0;
af.bitvector = AFF_CHARM;
affect_to_char(victim, &af);
act("Isn't $n just such a nice fellow?",FALSE,ch,0,victim,TO_VICT);
}
}
void spell_sense_life(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
assert(victim);
if (!affected_by_spell(victim, SPELL_SENSE_LIFE)) {
send_to_char("Your feel your awareness improve.\n\r", 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);
}
}
#define REAL 0
#define VIRTUAL 1
void spell_reanimate(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct char_data *mob;
struct follow_type *j,*jt;
int k;
struct char_data *read_mobile(int nr, int type);
if(!obj)
return;
if(obj->obj_flags.value[3] != 1){
send_to_char("There do not appear to be any corpses hereabouts?\n\r",ch);
return;
}
if(dice(9,9) > ch->skills[SPELL_REANIMATE].learned){
send_to_char("The spell fails miserably.\n\r",ch);
return;
}
k=0;
for(j=ch->followers;j;j=jt){
jt=j->next;
k++;
}
if(number(1,8) < k){
send_to_char("The spell fails MISERABLY.\n\r",ch);
return;
}
extract_obj(obj);
mob=read_mobile(2, VIRTUAL);
char_to_room(mob,ch->in_room);
act("$n has created a zombie!",TRUE,ch,0,0,TO_ROOM);
send_to_char("You have created a zombie.\n\r",ch);
add_follower(mob,ch);
mob->points.max_hit+=GET_LEVEL(ch);
mob->points.hit=mob->points.max_hit;
mob->player.title=(char *)strdup(GET_NAME(ch));
}
void spell_clone(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct char_data *mob,*tmp;
struct char_data *read_mobile(int nr, int type);
char buf[256];
int f,n;
if(obj){
if(GET_LEVEL(ch) > (IMO-100)){
if(GET_ITEM_TYPE(obj)==0){
obj_from_char(obj);
extract_obj(obj);
obj=read_object(17024,VIRTUAL);
obj_to_char(obj,ch);
act("$n has created $o!",TRUE,ch,obj,0,TO_ROOM);
act("You have created $o!",TRUE,ch,obj,0,TO_CHAR);
} else {
act("$n tried to clone $o. What a fool!",TRUE,ch,obj,0,TO_ROOM);
act("You try to clone $o, you fool.",TRUE,ch,obj,0,TO_CHAR);
}
return;
}
send_to_char("Cloning objects may not YET be possible??\n\r",ch);
return;
}
if(!victim){
send_to_char("Clone who?\n\r",ch);
return;
}
if(dice(5,30) > ch->skills[SPELL_CLONE].learned){
send_to_char("You fail, but not by much.\n\r",ch);
return;
}
if(IS_SET(victim->specials.act,ACT_CLONE)){
send_to_char("You are a knave and a fool.\n\r",ch);
return;
}
if(IS_NPC(victim) && (GET_LEVEL(victim) <= (level/4))){
mob=read_mobile(victim->nr, REAL);
char_to_room(mob,ch->in_room);
f = (mob->specials.act & 1);
GET_EXP(mob) = GET_EXP(victim);
sprintf(buf,"%s has been cloned!\n\r",
victim->player.short_descr);
send_to_room(buf,ch->in_room);
victim->specials.act |= ACT_CLONE;
mob->specials.act = ACT_ISNPC | ACT_CLONE;;
GET_GOLD(mob) = 0;
} else {
send_to_char("You may not clone THAT!\n\r",ch);
}
}
/* ***************************************************************************
* NPC spells.. *
* ************************************************************************* */
void spell_fire_breath(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
int hpch;
struct obj_data *burn;
assert(victim && ch);
dam = (level*level*level)>>3;
if(saves_spell(victim, SAVING_BREATH) )
dam >>= 1;
damage(ch, victim, dam, SPELL_FIRE_BREATH);
/* And now for the damage on inventory */
if(!saves_spell(victim,SAVING_BREATH)) {
for(burn=victim->carrying ; burn ; burn=burn->next_content){
if(number(1,7) == 3){
if((burn->obj_flags.type_flag==ITEM_CONTAINER)&&
(IS_SET(burn->obj_flags.extra_flags,ITEM_SFX)))
continue;
else {
act("$o burns",0,victim,burn,0,TO_CHAR);
obj_from_char(burn);
extract_obj(burn);
return;
}
}
}
}
}
void spell_frost_breath(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
int hpch;
struct obj_data *frozen;
assert(victim && ch);
dam = level*level;
if ( saves_spell(victim, SAVING_BREATH) )
dam >>= 1;
damage(ch, victim, dam, SPELL_FROST_BREATH);
if (!saves_spell(victim, SAVING_BREATH)){
for(frozen=victim->carrying ;
frozen && (frozen->obj_flags.type_flag!=ITEM_DRINKCON) &&
(frozen->obj_flags.type_flag!=ITEM_PILL) &&
(frozen->obj_flags.type_flag!=ITEM_POTION);
frozen=frozen->next_content);
if(frozen) {
act("$o breaks.",0,victim,frozen,0,TO_CHAR);
extract_obj(frozen);
}
if(IS_SET(world[victim->in_room].room_flags,DARK))
if(frozen=victim->equipment[WEAR_LIGHT]){
if(frozen->obj_flags.value[2]){
world[victim->in_room].light--;
frozen->obj_flags.value[2]=0;
act("$o is extinguished.",0,victim,frozen,0,TO_CHAR);
}
}
}
}
void spell_gas_breath(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
int hpch;
assert(victim && ch);
dam = level*level;
if ( saves_spell(victim, SAVING_BREATH) )
dam >>= 1;
damage(ch, victim, dam, SPELL_GAS_BREATH);
}
void spell_lightning_breath(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam;
int hpch;
assert(victim && ch);
dam = level*level;
if ( saves_spell(victim, SAVING_BREATH) )
dam >>= 1;
damage(ch, victim, dam, SPELL_LIGHTNING_BREATH);
}
void spell_super_heal(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
assert(victim);
spell_cure_blind(level, ch, victim, obj);
spell_remove_poison(level, ch, victim, obj);
GET_HIT(victim) = hit_limit(victim);
update_pos( victim );
send_to_char("You feel a prickly sensation.\n\r", victim);
}
static int maxmanaheal[]={100,500,2500,12500,62500};
static char *breezename[]={"slight","cool","warm","refreshing","brisk"};
void spell_manaheal(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int hv;
char buf[256];
assert(victim);
if((level < 1)||(level > 5))
return;
hv=maxmanaheal[level-1];
if(GET_MANA(victim) < (GET_MAX_MANA(victim)-hv))
GET_MANA(victim) += hv;
else
GET_MANA(victim) = GET_MAX_MANA(victim);
sprintf(buf,"You feel a %s breeze.\n\r",breezename[level-1]);
send_to_char(buf,victim);
}
void spell_moveheal(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
assert(victim);
GET_MOVE(victim) = GET_MAX_MOVE(victim);
send_to_char("You feel light on your feet.\n\r", victim);
}
void spell_greenman(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int num;
struct char_data *tmp;
assert(victim);
num = real_mobile(2450); /* 2450 = Little Green Man */
if(num > 0){
tmp=read_mobile(num,REAL);
char_to_room(tmp,victim->in_room);
act("You think you see $n.",TRUE,tmp,0,victim,TO_VICT);
spell_charm_person(IMO+1,tmp,victim,0);
}
}
void spell_earthquake(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int dam, halfdam;
struct char_data *tmp, *tmp2;
assert(ch);
dam = dice(1,3)*level;
halfdam = dam>>1;
send_to_char("The earth trembles beneath your feet!\n\r", ch);
act("$n makes the earth tremble and shiver\n\rYou fall, and hit yourself!",
FALSE, ch, 0, 0, TO_ROOM);
for(tmp = character_list; tmp; tmp = tmp2) {
tmp2 = tmp->next;
if(!IS_NPC(tmp)){
if(GET_LEVEL(tmp) > IMO) continue;
if(GET_LEVEL(tmp) < (level>>2)) continue;
}
if((GET_LEVEL(tmp) >= IMO)||(IS_NPC(tmp)==IS_NPC(ch))) continue;
if ( (ch->in_room == tmp->in_room) && (ch != tmp) ) {
damage(ch,tmp,GET_LEVEL(tmp) < 250 ? dam : halfdam,SPELL_EARTHQUAKE);
} else {
if (world[ch->in_room].zone == world[tmp->in_room].zone)
send_to_char("The earth trembles and shivers.\n\r", tmp);
}
}
}
void spell_radiation(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int idam,dam,n=0;
struct char_data *vict, *temp;
struct obj_data *sh;
assert(ch);
if(IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM))
return;
idam = dice((GET_WIS(ch)+GET_INT(ch))/25,level>>1);
act("You fill the room with radiation.",
FALSE, ch, 0, 0, TO_CHAR);
act("$n fills the room with deadly radiation.",
FALSE, ch, 0, 0, TO_ROOM);
for(vict=world[ch->in_room].people;vict;vict=temp){
temp = vict->next_in_room;
if(!IS_NPC(vict) && !(vict->specials.fighting))
continue;
if((GET_LEVEL(vict) >= IMO)||(IS_NPC(vict)==IS_NPC(ch))) continue;
dam = idam;
send_to_char("Sizzle..\n\r",vict);
if(ch != vict){
if(saves_spell(vict,SAVING_ROD))
dam>>=3;
if((sh=vict->equipment[WEAR_SHIELD])&&
(sh->obj_flags.value[1]==SHIELD_RAD)){
dam >>= 2;
act("$N's shield deflects most of the radiation.",
FALSE, ch, 0, vict, TO_NOTVICT);
act("Your shield deflects most of the radiation from $n.",
FALSE, ch, 0, vict, TO_VICT);
} else {
switch(number(0,4)){
case 0: spell_blindness(level,ch,vict,0); break;
case 1: spell_poison(level,ch,vict,0); break;
}
}
damage(ch,vict,dam,SPELL_RADIATION);
n++;
if(n==2){
n=0;
idam>>=1;
}
}
}
}
void spell_cyclone(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int idam,dam,n=0;
struct char_data *vict, *temp;
struct obj_data *sh;
assert(ch);
if(IS_NPC(ch) && IS_AFFECTED(ch,AFF_CHARM))
return;
idam = dice((GET_WIS(ch)+GET_INT(ch))/25,level);
act("You move your hands in a big circle!",
FALSE, ch, 0, 0, TO_CHAR);
act("$n makes a swirling motion.",
FALSE, ch, 0, 0, TO_ROOM);
for(vict=world[ch->in_room].people;vict;vict=temp){
temp = vict->next_in_room;
if(!IS_NPC(vict) && !(vict->specials.fighting))
continue;
if((GET_LEVEL(vict) >= IMO)||(IS_NPC(vict)==IS_NPC(ch))) continue;
dam = idam;
send_to_char("Whoosh..\n\r",vict);
if(ch != vict){
if(saves_spell(vict,SAVING_ROD))
dam>>=2;
if((sh=vict->equipment[WEAR_SHIELD])&&
(sh->obj_flags.value[1]==SHIELD_CYCLONE)){
dam >>= 2;
act("$N's shield reduces the wind velocity.",
FALSE, ch, 0, vict, TO_NOTVICT);
act("Your shield reduces the wind velocity.",
FALSE, ch, 0, vict, TO_VICT);
}
damage(ch,vict,dam,SPELL_CYCLONE);
n++;
if(n==5){
idam/=3; n=0;
}
}
}
}
void spell_invigorate(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type *aff;
void teleport(struct char_data *ch, int to_room);
int delta;
if(IS_NPC(victim))
return;
delta = (level>>4);
if(GET_WIS(ch) > 80)
delta += GET_WIS(ch)-80;
for(aff = victim->affected; aff; aff = aff->next) {
if(!obj && (number(1,101) > ch->skills[SPELL_INVIGORATE].learned)){
send_to_char("Grr..\n\r",ch);
if((ch!=victim) && (number(1,7) < 2))
teleport(ch,0);
return;
} else {
(aff->duration)+=delta;
send_to_char("Ah!\n\r",ch);
}
}
}
void spell_haste(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type af;
if(IS_NPC(victim)) return;
if (!affected_by_spell(victim, SPELL_HASTE) ) {
act("$n starts quivering.",TRUE,victim,0,0,TO_ROOM);
act("You start quivering.",TRUE,victim,0,0,TO_CHAR);
af.type = SPELL_HASTE;
af.duration = 2;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_HASTE;
affect_to_char(victim, &af);
}
}
void spell_dispel_spell(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
struct affected_type *aff;
if(IS_NPC(victim))
return;
aff = victim->affected;
if(!aff)
return;
aff->duration=0;
send_to_char("Patience!\n\r",ch);
}
void spell_drain_mr(short level, struct char_data *ch,
struct char_data *victim, struct obj_data *obj)
{
int hploss,mr;
struct obj_data *sh;
assert(ch);
assert(victim);
if(IS_SET(world[ch->in_room].room_flags,LAWFUL))
return;
if(IS_NPC(ch) || !IS_NPC(victim))
return;
if(victim != ch->specials.fighting){
act("You aren't fighting $N.",FALSE,ch,0,victim,TO_CHAR);
return;
}
if(number(1,GET_LEVEL(ch)+GET_WIS(ch)) < GET_LEVEL(victim)){
act("$N avoids any damage.",
FALSE, ch, 0, victim, TO_ROOM);
return;
}
--(victim->specials.magres);
act("$N's resistance seems to be a little lower.",
FALSE, ch, 0, victim, TO_ROOM);
act("Your spell seems to have had some effect.",
FALSE, ch, 0, victim, TO_CHAR);
}