1stMud4.5.3/
1stMud4.5.3/backup/
1stMud4.5.3/bin/
1stMud4.5.3/bin/extras/
1stMud4.5.3/data/i3/
1stMud4.5.3/doc/1stMud/
1stMud4.5.3/doc/Diku/
1stMud4.5.3/doc/MPDocs/
1stMud4.5.3/doc/Rom/
1stMud4.5.3/notes/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*          1stMud ROM Derivative (c) 2001-2004 by Markanth                *
*            http://www.firstmud.com/  <markanth@firstmud.com>            *
*         By using this code you have agreed to follow the term of        *
*             the 1stMud license in ../doc/1stMud/LICENSE                 *
***************************************************************************/

#include "merc.h"
#include "interp.h"
#include "magic.h"
#include "vnums.h"

EXTERN const char *target_name;

Spell_Fun(spell_farsight)
{
	if (IsAffected(ch, AFF_BLIND))
	{
		chprintln(ch, "Maybe it would help if you could see?");
		return false;
	}

	do_function(ch, &do_scan, target_name);
	return true;
}

Spell_Fun(spell_portal)
{
	CharData *victim;
	ObjData *portal, *stone;

	if ((victim = get_char_world(ch, target_name)) == NULL || victim == ch
		|| victim->in_room == NULL || !can_see_room(ch, victim->in_room)
		|| IsSet(victim->in_room->room_flags, ROOM_SAFE)
		|| IsSet(victim->in_room->room_flags, ROOM_PRIVATE)
		|| IsSet(victim->in_room->room_flags, ROOM_SOLITARY)
		|| IsSet(victim->in_room->area->area_flags, AREA_CLOSED)
		|| IsSet(victim->in_room->room_flags, ROOM_ARENA)
		|| IsSet(ch->in_room->room_flags, ROOM_ARENA)
		|| IsSet(victim->in_room->room_flags, ROOM_NO_RECALL)
		|| IsSet(ch->in_room->room_flags, ROOM_NO_RECALL) || (IsNPC(victim)
															  &&
															  is_gqmob(NULL,
																	   victim->
																	   pIndexData->
																	   vnum)
															  != -1)
		|| (IsNPC(victim) && IsQuester(ch) && ch->pcdata->quest.mob == victim)
		|| victim->level >= level + 3 || (!IsNPC(victim)
										  && victim->level >=
										  MAX_MORTAL_LEVEL) || (IsNPC(victim)
																&&
																IsSet
																(victim->imm_flags,
																 IMM_SUMMON))
		|| (IsNPC(victim) && saves_spell(level, victim, DAM_NONE))
		|| (is_clan(victim) && !is_same_clan(ch, victim)))
	{
		chprintln(ch, "You failed.");
		return false;
	}

	stone = get_eq_char(ch, WEAR_HOLD);
	if (!IsImmortal(ch)
		&& (stone == NULL || stone->item_type != ITEM_WARP_STONE))
	{
		chprintln(ch, "You lack the proper component for this spell.");
		return false;
	}

	if (stone != NULL && stone->item_type == ITEM_WARP_STONE)
	{
		act("You draw upon the power of $p.", ch, stone, NULL, TO_CHAR);
		act("It flares brightly and vanishes!", ch, stone, NULL, TO_CHAR);
		extract_obj(stone);
	}

	portal = create_object(get_obj_index(OBJ_VNUM_PORTAL), 0);
	portal->timer = 2 + level / 25;
	portal->value[3] = victim->in_room->vnum;

	obj_to_room(portal, ch->in_room);

	act("$p rises up from the ground.", ch, portal, NULL, TO_ROOM);
	act("$p rises up before you.", ch, portal, NULL, TO_CHAR);
	return true;
}

