roh/conf.old/area/
roh/config/code/python/
roh/config/game/area/
roh/config/game/signs/
roh/help/dmhelp/
roh/help/help/
roh/log/
roh/log/staff/
roh/monsters/ocean/
roh/objects/misc/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.47e/
/*
 * abjuration.cpp
 *	 Abjuration spells
 *   ____            _
 *  |  _ \ ___  __ _| |_ __ ___  ___
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 * Permission to use, modify and distribute is granted via the
 *  Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
 *    http://creativecommons.org/licenses/by-nc-sa/3.0/
 *
 * 	Copyright (C) 2007-2012 Jason Mitchell, Randi Mitchell
 * 	   Contributions by Tim Callahan, Jonathan Hseu
 *  Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
 *
 */
#include "mud.h"
#include "math.h"
#include "effects.h"
#include "move.h"


//*********************************************************************
//						protection from room damage spells
//*********************************************************************

int splHeatProtection(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "heat-protection", "heat-protection"));
}
int splEarthShield(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "an", "earth-shield", "earth-shield"));
}
int splBreatheWater(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "breathe-water", "breathe-water"));
}
int splWarmth(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "warmth", "warmth", true));
}
int splWindProtection(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "wind-protection", "wind-protection"));
}
int splStaticField(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "static-field", "static-field"));
}


//*********************************************************************
//						splProtection
//*********************************************************************
// This function allows a spellcaster to cast a protection spell either
// on themself or on another player, improving the armor class by a
// score of 10.

int splProtection(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "protection", "protection"));
}


//*********************************************************************
//						splUndeadWard
//*********************************************************************

int splUndeadWard(Creature* player, cmd* cmnd, SpellData* spellData) {
	if(!player->isCt() && spellData->how == CAST) {
		if(player->getClass() != CLERIC && player->getClass() != PALADIN ) {
			player->print("Only clerics and paladins may cast that spell.\n");
			return(0);
		}
		if(player->getDeity() != ENOCH && player->getDeity() != LINOTHAN && player->getDeity() != CERIS) {
			player->print("%s will not allow you to cast that spell.\n", gConfig->getDeity(player->getDeity())->getName().c_str());
			return(0);
		}
		if(!player->getDeity()) {
			// this should never happen
			player->print("You must belong to a religion to cast that spell.\n");
			return(0);
		}
	}

	return(splGeneric(player, cmnd, spellData, "an", "undead-ward", "undead-ward"));
}

//*********************************************************************
//						splBless
//*********************************************************************
// This function allows a player to cast a bless spell on themself or
// on another player, reducing the target's thaco by 1.

int splBless(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "bless", "bless"));
}

//*********************************************************************
//						splDrainShield
//*********************************************************************

int splDrainShield(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(splGeneric(player, cmnd, spellData, "a", "drain-shield", "drain-shield"));
}

//*********************************************************************
//						reflect magic spells
//*********************************************************************
// The strength of the spell is the chance to reflect

int addReflectMagic(Creature* player, cmd* cmnd, SpellData* spellData, const char* article, const char* spell, int strength, unsigned int level) {
	if(spellData->how == CAST) {
		if(!player->isMageLich())
			return(0);
		if(spellData->level < level) {
			player->print("You are not powerful enough to cast this spell.\n");
			return(0);
		}
	}
	return(splGeneric(player, cmnd, spellData, article, spell, "reflect-magic", strength));
}

int splBounceMagic(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(addReflectMagic(player, cmnd, spellData, "a", "bounce magic", 33, 9));
}
int splReboundMagic(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(addReflectMagic(player, cmnd, spellData, "a", "rebound magic", 66, 16));
}
int splReflectMagic(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(addReflectMagic(player, cmnd, spellData, "a", "reflect-magic", 100, 21));
}

//*********************************************************************
//						splResistMagic
//*********************************************************************
// This function allows players to cast the resist-magic spell. It
// will allow the player to resist magical attacks from monsters

