area/
build/testing/
log/
player/
player/backup/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments 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          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/
#include <glib.h>

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <merc.h>

int get_vage_bonus (CHAR_DATA *ch)
{
	int ch_age = (get_age(ch) - 17) * 2;  /* hours calculation */
	
	if (IS_SWWF(ch))
	{	
		if      (ch_age >= 1500) return 2;
		else if (ch_age >=  800) return 1;
	}
 	return 0;
}

bool can_see_incog( CHAR_DATA *ch, CHAR_DATA *victim)
{
	bool found = TRUE;
	
	if ( !IS_NPC(victim) 
		&& IS_SET(victim->act, PLR_INCOG)
		&&   get_trust( ch ) < LEVEL_IMMORTAL
		&&   ch->in_room != victim->in_room )
			found = FALSE;
		
	return found;
}

bool can_see_vampire_wizinvis(CHAR_DATA *victim, int Seeker_Sight_Level, int chance_v)
{
	bool can_see = FALSE;
	int Obf_Level = 0;
	
	if (IS_VAMPIRE(victim))
	{	
	
		Obf_Level = get_disc(victim,DISC_OBFUSCATE);
    
    	if (IS_ADDED(victim,ADDED_CHAMELEON))
    		Obf_Level++;
    
		if (Seeker_Sight_Level >= Obf_Level && number_percent() > chance_v)
			can_see = TRUE;
	}
	
	return can_see;
}

bool can_see_werewolf_wizinvis(CHAR_DATA *victim, int Seeker_Sight_Level, int chance_v)
{
	bool can_see = FALSE;
	int Obf_Level = 0;
	
	if (IS_SWWF(victim))
	{	
	
		Obf_Level = get_auspice(victim,AUSPICE_RAGABASH) + get_vage_bonus(victim);
    
    	if (Seeker_Sight_Level >= Obf_Level && number_percent() > chance_v)
			can_see = TRUE;
	}
	
	return can_see;
}

bool can_see_mage_wizinvis(CHAR_DATA *victim, int Seeker_Sight_Level, int chance_v)
{
	bool can_see = FALSE;
	int Obf_Level = 0;
	
	if (IS_MAGE(victim))
	{	
	
		Obf_Level = has_sphere(victim,SPHERE_CORRESPONDENCE);
    
    	if (Seeker_Sight_Level >= Obf_Level && number_percent() > chance_v)
			can_see = TRUE;
	}
	
	return can_see;
}

bool get_player_wizinvis(CHAR_DATA *victim, int char_sight_level,int chance_v)
{
	bool found = FALSE;
	
	switch (victim->creature)
	{
		default :
			break;
		case CLASS_SWWF:
			found = can_see_werewolf_wizinvis(victim,char_sight_level,chance_v);
			break;
		case CLASS_VAMPIRE:
			found = can_see_vampire_wizinvis(victim,char_sight_level,chance_v);
			break;
		case CLASS_MAGE:
			found = can_see_mage_wizinvis(victim,char_sight_level,chance_v);
			break;
	}		
	return found;
}

int get_char_sight_level(CHAR_DATA *ch)
{
	int level = 0;
	
	switch (ch->creature){
		default:
			break;
		case CLASS_SWWF:
			level = get_breed(ch,BREED_LUPUS);
			break;
		case CLASS_VAMPIRE:
			level = get_disc(ch,DISC_AUSPEX);
        	if (IS_ADDED(ch,ADDED_VOICESOFCASTLE))
         	   level++;
    		break;
		case CLASS_MAGE:
			level = has_sphere(ch,SPHERE_CORRESPONDENCE);
			break;
	}
	
	return level;
}
bool see_wizinvis( CHAR_DATA *ch, CHAR_DATA *victim)
{
	int chance_v = 50;
	bool found_victim = FALSE;

	
	if (IS_SET(victim->act,PLR_WIZINVIS))
	{	
		if (!IS_NPC(victim) )
		{
			/*
			 * Player
			 */
			if (IS_IMMORTAL(victim))
			{		
				if ( get_trust(ch) >= victim->invis_level )
					found_victim = TRUE;
			}
			else
			{
				/*
				 * Mortal Character
				 */
				if (IS_IMMORTAL(ch))
					return TRUE;

				/*
				 * Non Avatar's don't have vanish
				 */
				if (victim->level <= 2)
					return TRUE;

				/*
				 * Now check Avatar Victim's
				 */
				if ( victim->pk_timer > 4 && ch->level > 2 )
				{
					found_victim = TRUE;
				}
				else
				{
					if (!IS_NPC(ch))
					{
						int char_sight_level = 0;
						chance_v = 50;
	
						if (IS_MERIT(ch,MERIT_PERCEPTIVE))
							chance_v -= 30;
	
						if (IS_FLAW(ch,FLAW_UNPERCEPTIVE))
							chance_v += 30;

						char_sight_level = get_char_sight_level(ch);
						found_victim = get_player_wizinvis(victim,char_sight_level,chance_v);
					}
					else
					{
						if (IS_SET(ch->act,ACT_HOLYLIGHT))
							found_victim = TRUE;
					}	
				}
			}
		}
		else
		{
			//Mobile
			if (!IS_NPC(ch) && IS_IMMORTAL(ch))
			{
				found_victim = TRUE;
			}
			else
			{
				if (IS_SET(ch->act,ACT_HOLYLIGHT))
					found_victim = TRUE;
			}
		}	
	}
	else
	{
		found_victim = TRUE;
	}
	
    return found_victim;
}