Spell_Fun(spell_nexus)
{
	CharData *victim;
	ObjData *portal, *stone;
	RoomIndex *to_room, *from_room;

	from_room = ch->in_room;

	if ((victim = get_char_world(ch, target_name)) == NULL || victim == ch
		|| (to_room = victim->in_room) == NULL || !can_see_room(ch, to_room)
		|| !can_see_room(ch, from_room)
		|| IsSet(to_room->room_flags, ROOM_SAFE)
		|| IsSet(from_room->room_flags, ROOM_SAFE)
		|| IsSet(to_room->room_flags, ROOM_PRIVATE)
		|| IsSet(to_room->room_flags, ROOM_SOLITARY)
		|| IsSet(to_room->room_flags, ROOM_NO_RECALL)
		|| IsSet(from_room->room_flags, ROOM_NO_RECALL)
		|| IsSet(to_room->area->area_flags, AREA_CLOSED)
		|| IsSet(to_room->room_flags, ROOM_ARENA)
		|| IsSet(from_room->room_flags, ROOM_ARENA) || (IsNPC(victim)
														&& is_gqmob(NULL,
																	victim->
																	pIndexData->
																	vnum) !=
														-1) || (IsQuester(ch)
																&& ch->
																pcdata->quest.
																mob == victim)
		|| victim->level >= level + 3 || (!IsNPC(victim)
										  && victim->level >=
										  MAX_MORTAL_LEVEL) || (IsNPC(victim)
																&&
																IsSet
																(victim->imm_flags,
																 IMM_SUMMON))
		|| (IsNPC(victim) && saves_spell(level, victim, DAM_NONE))
		|| (is_clan(victim) && !is_same_clan(ch, victim)))
	{
		chprintln(ch, "You failed.");
		return false;
	}

	stone = get_eq_char(ch, WEAR_HOLD);
	if (!IsImmortal(ch)
		&& (stone == NULL || stone->item_type != ITEM_WARP_STONE))
	{
		chprintln(ch, "You lack the proper component for this spell.");
		return false;
	}

	if (stone != NULL && stone->item_type == ITEM_WARP_STONE)
	{
		act("You draw upon the power of $p.", ch, stone, NULL, TO_CHAR);
		act("It flares brightly and vanishes!", ch, stone, NULL, TO_CHAR);
		extract_obj(stone);
	}

	portal = create_object(get_obj_index(OBJ_VNUM_PORTAL), 0);
	portal->timer = 1 + level / 10;
	portal->value[3] = to_room->vnum;

	obj_to_room(portal, from_room);

	act("$p rises up from the ground.", ch, portal, NULL, TO_ROOM);
	act("$p rises up before you.", ch, portal, NULL, TO_CHAR);

	if (to_room == from_room)
		return true;

	portal = create_object(get_obj_index(OBJ_VNUM_PORTAL), 0);
	portal->timer = 1 + level / 10;
	portal->value[3] = from_room->vnum;

	obj_to_room(portal, to_room);

	if (to_room->person_first != NULL)
	{
		act("$p rises up from the ground.", to_room->person_first, portal,
			NULL, TO_ROOM);
		act("$p rises up from the ground.", to_room->person_first, portal,
			NULL, TO_CHAR);
	}
	return true;
}

Spell_Fun(spell_forceshield)
{
	CharData *victim = (CharData *) vo;
	AffectData af;

	if (is_affected(victim, sn))
	{
		if (victim == ch)
			chprintln(ch, "You are already force-shielded.");
		else
			act("$N is already force-shielded.", ch, NULL, victim, TO_CHAR);
		return false;
	}

	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = level / 4;
	af.location = APPLY_AC;
	af.modifier = (level / 5) * -1;
	af.bitvector = AFF_FORCE_SHIELD;
	affect_to_char(victim, &af);
	act("A sparkling force-shield encircles $n.", victim, NULL, NULL,
		TO_ROOM);
	chprintln(victim, "You are encircled by a sparkling force-shield.");
	return true;
}