int splResistMagic(Creature* player, cmd* cmnd, SpellData* spellData) {
	int strength=0;

	if(spellData->how == CAST && !player->isStaff()) {
		if(	player->getClass() != MAGE &&
			player->getClass() != LICH
		) {
			player->print("Only mages and liches may cast this spell.\n");
			return(0);
		}
		if(spellData->level < 16) {
			player->print("You are not experienced enough to cast that spell.\n");
			return(0);
		}
	}

	if(spellData->how == CAST)
		strength = spellData->level;

	return(splGeneric(player, cmnd, spellData, "a", "resist-magic", "resist-magic", strength));
}


//*********************************************************************
//						splFreeAction
//*********************************************************************

int splFreeAction(Creature* player, cmd* cmnd, SpellData* spellData) {
	Creature* target=0;
	Player	*pTarget=0;
	long 	t = time(0);

	if(spellData->how != POTION && !player->isCt() && player->getClass() != DRUID && player->getClass() != CLERIC) {
		player->print("Your class is unable to cast that spell.\n");
		return(0);
	}


	if(cmnd->num == 2) {
		target = player;

		if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
			player->print("Free-action spell cast.\nYou can now move freely.\n");
			broadcast(player->getSock(), player->getParent(), "%M casts a free-action spell on %sself.", player, player->himHer());
		} else if(spellData->how == POTION)
			player->print("You can now move freely.\n");

	} else {
		if(player->noPotion( spellData))
			return(0);

		cmnd->str[2][0] = up(cmnd->str[2][0]);

		target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);

		if(!target || (target && target->isMonster())) {
			player->print("You don't see that person here.\n");
			return(0);
		}

		if(checkRefusingMagic(player, target))
			return(0);

		player->print("Free-action cast on %s.\n", target->getCName());
		target->print("%M casts a free-action spell on you.\n%s", player, "You can now move freely.\n");
		broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts a free-action spell on %N.",player, target);
	}

	pTarget = target->getAsPlayer();

	if(pTarget) {
		pTarget->setFlag(P_FREE_ACTION);

		pTarget->lasttime[LT_FREE_ACTION].ltime = t;
		if(spellData->how == CAST) {
			pTarget->lasttime[LT_FREE_ACTION].interval = MAX(300, 900 +
				bonus((int) player->intelligence.getCur()) * 300);

			if(player->getRoomParent()->magicBonus()) {
				pTarget->print("The room's magical properties increase the power of your spell.\n");
				pTarget->lasttime[LT_FREE_ACTION].interval += 300L;
			}
		} else
			pTarget->lasttime[LT_FREE_ACTION].interval = 600;

		pTarget->clearFlag(P_STUNNED);
		pTarget->removeEffect("hold-person");
		pTarget->removeEffect("slow");

		pTarget->computeAC();
		pTarget->computeAttackPower();
	}
	return(1);
}

//*********************************************************************
//						splRemoveFear
//*********************************************************************

int splRemoveFear(Creature* player, cmd* cmnd, SpellData* spellData) {
	Creature* target=0;

	if(cmnd->num == 2) {
		target = player;

		if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {

			player->print("You cast remove-fear on yourself.\n");
			if(player->isEffected("fear"))
				player->print("You feel brave again.\n");
			else
				player->print("Nothing happens.\n");
			broadcast(player->getSock(), player->getParent(), "%M casts remove-fear on %sself.", player, player->himHer());
		} else if(spellData->how == POTION && player->isEffected("fear"))
			player->print("You feel brave again.\n");
		else if(spellData->how == POTION)
			player->print("Nothing happens.\n");

	} else {
		if(player->noPotion( spellData))
			return(0);

		cmnd->str[2][0] = up(cmnd->str[2][0]);
		target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);
		if(!target) {
			player->print("That's not here.\n");
			return(0);
		}


		if(checkRefusingMagic(player, target))
			return(0);


		if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
			player->print("You cast remove-fear on %N.\n", target);
			broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts remove-fear on %N.", player, target);
			if(target->isPlayer()) {
				target->print("%M casts remove-fear on you.\n", player);
				if(target->isEffected("fear"))
					target->print("You feel brave again.\n");
				else
					player->print("Nothing happens.\n");
			}
		}
	}
	if(target->inCombat(false))
		player->smashInvis();

	target->removeEffect("fear", true, false);
	return(1);
}