bool can_see_plane_normal(CHAR_DATA *ch){
	bool can_see_char = FALSE;
	
	if (ch->plane == PLANE_SHADOW && IS_SET(ch->sight, SIGHT_SHADOW))
		can_see_char = TRUE;
	
	if (ch->plane == PLANE_SPIRIT && IS_SET(ch->sight, SIGHT_SPIRIT))
		can_see_char = TRUE;
		
	return can_see_char;
}

bool can_see_plane_shadow(CHAR_DATA *ch){
	bool can_see = FALSE;
	
	if (ch->plane == PLANE_NORMAL && IS_SET(ch->sight, SIGHT_SHADOW))
		can_see = TRUE;
		
	return can_see;	
}

bool can_see_plane_spirit(CHAR_DATA *ch){
	bool can_see = FALSE;

	if (ch->plane == PLANE_NORMAL && IS_SET(ch->sight, SIGHT_SPIRIT))
		can_see = TRUE;

	return can_see;	
}

bool can_see_plane_dead(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_earth(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_immortal(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_punishment(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_ethereal(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_umbra(CHAR_DATA *ch){
	bool can_see = FALSE;

	if (ch->plane == PLANE_NORMAL && IS_SET(ch->sight, SIGHT_UMBRA))
		can_see = TRUE;

	return can_see;	
}

bool has_planesight(CHAR_DATA *ch, CHAR_DATA *victim){
	
	bool found = FALSE;
	
	//Immortals can see all!
	if (IS_IMMORTAL(ch))
		return TRUE;
		
	if (ch->plane != victim->plane)
	{
		switch (victim->plane){
			case PLANE_NORMAL:
				found = can_see_plane_normal(ch);
				break;
			case PLANE_DEAD:
				found = can_see_plane_dead(ch);
				break;
			case PLANE_SHADOW:
				found = can_see_plane_shadow(ch);
				break;
			case PLANE_SPIRIT:
				found = can_see_plane_spirit(ch);
				break;
			case PLANE_UMBRA:
				found = can_see_plane_umbra(ch);
				break;
			case PLANE_ETHEREAL:
				found = can_see_plane_ethereal(ch);
				break;
			case PLANE_EARTH:
				found = can_see_plane_earth(ch);
				break;
			case PLANE_PUNISHMENT:
				found = can_see_plane_punishment(ch);
				break;
			case PLANE_IMMORTAL:
				found = can_see_plane_immortal(ch);
				break;
			default:
				break;
		}
	}
	else
		return TRUE;

	return found;	
}
/*
 * True if char can see victim.
 */
bool can_see( CHAR_DATA *ch, CHAR_DATA *victim )
{
	//Char is looking at self..
	if ( ch == victim )
		return TRUE;
	
	//If the victim has a artifact.. we want people to see em
	if (IS_ITEMAFF(victim, ITEMA_ARTIFACT) && !IS_IMMORTAL(victim))
		return TRUE;

	if (!has_planesight(ch,victim))
		return FALSE;
	
	if (!can_see_incog(ch,victim))
		return FALSE;
		
	//Wizinvis(Vanish)
	if (!see_wizinvis(ch,victim))
		return FALSE;
	
	if (IS_RAFFECTED(ch->in_room, ROOM_AFF_AEOLUS ))
	{
		if (!IS_SET(ch->sight, SIGHT_PDARK))
			return FALSE;
	}
	
	if (IS_RAFFECTED(ch->in_room,ROOM_AFF_DARK))
	{
		if (!IS_SET(ch->sight,SIGHT_NIGHTSIGHT) && !IS_SET(ch->sight,SIGHT_INFRARED))
			return FALSE;
	}
	
	
	if ( IS_HEAD(ch, LOST_EYE_L) || IS_HEAD(ch, LOST_EYE_R) )
		return FALSE;
	
	if ( IS_EXTRA(ch, BLINDFOLDED) && !IS_VAMPAFF(ch, VAM_SONIC))
		return FALSE;
	//
	//Invis Check vs Detect Invis
	if (IS_SET(victim->affected_by,AFF_INVISIBLE) && (!IS_SET(ch->sight,SIGHT_INVISABLE) && !IS_SET(ch->act, PLR_HOLYLIGHT))){
		return FALSE;
	}
	
    return TRUE;
}


bool can_see_plane_normal_obj(CHAR_DATA *ch){
	bool can_see = FALSE;
	
	if (ch->plane == PLANE_SHADOW && IS_SET(ch->sight, SIGHT_SHADOW))
		can_see = TRUE;
	
	if (ch->plane == PLANE_SPIRIT && IS_SET(ch->sight, SIGHT_SPIRIT))
		can_see = TRUE;
		
	return can_see;
}

bool can_see_plane_shadow_obj(CHAR_DATA *ch){
	bool can_see = FALSE;
	
	if (ch->plane == PLANE_NORMAL && IS_SET(ch->sight, SIGHT_SHADOW))
		can_see = TRUE;
		
	return can_see;	
}

bool can_see_plane_spirit_obj(CHAR_DATA *ch){
	bool can_see = FALSE;

	if (ch->plane == PLANE_NORMAL && IS_SET(ch->sight, SIGHT_SPIRIT))
		can_see = TRUE;

	return can_see;	
}

bool can_see_plane_dead_obj(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_earth_obj(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_immortal_obj(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_punishment_obj(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_ethereal_obj(CHAR_DATA *ch){
	bool can_see = FALSE;
	return can_see;	
}

bool can_see_plane_umbra_obj(CHAR_DATA *ch){
	bool can_see = FALSE;

	if (ch->plane == PLANE_NORMAL && IS_SET(ch->sight, SIGHT_UMBRA))
		can_see = TRUE;

	return can_see;	
}


bool can_seeobj_plane(CHAR_DATA *ch, OBJ_DATA *obj){
	bool can_see = FALSE;
	
	if (ch->plane == obj->plane)
		return TRUE;
	
	if (IS_IMMORTAL(ch))
		return TRUE;
		
	switch (obj->plane){
		case PLANE_NORMAL:
			can_see = can_see_plane_normal_obj(ch);
			break;
		case PLANE_DEAD:
			can_see = can_see_plane_dead_obj(ch);
			break;
		case PLANE_SHADOW:
			can_see = can_see_plane_shadow_obj(ch);
			break;
		case PLANE_SPIRIT:
			can_see = can_see_plane_spirit_obj(ch);
			break;
		case PLANE_UMBRA:
			can_see = can_see_plane_umbra_obj(ch);
			break;
		case PLANE_ETHEREAL:
			can_see = can_see_plane_ethereal_obj(ch);
			break;
		case PLANE_EARTH:
			can_see = can_see_plane_earth_obj(ch);
			break;
		case PLANE_PUNISHMENT:
			can_see = can_see_plane_punishment_obj(ch);
			break;
		case PLANE_IMMORTAL:
			can_see = can_see_plane_immortal_obj(ch);
			break;
		default:
			break;
	}
	return can_see;
}

/*
 * True if char can see obj.
 */
bool can_see_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
	if ( !IS_IMMORTAL(ch) && obj->carried_by != NULL 
			&& !IS_NPC(obj->carried_by) && ch != obj->carried_by 
			&& IS_SET(obj->carried_by->added, ADDED_CLOAK) )
		return FALSE;

	if (!can_seeobj_plane(ch,obj) && !IS_IMMORTAL(ch))
		return FALSE;


	//Invis Check && Vanish Check
	if (IS_SET(obj->extra_flags,ITEM_INVIS) && !IS_SET(ch->sight,SIGHT_INVISABLE) &&  !IS_SET(ch->act, PLR_HOLYLIGHT)){
		return FALSE;
	}


	if ( IS_ITEMAFF(ch, ITEMA_VISION) )
		return TRUE;

	if ( !IS_NPC(ch) && IS_VAMPAFF(ch, VAM_SONIC) )
		return TRUE;

	if ( obj->item_type == ITEM_POTION )
		return TRUE;

	if ( IS_HEAD(ch, LOST_EYE_L) && IS_HEAD(ch, LOST_EYE_R) )
		return FALSE;

	if ( IS_EXTRA(ch, BLINDFOLDED) )
		return FALSE;

	if ( obj->item_type == ITEM_LIGHT && obj->value[2] != 0 )
		return TRUE;

	if (IS_RAFFECTED(ch->in_room,ROOM_AFF_DARK))
	{
		if (!IS_IMMORTAL( ch ))
			return FALSE;
		else
			return TRUE;
	}

	if ( !IS_NPC(ch) && IS_HEAD(ch, LOST_HEAD) &&
			ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
		return TRUE;

	if ( !IS_NPC(ch) && IS_EXTRA(ch, EXTRA_OSWITCH) &&
			ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
		return TRUE;

	return TRUE;
}



/*
 * True if char can drop obj.
 */
bool can_drop_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
	if ( !IS_SET(obj->extra_flags, ITEM_NODROP) )
		return TRUE;
	
	if ( !IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL )
		return TRUE;
	
	return FALSE;
}