Spell_Fun(spell_staticshield)
{
	CharData *victim = (CharData *) vo;
	AffectData af;

	if (is_affected(victim, sn))
	{
		if (victim == ch)
			chprintln(ch, "You are surrounded by static charge.");
		else
			act("$N is already surrounded by static charge.", ch, NULL,
				victim, TO_CHAR);
		return false;
	}

	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = level / 3;
	af.location = APPLY_AC;
	af.modifier = (level / 4) * -1;
	af.bitvector = AFF_STATIC_SHIELD;
	affect_to_char(victim, &af);
	act("$n is surrounded by a pulse of static charge.", victim, NULL, NULL,
		TO_ROOM);
	chprintln(victim, "You are surrounded by a pulse of static charge.");
	return true;
}

Spell_Fun(spell_flameshield)
{
	CharData *victim = (CharData *) vo;
	AffectData af;

	if (is_affected(victim, sn))
	{
		if (victim == ch)
			chprintln(ch, "You are already protected by fire.");
		else
			act("$N is already protected by fire.", ch, NULL, victim,
				TO_CHAR);
		return false;
	}

	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = (level / 10);
	af.location = APPLY_AC;
	af.modifier = (level / 2) * -1;
	af.bitvector = AFF_FLAME_SHIELD;
	affect_to_char(victim, &af);
	act("$n is shielded by red walls of flame.", victim, NULL, NULL, TO_ROOM);
	chprintln(victim, "You are shielded by red walls of flame.");
	return true;
}

Spell_Fun(spell_channel)
{
	CharData *victim = (CharData *) vo;
	int heal;

	heal = dice(3, 3) + (level / 3) * 2;
	if (ch == victim)
	{
		chprintln(ch, "You cannot channel energy into yourself.");
		return false;
	}
	victim->mana = Min(victim->mana + heal, victim->max_mana);
	update_pos(victim);
	chprintln(victim, "A swirling cloud of energy engulfs you!");
	if (ch != victim)
		chprintln(ch,
				  "A swirling cloud of energy slips from your fingertips.");
	return true;
}

Spell_Fun(spell_investiture)
{
	CharData *victim = (CharData *) vo;
	int heal;

	heal = ch->move;
	victim->mana = Min(victim->mana + heal, victim->max_mana);
	victim->move = 0;
	update_pos(victim);
	chprintln(victim, "{cThe forces of the earth fill you with energy!{x");
	act("$n draws magic from the very earth!", ch, NULL, NULL, TO_ROOM);
	return true;
}

Spell_Fun(spell_powerstorm)
{
	CharData *vch;
	CharData *vch_next;
	bool found = false;

	act("$n makes a firey blaze of magic engulf the room!", ch, NULL, NULL,
		TO_ROOM);
	for (vch = char_first; vch != NULL; vch = vch_next)
	{
		vch_next = vch->next;
		if (vch->in_room == NULL)
			continue;
		if (vch->in_room == ch->in_room)
		{
			if (vch != ch && !is_safe_spell(ch, vch, true))
			{
				damage(ch, vch, level / 3 * 2 + dice(20, 20), sn, DAM_FIRE,
					   true);
				found = true;
			}
			continue;
		}
		if (vch->in_room->area == ch->in_room->area)
			found = true;
		chprintln(vch, "A blazing storm of energy rumbles through the area.");
	}
	return found;
}

Spell_Fun(spell_mana_burn)
{
	CharData *victim = (CharData *) vo;
	int dam;

	dam = dice(level, 13);
	if (saves_spell(level, victim, DAM_FIRE))
		dam /= 2;
	fire_effect(victim, level / 2, dam / 10, TARGET_CHAR);
	damage(ch, victim, dam, sn, DAM_FIRE, true);
	return true;
}

Spell_Fun(spell_bark_skin)
{
	CharData *victim = (CharData *) vo;
	AffectData af;

	if (is_affected(victim, sn))
	{
		if (victim == ch)
			chprintln(ch, "Your skin is already covered in bark.");
		else
			act("$N's skin is already bark.", ch, NULL, victim, TO_CHAR);
		return false;
	}
	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = level / 3;
	af.modifier = -30 - level / 5;
	af.location = APPLY_AC;
	af.bitvector = 0;
	affect_to_char(victim, &af);
	chprintln(victim, "Your skin becomes as tough as bark.");
	if (ch != victim)
		act("$N's skin becomes as tough as bark.", ch, NULL, victim, TO_CHAR);
	return true;
}