//*********************************************************************
//						splRemoveSilence
//*********************************************************************

int splRemoveSilence(Creature* player, cmd* cmnd, SpellData* spellData) {
	Creature* target=0;

	if(cmnd->num == 2) {
		target = player;
		if(spellData->how == POTION && player->isEffected("silence") && !player->flagIsSet(P_DM_SILENCED))
			player->print("You can speak again.\n");
		else {
			player->print("Nothing happens.\n");
			return(0);
		}

	} else {
		if(player->noPotion( spellData))
			return(0);

		cmnd->str[2][0] = up(cmnd->str[2][0]);
		target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);

		if(!target) {
			player->print("That's not here.\n");
			return(0);
		}

		if(checkRefusingMagic(player, target))
			return(0);

		if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
			player->print("You cast remove-silence on %N.\n", target);
			broadcast(player->getSock(), target->getSock(), player->getParent(),
				"%M casts remove-silence on %N.", player, target);

			logCast(player, target, "remove-silence");
			if(target->isPlayer()) {
				target->print("%M casts remove-silence on you.\n", player);
				if(	(target->flagIsSet(P_DM_SILENCED) && player->isCt()) ||
					 !target->flagIsSet(P_DM_SILENCED)
				)
					target->print("You can speak again.\n");
				else
					target->print("Nothing happens.\n");
			}
		}
	}
	if(target->inCombat(false))
		player->smashInvis();

	target->removeEffect("silence");

	if(player->isCt() && target->isPlayer())
		target->clearFlag(P_DM_SILENCED);

	return(1);
}

//*********************************************************************
//						splDispelAlign
//*********************************************************************

int splDispelAlign(Creature* player, cmd* cmnd, SpellData* spellData, const char* spell, int align) {
	Creature* target=0;
	Damage damage;


	if((target = player->findMagicVictim(cmnd->str[2], cmnd->val[2], spellData, true, false, "Cast on what?\n", "You don't see that here.\n")) == NULL)
		return(0);

	if(player == target) {
		// mobs can't cast on themselves!
		if(!player->getAsPlayer())
			return(0);

		// turn into a boolean!
		// are they in alignment?
		if(align == PINKISH)
			align = player->getAlignment() <= align;
		else
			align = player->getAlignment() >= align;

		if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND)
			player->print("You cannot cast that spell on yourself.\n");
		else if(spellData->how == POTION && !align)
			player->print("Nothing happens.\n");
		else if(spellData->how == POTION && align) {
			player->smashInvis();

			damage.set(mrand(spellData->level * 2, spellData->level * 4));
			damage.add(MAX(0, bonus((int) player->piety.getCur())));
			player->modifyDamage(player, MAGICAL, damage);

			player->print("You feel as if your soul is savagely ripped apart!\n");
			player->printColor("You take %s%d^x points of damage!\n", player->customColorize("*CC:DAMAGE*").c_str(), damage.get());
			broadcast(player->getSock(), player->getParent(), "%M screams and doubles over in pain!", player);
			player->hp.decrease(damage.get());
			if(player->hp.getCur() < 1) {
				player->print("Your body explodes. You're dead!\n");
				broadcast(player->getSock(), player->getParent(), "%M's body explodes! %s's dead!", player,
						player->upHeShe());
				player->getAsPlayer()->die(EXPLODED);
			}
		}

	} else {
		if(player->spellFail( spellData->how))
			return(0);

		cmnd->str[2][0] = up(cmnd->str[2][0]);
		target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);

		if(!target) {
			player->print("That's not here.\n");
			return(0);
		}

		if(!player->canAttack(target))
			return(0);

		if(	(target->getLevel() > spellData->level + 7) ||
			(!player->isStaff() && target->isStaff())
		) {
			player->print("Your magic would be too weak to harm %N.\n", target);
			return(0);
		}

		player->smashInvis();
		// turn into a boolean!
		// are they in alignment?
		if(align == PINKISH)
			align = target->getAlignment() <= align;
		else
			align = target->getAlignment() >= align;



		if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
			player->print("You cast %s on %N.\n", spell, target);
			broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts a %s spell on %N.", player, spell, target);

			if(target->getAsPlayer()) {
				target->wake("Terrible nightmares disturb your sleep!");
				target->print("%M casts a %s spell on you.\n", player, spell);
			}

			if(!align) {
				player->print("Nothing happens.\n");
			} else {
				damage.set(mrand(spellData->level * 2, spellData->level * 4));
				damage.add(abs(player->getAlignment()/100));
				damage.add(MAX(0, bonus((int) player->piety.getCur())));
				target->modifyDamage(player, MAGICAL, damage);

				if(target->chkSave(SPL, player,0))
					damage.set(damage.get() / 2);

				player->printColor("The spell did %s%d^x damage.\n", player->customColorize("*CC:DAMAGE*").c_str(), damage.get());
				player->print("%M screams in agony as %s soul is ripped apart!\n",
					target, target->hisHer());
				target->printColor("You take %s%d^x points of damage as your soul is ripped apart!\n", target->customColorize("*CC:DAMAGE*").c_str(), damage.get());
				broadcastGroup(false, target, "%M cast a %s spell on ^M%N^x for *CC:DAMAGE*%d^x damage, %s%s\n",
					player, spell, target, damage.get(), target->heShe(), target->getStatusStr(damage.get()));

				broadcast(player->getSock(), target->getSock(), player->getParent(), "%M screams and doubles over in pain!", target);

				// if the target is reflecting magic, force printing a message (it will say 0 damage)
				player->doReflectionDamage(damage, target, target->isEffected("reflect-magic") ? REFLECTED_MAGIC : REFLECTED_NONE);

				if(spellData->how == CAST && player->isPlayer())
					player->getAsPlayer()->statistics.offensiveCast();

				player->doDamage(target, damage.get(), NO_CHECK);
				if(target->hp.getCur() < 1) {
					target->print("Your body explodes! You die!\n");
					broadcast(player->getSock(), target->getSock(), player->getParent(),
						"%M's body explodes! %s's dead!", target, target->upHeShe());
					player->print("%M's body explodes! %s's dead!\n", target, target->upHeShe());
					target->die(player);
					return(2);
				}
			}

		}
	}

	return(1);
}

