roh/conf/area/
roh/game/talk/
roh/help/
roh/monsters/ocean/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.44b/
/*
 * illusion.cpp
 *	 Illusion 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-2009 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 "magic.h"
#include "effects.h"
#include "commands.h"


//*********************************************************************
//						splInvisibility
//*********************************************************************
// This function allows a player to cast an invisibility spell on themself
// or on another player.

int splInvisibility(Creature* player, cmd* cmnd, SpellData* spellData) {
	if(!player->isStaff()) {
		if(player->getClass() == LICH && player->getLevel() < 3 && spellData->how == CAST) {
			player->print("You are not experienced enough to cast that yet.\n");
			return(0);
		}
		if(player->inCombat()) {
			player->print("Not in the middle of combat.\n");
			return(0);
		}
	}

	return(splGeneric(player, cmnd, spellData, "an", "invisibility", "invisibility"));
}

//*********************************************************************
//						splInvisibility
//*********************************************************************
// This function allows a player to cast an invisibility spell on themself
// or on another player.

int splGreaterInvisibility(Creature* player, cmd* cmnd, SpellData* spellData) {
	if(!player->isStaff()) {
		if(!isMageLich(player))
			return(0);
		if(player->getLevel() < 20 && spellData->how == CAST) {
			player->print("You are not experienced enough to cast that yet.\n");
			return(0);
		}
		if(player->inCombat()) {
			player->print("Not in the middle of combat.\n");
			return(0);
		}
	}

	return(splGeneric(player, cmnd, spellData, "a", "greater invisibility", "greater-invisibility"));
}

bool Creature::isInvisible() const {
	return(isEffected("invisibility") || isEffected("greater-invisibility"));
}

//*********************************************************************
//						splCamouflage
//*********************************************************************
// This function allows players to cast camouflage on one another or
// themselves. Camouflage lessens the chance of ranger track spell.

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

//*********************************************************************
//						splBlink
//*********************************************************************

int splBlink(Creature* player, cmd* cmnd, SpellData* spellData) {
	Player	*pPlayer = player->getPlayer();
	int		canCast=0;
	Exit	*exit=0;
	BaseRoom* newRoom=0;

	if(!pPlayer)
		return(0);

	if(pPlayer->getClass() == MAGE || pPlayer->getClass() == LICH ||
	        pPlayer->getSecondClass() == MAGE || pPlayer->isStaff())
		canCast=1;


	if(!pPlayer->spellIsKnown(S_BLINK)) {
		player->print("You do not know that spell.\n");
		return(0);
	}

	if(!canCast && spellData->how == CAST) {
		player->print("You cannot cast that spell.\n");
		return(0);
	}

	if(!canCast && spellData->how != CAST) {
		player->print("The magic will not work for you.\n");
		return(0);
	}

	if(cmnd->num < 3) {
		player->print("Syntax: cast blink (exit)\n");
		return(0);
	}

	exit = findExit(pPlayer, cmnd, 2);

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

	Monster* guard = pPlayer->getRoom()->getGuardingExit(exit);
	if(guard && !player->checkStaff("You cannot see past %N.\n", guard))
		return(0);

	if(exit->flagIsSet(X_CLOSED)) {
		player->print("You cannot blink where you cannot see!\n");
		return(0);
	}



	if(!pPlayer->canFleeToExit(exit)) {
		player->print("The spell fizzled.\n");
		return(0);
	}

	if(spellData->how == CAST && !pPlayer->isStaff() && pPlayer->checkDimensionalAnchor()) {
		player->printColor("^yYour dimensional-anchor causes your spell to fizzle!^w\n");
		return(1);
	}

	newRoom = pPlayer->getFleeableRoom(exit);

	if(!newRoom) {
		player->print("The spell fizzled.\n");
		return(0);
	}


	player->print("You cast a blink spell. You blink away to the %s.\n", exit->name);
	broadcast(pPlayer->getSock(), pPlayer->getRoom(), "%M blinks away!", pPlayer);
	broadcast(isDm, pPlayer->getSock(), pPlayer->getRoom(), "*DM* %M blinks to the \"%s\" exit.", pPlayer, exit->name);

	pPlayer->deleteFromRoom();
	pPlayer->addToRoom(newRoom);
	pPlayer->doPetFollow();

	broadcast(pPlayer->getSock(), newRoom, "%M just blinked into existance.", pPlayer);
	return(1);
}

//*********************************************************************
//						splIllusion
//*********************************************************************

int splIllusion(Creature* player, cmd* cmnd, SpellData* spellData) {
	bstring txt = "";
	Player* pPlayer=0, *target=0;
	const RaceData* race=0;

	if(!player->isPlayer())
		return(0);
	pPlayer = player->getPlayer();

	if(spellData->how == CAST) {
		// if the spell was cast
		if(!isMageLich(pPlayer))
			return(0);

		txt = getFullstrText(cmnd->fullstr, cmnd->num == 3 ? 2 : 3);

		if(txt == "") {
			pPlayer->print("Illusion whom to what race?\n");
			pPlayer->print("Syntax: cast illusion [target] <race>\n");
			return(0);
		}

		race = gConfig->getRace(txt);

		if(!race) {
			pPlayer->print("Race not understood or not unique.\n");
			pPlayer->print("Syntax: cast illusion [target] <race>\n");
			return(0);
		}
	} else if(spellData->object) {
		// if we're using an object to get data
		if(spellData->object->getExtra() > 0 && spellData->object->getExtra() < RACE_COUNT)
			race = gConfig->getRace(spellData->object->getExtra());

		if(!race) {
			pPlayer->printColor("%O is doesn't taste quite right.\n", spellData->object);
			return(0);
		}
	}


	if(cmnd->num == 3 || (cmnd->num == 2 && spellData->how == POTION)) {
		target = pPlayer;

		if(spellData->how != POTION) {
			pPlayer->print("You cast an illusion spell.\n");
			broadcast(pPlayer->getSock(), pPlayer->getRoom(), "%M casts an illusion spell.", pPlayer);
		}
	} else {
		if(noPotion(player, spellData))
			return(0);

		cmnd->str[2][0] = up(cmnd->str[2][0]);
		target = pPlayer->getRoom()->findPlayer(pPlayer, cmnd->str[2], cmnd->val[2], false);

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

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

		broadcast(pPlayer->getSock(), target->getSock(), pPlayer->getRoom(), "%M casts an illusion spell on %N.",
			pPlayer, target);
		target->print("%M casts illusion on you.\n", pPlayer);
		pPlayer->print("You cast an illusion spell on %N.\n", target);
	}

	if(pPlayer->getRoom()->magicBonus())
		pPlayer->print("The room's magical properties increase the power of your spell.\n");

	if(target->isEffected("illusion"))
		target->removeEffect("illusion", false);
	target->addEffect("illusion", pPlayer, FROM_CREATURE, true, player);


	EffectInfo* effect = target->getEffect("illusion");
	effect->setExtra(race->getId());
	effect->setStrength(pPlayer->getLevel());

	return(1);
}

//*********************************************************************
//						willIgnoreIllusion
//*********************************************************************

bool Creature::willIgnoreIllusion() const {
	if(isStaff())
		return(true);
	if(isUndead() || monType::noLivingVulnerabilities(type))
		return(true);
	if(isEffected("true-sight"))
		return(true);
	return(false);
}

//*********************************************************************
//						splBlur
//*********************************************************************

int splBlur(Creature* player, cmd* cmnd, SpellData* spellData) {
	// this number is the % miss chance
	int strength = 7;
	if(spellData->how == CAST)
		strength += player->getLevel()/10;
	return(splGeneric(player, cmnd, spellData, "a", "blur", "blur", strength));
}


//*********************************************************************
//						splIllusoryWall
//*********************************************************************

int splIllusoryWall(Creature* player, cmd* cmnd, SpellData* spellData) {
	Exit *exit=0;
	int strength = spellData->level;
	long duration = 300;

	if(noPotion(player, spellData))
		return(0);

	if(cmnd->num > 2)
		exit = findExit(player, cmnd, 2);
	if(!exit) {
		player->print("Cast an illusory wall spell on which exit?\n");
		return(0);
	}

	player->print("You cast an illusory wall spell on the %s.\n", exit->name);
	broadcast(player->getSock(), player->getRoom(), "%M casts an illusory wall spell on the %s.",
		player, exit->name);

	if(exit->flagIsSet(X_CONCEALED) || exit->hasPermEffect("illusory-wall")) {
		player->print("The spell didn't take hold.\n");
		return(0);
	}

	if(spellData->how == CAST) {
		if(player->getRoom()->magicBonus())
			player->print("The room's magical properties increase the power of your spell.\n");
	}

	exit->addEffect("illusory-wall", duration, strength, true, player->getRoom(), player);
	return(1);
}