Spell_Fun(spell_spell_mantle)
{
	CharData *victim = (CharData *) vo;
	AffectData af;

	if (is_affected(victim, sn))
	{
		if (victim == ch)
			chprintln(ch, "You are already protected against magic.");
		else
			act("$N is already protected.", ch, NULL, victim, TO_CHAR);
		return false;
	}
	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = level / 3;
	af.modifier = 1 - level / 6;
	af.location = APPLY_SAVES;
	af.bitvector = 0;
	affect_to_char(victim, &af);
	chprintln(victim, "You are surrounded by a glowing spell mantle.");
	if (ch != victim)
		act("$N is surrounded by a glowing spell mantle.", ch, NULL, victim,
			TO_CHAR);
	return true;
}

Spell_Fun(spell_animal_instinct)
{
	CharData *victim = (CharData *) vo;
	AffectData af;

	if (is_affected(victim, sn))
	{
		if (victim == ch)
			chprintln(ch, "You are already animalistic.");
		else
			act("$N is already animalistic.", ch, NULL, victim, TO_CHAR);
		return false;
	}
	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = level / 2;
	af.modifier = level / 25;
	af.location = APPLY_STR;
	af.bitvector = 0;
	affect_to_char(victim, &af);
	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = level / 2;
	af.modifier = level / 20;
	af.location = APPLY_DAMROLL;
	af.bitvector = 0;
	affect_to_char(victim, &af);
	chprintln(victim, "You suddenly look like a wild beast!");
	if (ch != victim)
		act("$N suddenly grows fangs and claws!", ch, NULL, victim, TO_CHAR);
	return true;

}

Spell_Fun(spell_chaos_flare)
{
	CharData *victim = (CharData *) vo;
	AffectData af;
	int rnum;

	if (is_affected(victim, sn))
	{
		if (victim == ch)
			chprintln(ch, "You are already touched by chaos.");
		else
			act("$N's skin is already touched by chaos.", ch, NULL, victim,
				TO_CHAR);
		return false;
	}
	af.where = TO_AFFECTS;
	af.type = sn;
	af.level = level;
	af.duration = level / 3;
	rnum = number_percent();
	if (rnum <= 5)
	{
		af.modifier = -30 - level / 5;
		af.location = APPLY_AC;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "Glinting scales form over your skin!");
		if (ch != victim)
			act("$N's skin is suddenly covered with metallic scales.", ch,
				NULL, victim, TO_CHAR);
		return true;
	}
	if (rnum <= 15)
	{
		af.modifier = level / 20;
		af.location = APPLY_DAMROLL;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "Sharp spikes jut out of your skin!");
		if (ch != victim)
			act("$N's skin is suddenly covered with jagged spikes.", ch, NULL,
				victim, TO_CHAR);
		return true;
	}
	if (rnum <= 25)
	{
		af.modifier = level / 20;
		af.location = APPLY_HITROLL;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "Your eyes gleam.");
		if (ch != victim)
			act("$N's eyes gleam.", ch, NULL, victim, TO_CHAR);
		return true;
	}
	if (rnum <= 35)
	{
		af.modifier = level * 2;
		af.location = APPLY_MOVE;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "You suddenly grow an extra set of legs!");
		if (ch != victim)
			act("$N suddenly grows an extra set of legs! Yipes!", ch, NULL,
				victim, TO_CHAR);
		return true;
	}
	if (rnum <= 45)
	{
		af.modifier = level / 20;
		af.location = APPLY_CON;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "You grow much tougher!");
		if (ch != victim)
			act("$N seems much tougher all of a sudden.", ch, NULL, victim,
				TO_CHAR);
		return true;
	}
	if (rnum <= 50)
	{
		af.modifier = level / 4;
		af.location = APPLY_DAMROLL;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "{YA blaze of light surrounds you!{x");
		if (ch != victim)
			act("{YA blazing halo surrounds $N!{x", ch, NULL, victim,
				TO_CHAR);
		return true;
	}
	if (rnum <= 65)
	{
		af.modifier = 1 - level / 20;
		af.location = APPLY_DEX;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "One of your arms suddenly turns into a flipper.");
		if (ch != victim)
			act("One of $N's arms turns into a.. dolphin flipper.", ch, NULL,
				victim, TO_CHAR);
		return true;
	}
	if (rnum <= 75)
	{
		af.modifier = 1 - level / 20;
		af.location = APPLY_INT;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "Me say wah? You suddenly feel very stoopid.");
		if (ch != victim)
			act("$N is suddenly looking very stupid.", ch, NULL, victim,
				TO_CHAR);
		return true;
	}
	if (rnum <= 85)
	{
		af.modifier = level * 3;
		af.location = APPLY_HIT;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "You grow two sizes bigger!");
		if (ch != victim)
			act("$N suddenly gets bigger.. and bigger.. and bigger.", ch,
				NULL, victim, TO_CHAR);
		return true;
	}
	if (rnum <= 95)
	{
		af.modifier = 1 + level * 2;
		af.location = APPLY_AC;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim,
				  "You suddenly feel quite vulnerable. They're all out to get you!");
		if (ch != victim)
			act("$N looks might paranoid all of a sudden.", ch, NULL, victim,
				TO_CHAR);
		return true;
	}
	if (rnum <= 100)
	{
		af.modifier = 1 - level;
		af.location = APPLY_DAMROLL;
		af.bitvector = 0;
		affect_to_char(victim, &af);
		chprintln(victim, "{cAck! You turn into an oozing gelatinous blob!");
		if (ch != victim)
			act("{c$N's been turned into a green oozing blob!{c", ch, NULL,
				victim, TO_ROOM);
		return true;
	}

	return true;
}