//*********************************************************************
//						splDispelEvil
//*********************************************************************

int splDispelEvil(Creature* player, cmd* cmnd, SpellData* spellData) {

	if(spellData->how != POTION && !player->isStaff()) {
		if(player->getClass() != CLERIC && player->getClass() != PALADIN && player->isPlayer()) {
			player->print("Your class is unable to cast that spell.\n");
			return(0);
		}
		if(player->getClass() == CLERIC && player->getDeity() != ENOCH && player->getDeity() != LINOTHAN) {
			player->print("%s will not allow you to cast that spell.\n", gConfig->getDeity(player->getDeity())->getName().c_str());
			return(0);
		}
		if(player->getAlignment() < LIGHTBLUE) {
			player->print("You have to be good to cast that spell.\n");
			return(0);
		}
	}

	return(splDispelAlign(player, cmnd, spellData, "dispel-evil", PINKISH));
}

//*********************************************************************
//						splDispelGood
//*********************************************************************

int splDispelGood(Creature* player, cmd* cmnd, SpellData* spellData) {

	if(spellData->how != POTION && !player->isStaff()) {
		if(player->getClass() != CLERIC && player->getClass() != DEATHKNIGHT && player->isPlayer()) {
			player->print("Your class is unable to cast that spell.\n");
			return(0);
		}
		if(player->getClass() == CLERIC && player->getDeity() != ARAMON && player->getDeity() != ARACHNUS) {
			player->print("Your deity will not allow you to cast that vile spell.\n");
			return(0);
		}
		if(player->getAlignment() > PINKISH) {
			player->print("You have to be evil to cast that spell.\n");
			return(0);
		}
	}

	return(splDispelAlign(player, cmnd, spellData, "dispel-good", LIGHTBLUE));
}

//*********************************************************************
//						splArmor
//*********************************************************************
// This spell allows a mage to cast an armor shield around themself which gives themself an
// AC of 6. It sets a pool of virtual HP to effect.strength which is equal to the caster's
// max HP. The armor can take that much damage before dispelling, or its time can run out.
// This spell does NOT absorb damage, it only protects by giving better AC. -TC

int splArmor(Creature* player, cmd* cmnd, SpellData* spellData) {
	Player	*pPlayer = player->getAsPlayer();
	int	mpNeeded=0, multi=0;

	if(!pPlayer)
		return(0);

	mpNeeded = spellData->level;

	if(spellData->how == CAST && !pPlayer->checkMp(mpNeeded))
		return(0);

	if(!pPlayer->isCt()) {
		if(pPlayer->getClass() != MAGE && pPlayer->getSecondClass() != MAGE) {
			if(spellData->how == CAST) {
				player->print("The arcane nature of that spell eludes you.\n");
				return(0);
			} else {
				player->print("Nothing happens.\n");
				return(0);
			}
		}
	}


	if(	pPlayer->getSecondClass() == MAGE ||
		(pPlayer->getClass() == MAGE && pPlayer->getSecondClass() != MAGE)
	) {
		multi=1;
	}

	if(pPlayer->spellFail( spellData->how)) {
		if(spellData->how == CAST)
			pPlayer->subMp(mpNeeded);
		return(0);
	}

	// Cast armor on self

	int strength = 0;
	int duration = 0;
	if(spellData->how == CAST) {
		duration = 1800 + bonus((int)pPlayer->intelligence.getCur());

		if(spellData->how == CAST)
			pPlayer->subMp(mpNeeded);
		if(pPlayer->getRoomParent()->magicBonus()) {
			player->print("The room's magical properties increase the power of your spell.\n");
			duration += 600L;
		}

		if(!multi)
			strength = pPlayer->hp.getMax();
		else
			strength = pPlayer->hp.getMax()/2;
	} else {
		duration = 300L;
		strength = pPlayer->hp.getMax()/2;
	}

	pPlayer->addEffect("armor", duration, strength, player, true, player);
	pPlayer->computeAC();

	if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
		player->print("Armor spell cast.\n");
		broadcast(pPlayer->getSock(), pPlayer->getRoomParent(),"%M casts an armor spell on %sself.", pPlayer, pPlayer->himHer());
	}

	return(1);
}

//*********************************************************************
//						splStoneskin
//*********************************************************************
// This spell allows a mage or lich to use magic to make their skin
// stone-hard to ward off physical attacks.

int splStoneskin(Creature* player, cmd* cmnd, SpellData* spellData) {
	Player	*pPlayer = player->getAsPlayer();
	int		mpNeeded=0, multi=0;

	if(player->getClass() != LICH)
		mpNeeded = player->mp.getMax()/2;
	else
		mpNeeded = player->hp.getMax()/2;

	if(spellData->how == CAST && !player->checkMp(mpNeeded))
		return(0);

	if(!player->isCt()) {
		if(player->getClass() != LICH && player->getClass() != MAGE && (!pPlayer || pPlayer->getSecondClass() != MAGE)) {
			if(spellData->how == CAST) {
				player->print("The arcane nature of that spell eludes you.\n");
				return(0);
			} else {
				player->print("Nothing happens.\n");
				return(0);
			}
		}
		if(spellData->how == CAST && spellData->level < 13) {
			player->print("You are not powerful enough to cast this spell.\n");
			return(0);
		}
	}


	if(	pPlayer && (pPlayer->getSecondClass() == MAGE ||
		(pPlayer->getClass() == MAGE && pPlayer->getSecondClass()))
	) {
		multi=1;
	}

	if(player->spellFail( spellData->how) && spellData->how != POTION) {
		if(spellData->how == CAST)
			player->subMp(mpNeeded);
		return(0);
	}

	int duration = 0;
	int strength = 0;
	// Cast stoneskin on self
	if(spellData->how == CAST) {
		duration = 240 + 10*bonus((int)player->intelligence.getCur());
		if(spellData->how == CAST)
			player->subMp(mpNeeded);
		if(player->getRoomParent()->magicBonus()) {
			player->print("The room's magical properties increase the power of your spell.\n");
			duration += 300L;
		}

		if(!multi)
			strength = spellData->level;
		else
			strength = MAX(1, spellData->level-3);
	} else {
		duration = 180L;
		strength = spellData->level/2;
	}

	player->addEffect("stoneskin", duration, strength, player, true, player);

	if(spellData->how == CAST || spellData->how == SCROLL || spellData->how == WAND) {
		player->print("Stoneskin spell cast.\nYou feel impervious.\n");
		broadcast(player->getSock(), player->getParent(),"%M casts a stoneskin spell on %sself.", player,
			player->himHer());
	} else if(spellData->how == POTION)
		player->print("You feel impervious.\n");

	return(1);
}