Spell_Fun(spell_wild_magic)
{
	CharData *victim = (CharData *) vo;
	int dam;
	int numba;

	dam = dice(level * 3 / 2, 14);
	numba = number_percent();
	if (numba <= 10)
	{
		if (saves_spell(level, victim, DAM_ACID))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_ACID, true);
		acid_effect(victim, level, dam, TARGET_CHAR);
		return true;
	}
	if (numba <= 20)
	{
		if (saves_spell(level, victim, DAM_FIRE))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_FIRE, true);
		fire_effect(victim, level, dam, TARGET_CHAR);
		return true;
	}
	if (numba <= 30)
	{
		if (saves_spell(level, victim, DAM_LIGHTNING))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_LIGHTNING, true);
		shock_effect(victim, level, dam, TARGET_CHAR);
		return true;
	}
	if (numba <= 40)
	{
		if (saves_spell(level, victim, DAM_COLD))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_COLD, true);
		cold_effect(victim, level, dam, TARGET_CHAR);
		return true;
	}
	if (numba <= 50)
	{
		if (saves_spell(level, victim, DAM_HOLY))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_HOLY, true);
		return true;
	}
	if (numba <= 60)
	{
		if (saves_spell(level, victim, DAM_LIGHT))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_LIGHT, true);
		return true;
	}
	if (numba <= 70)
	{
		if (saves_spell(level, victim, DAM_DROWNING))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_DROWNING, true);
		return true;
	}
	if (numba <= 80)
	{
		if (saves_spell(level, victim, DAM_DISEASE))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_DISEASE, true);
		return true;
	}
	if (numba <= 90)
	{
		if (saves_spell(level, victim, DAM_SLASH))
			dam /= 2;
		damage(ch, victim, dam, sn, DAM_SLASH, true);
		return true;
	}
	if (numba <= 100)
	{
		if (saves_spell(level, victim, DAM_NEGATIVE))
			dam /= 2;
		dam /= 5;
		damage(ch, victim, dam, sn, DAM_NEGATIVE, true);
		acid_effect(victim, level, dam, TARGET_CHAR);
		fire_effect(victim, level, dam, TARGET_CHAR);
		cold_effect(victim, level, dam, TARGET_CHAR);
		shock_effect(victim, level, dam, TARGET_CHAR);
		return true;
	}
	return true;
}