//*********************************************************************
//						doDispelMagic
//*********************************************************************

int doDispelMagic(Creature* player, cmd* cmnd, SpellData* spellData, const char* spell, int numDispel) {
	Creature* target=0;
	int		chance=0;

	if(spellData->how == CAST &&
		player->getClass() != MAGE &&
	 	player->getClass() != LICH &&
		player->getClass() != CLERIC &&
		player->getClass() != DRUID &&
		!player->isStaff()
	) {
		player->print("Only mages, liches, clerics, and druids may cast that spell.\n");
		return(0);
	}

	if(cmnd->num == 2) {
		target = player;
		broadcast(player->getSock(), player->getParent(), "%M casts a %s spell on %sself.", player, spell, player->himHer());


		player->print("You cast a %s spell on yourself.\n", spell);
		player->print("Your spells begin to dissolve away.\n");


		player->doDispelMagic(numDispel);
	} else {
		if(player->noPotion( spellData))
			return(0);

		cmnd->str[2][0] = up(cmnd->str[2][0]);
		target = player->getParent()->findPlayer(player, cmnd, 2);
		if(!target) {
			// dispel-magic on an exit
			cmnd->str[2][0] = low(cmnd->str[2][0]);
			Exit* exit = findExit(player, cmnd, 2);

			if(exit) {
				player->printColor("You cast a %s spell on the %s^x.\n", spell, exit->getCName());
				broadcast(player->getSock(), player->getParent(), "%M casts a %s spell on the %s^x.", player, spell, exit->getCName());

				if(exit->flagIsSet(X_PORTAL))
					Move::deletePortal(player->getRoomParent(), exit);
				else
					exit->doDispelMagic(player->getRoomParent());
				return(0);
			}

			player->print("You don't see that player here.\n");
			return(0);
		}

		if(player->isPlayer() && player->getRoomParent()->isPkSafe() && (!player->isCt()) && !target->flagIsSet(P_OUTLAW)) {
			player->print("That spell is not allowed here.\n");
			return(0);
		}

		if(!target->isEffected("petrification")) {
			if(!player->canAttack(target))
				return(0);
		} else {
			player->print("You cast a %s spell on %N.\n%s body returns to flesh.\n",
				spell, target, target->upHisHer());
			if(mrand(1,100) < 50) {

				target->print("%M casts a %s spell on you.\nYour body returns to flesh.\n", player, spell);
				broadcast(player->getSock(), target->getSock(), player->getParent(),
					"%M casts a %s spell on %N.\n%s body returns to flesh.\n",
					player, spell, target, target->upHisHer());
				target->removeEffect("petrification");
				return(1);
			} else {
				target->print("%M casts a dispel-magic spell on you.\n", player);
				broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts a dispel-magic spell on %N.\n",player, target);
				return(0);
			}


		}


		chance = 50 - (10*(bonus((int) player->intelligence.getCur()) -
			bonus((int) target->intelligence.getCur())));

		chance += (spellData->level - target->getLevel())*10;

		chance = MIN(chance, 90);

		if((target->isEffected("resist-magic")) && target->isPlayer())
			chance /=2;




		if(	player->isCt() ||
			(mrand(1,100) <= chance && !target->chkSave(SPL, player, 0)))
		{
			player->print("You cast a %s spell on %N.\n", spell, target);

			logCast(player, target, spell);

			broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts a %s spell on %N.", player, spell, target);
			target->print("%M casts a %s spell on you.\n", player, spell);
			target->print("Your spells begin to dissolve away.\n");


			target->doDispelMagic(numDispel);

			for(Monster* pet : target->pets) {
			    if(pet) {
	                if(player->isCt() || !pet->chkSave(SPL, player, 0)) {
	                    player->print("Your spell bansished %N's %s!\n", target, pet->getCName());
	                    target->print("%M's spell banished your %s!\n%M fades away.\n", player, pet->getCName(), pet);
	                    gServer->delActive(pet);
	                    pet->die(pet->getMaster());
	                }
			    }
			}
		} else {
			player->printColor("^yYour spell fails against %N.\n", target);
			target->print("%M tried to cast a dispel-magic spell on you.\n", player);
			broadcast(player->getSock(), target->getSock(), player->getParent(), "%M tried to cast a dispel-magic spell on %N.", player, target);
			return(0);
		}
	}
	return(1);
}

//*********************************************************************
//						dispel-magic spells
//*********************************************************************

int splCancelMagic(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(doDispelMagic(player, cmnd, spellData, "cancel-magic", mrand(1,2)));
}

int splDispelMagic(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(doDispelMagic(player, cmnd, spellData, "dispel-magic", mrand(3,5)));
}

int splAnnulMagic(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(doDispelMagic(player, cmnd, spellData, "annul-magic", -1));
}

//********************************************************************
//						doDispelMagic
//********************************************************************
// num = -1 means dispel all effects

void Creature::doDispelMagic(int num) {
	EffectInfo* effect=0;
	std::list<bstring> effList;
	std::list<bstring>::const_iterator it;

	// create a list of possible effects
	effList.push_back("anchor");
	effList.push_back("hold-person");
	effList.push_back("strength");
	effList.push_back("haste");
	effList.push_back("fortitude");
	effList.push_back("insight");
	effList.push_back("prayer");
	effList.push_back("enfeeblement");
	effList.push_back("slow");
	effList.push_back("weakness");
	effList.push_back("prayer");
	effList.push_back("damnation");
	effList.push_back("confusion");

	effList.push_back("enlarge");
	effList.push_back("reduce");
	effList.push_back("darkness");
	effList.push_back("infravision");
	effList.push_back("invisibility");
	effList.push_back("detect-invisible");
	effList.push_back("undead-ward");
	effList.push_back("bless");
	effList.push_back("detect-magic");
	effList.push_back("protection");
	effList.push_back("tongues");
	effList.push_back("comprehend-languages");
	effList.push_back("true-sight");
	effList.push_back("fly");
	effList.push_back("levitate");
	effList.push_back("drain-shield");
	effList.push_back("resist-magic");
	effList.push_back("know-aura");
	effList.push_back("warmth");
	effList.push_back("breathe-water");
	effList.push_back("earth-shield");
	effList.push_back("reflect-magic");
	effList.push_back("camouflage");
	effList.push_back("heat-protection");
	effList.push_back("farsight");
	effList.push_back("pass-without-trace");
	effList.push_back("resist-earth");
	effList.push_back("resist-air");
	effList.push_back("resist-fire");
	effList.push_back("resist-water");
	effList.push_back("resist-cold");
	effList.push_back("resist-electricity");
	effList.push_back("wind-protection");
	effList.push_back("static-field");

	effList.push_back("illusion");
	effList.push_back("blur");
	effList.push_back("fire-shield");
	effList.push_back("greater-invisibility");

	// true we'll show, false don't remove perm effects

	// num = -1 means dispel all effects
	if(num <= -1) {
		for(it = effList.begin() ; it != effList.end() ; it++)
			removeEffect(*it, true, false);
		return;
	}

	int numEffects=0, choice=0;
	while(num > 0) {
		// how many effects are we under?
		for(it = effList.begin() ; it != effList.end() ; it++) {
			effect = getEffect(*it);
			if(effect && !effect->isPermanent())
				numEffects++;
		}

		// none? we're done
		if(!numEffects)
			return;
		// which effect shall we dispel?
		choice = mrand(1, numEffects);
		numEffects = 0;

		// find it and get rid of it!
		for(it = effList.begin() ; it != effList.end() && choice ; it++) {
			effect = getEffect(*it);
			if(effect && !effect->isPermanent()) {
				numEffects++;
				if(choice == numEffects) {
					removeEffect(*it, true, false);
					// stop the loop!
					choice = 0;
				}
			}
		}

		num--;
	}
}

//*********************************************************************
//						doDispelMagic
//*********************************************************************

void Exit::doDispelMagic(BaseRoom* parent) {
	bringDownTheWall(getEffect("wall-of-fire"), parent, this);
	bringDownTheWall(getEffect("wall-of-thorns"), parent, this);

	// true we'll show, false don't remove perm effects
	removeEffect("concealed", true, false);
}

//*********************************************************************
//						fire shield spells
//*********************************************************************
// This adds the actual fire-shield effect, include mage-lich restrict and
// strength of the spell. Strength and level restrict follow this chart:
//	1=1, 2=4, 3=9, 4=16

int addFireShield(Creature* player, cmd* cmnd, SpellData* spellData, const char* article, const char* spell, int strength) {
	if(spellData->how == CAST) {
		if(!player->isMageLich())
			return(0);
		if(spellData->level < pow(strength, 2)) {
			player->print("You are not powerful enough to cast this spell.\n");
			return(0);
		}
	}

	return(splGeneric(player, cmnd, spellData, article, spell, "fire-shield", (int)pow(strength, 2)));
}

int splRadiation(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(addFireShield(player, cmnd, spellData, "a", "radiation", 1));
}
int splFieryRetribution(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(addFireShield(player, cmnd, spellData, "a", "fiery retribution", 2));
}
int splAuraOfFlame(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(addFireShield(player, cmnd, spellData, "an", "aura of flame", 3));
}
int splBarrierOfCombustion(Creature* player, cmd* cmnd, SpellData* spellData) {
	return(addFireShield(player, cmnd, spellData, "a", "barrier of combustion", 4));
}

//*********************************************************************
//						doReflectionDamage
//*********************************************************************
// return true if we were killed by the reflection
// passing printZero as REFLECTED_MAGIC or REFLECTED_PHYSICAL will print, even if damage is 0

bool Creature::doReflectionDamage(Damage damage, Creature* target, ReflectedDamageType printZero) {
	int dmg = damage.getReflected() ? damage.getReflected() : damage.getPhysicalReflected();

	// don't quit if we want to print 0
	if(!dmg && printZero == REFLECTED_NONE)
		return(false);

	if(damage.getReflected() || printZero == REFLECTED_MAGIC) {
		target->printColor("Your shield of magic reflects %s%d^x damage.\n", target->customColorize("*CC:DAMAGE*").c_str(), dmg);
		printColor("%M's shield of magic flares up and hits you for %s%d^x damage.\n", target, customColorize("*CC:DAMAGE*").c_str(), dmg);
		broadcastGroup(false, this, "%M's shield of magic flares up and hits %N for *CC:DAMAGE*%d^x damage.\n",
			target, this, dmg);
	} else {
		switch(damage.getPhysicalReflectedType()) {
		case REFLECTED_FIRE_SHIELD:
		default:
			target->printColor("Your shield of fire reflects %s%d^x damage.\n", target->customColorize("*CC:DAMAGE*").c_str(), dmg);
			printColor("%M's shield of fire flares up and hits you for %s%d^x damage.\n", target, customColorize("*CC:DAMAGE*").c_str(), dmg);
			broadcastGroup(false, this, "%M's shield of fire flares up and hits %N for *CC:DAMAGE*%d^x damage.\n",
				target, this, dmg);
			break;
		}
	}

	if(damage.getDoubleReflected()) {
		Damage reflectedDamage;
		reflectedDamage.setReflected(damage.getDoubleReflected());
		target->doReflectionDamage(reflectedDamage, this);
	}

	// we may have gotten this far for printing reasons (even on zero), but really, go no further
	if(!dmg)
		return(false);

	if(target->isPlayer() && isMonster())
		getAsMonster()->adjustThreat(target, dmg);

	hp.decrease(dmg);
	if(hp.getCur() <= 0)
		return(true);
	return(false);
}