// XXX LOS BEGIN
public virtual bool CanSee(Mobile m)
{
bool canSee = true;
if (this == m) canSee = true;
else if (!Utility.InRange(this.Location, m.Location, 15)) canSee = false;
else if (m_Deleted || m.m_Deleted || m_Map == Map.Internal || m.m_Map == Map.Internal || this.m_Map != m.m_Map) canSee = false;
else if (this.AccessLevel > AccessLevel.Player && (this.AccessLevel >= m.AccessLevel || this.AccessLevel >= AccessLevel.Administrator)) canSee = true;
else canSee =
!m.Hidden // hidden cant be seen regardless
&&
(
( // account for ghosts and what not
m.Alive
||
Core.SE && Skills.SpiritSpeak.Value >= 100.0
||
!this.Alive
||
m.Warmode
)
&&
CheckLos(m)
);
//Console.WriteLine("LOS: \"{0}\" sees \"{1}\" ? {2}", this.Name, m.Name, canSee );
//if( AccessLevel = AccessLevel.Player || LOS.Config.GetInstance().LosForMobs )
//if( canSee && addLos ) AddLos( m );
return canSee;
}
//------------------------------------------------------------------------------
// CheckLos() -- this is where the real line of sight checking is actually
// done.
//------------------------------------------------------------------------------
public bool CheckLos(IEntity o)
{
//if( this.NetState == null )
//Console.WriteLine( "Checking LOS for {0} --> {1}", this.Name, o is Mobile ? ((Mobile)o).Name : ((Item)o).Name );
Point3D viewer = this.Location;
Point3D target = o.Location;
//if( o is Item ) Console.WriteLine( "Checking LOS for item {0},{1},{2} --> {3},{4},{5} \"{6}\"",
// viewer.X, viewer.Y, viewer.Z, target.X, target.Y, target.Z, o.GetType().Name
// );
// CHECK NO UP IN CAN_SEE, No need here
//
// if ( !Utility.InRange( viewer, target, 15 ) )
// {
// return false; // LOS stops resolving at a range of 15
// }
if (o is Item)
{
Item item = (Item)o;
//--------------------------------------------------------------
// Immovable items always visible
//--------------------------------------------------------------
if (!item.Movable)
{
if (LOS.Values.Corpse.IsInstanceOfType(item))
{
PropertyInfo info = LOS.Values.Corpse.GetProperty("Owner");
Mobile owner = (Mobile)info.GetValue(item, null);
if (owner == this) return true;
}
else return true;
}
//--------------------------------------------------------------
// Not lossed items always visible
//--------------------------------------------------------------
if (LOS.Config.GetInstance().NotLossed(item.ItemID | 0x4000))
{
return true;
}
//--------------------------------------------------------------
// All items are visible if we're not lossing them.
//--------------------------------------------------------------
if (!LOS.Config.GetInstance().Items)
{
return true;
}
}
else if (o is Mobile)
{
if (this.Player)
{
if (!LOS.Config.GetInstance().Mobiles)
{
return true; // if mobile is off, we can see all mobiles
}
}
else
{
if (!LOS.Config.GetInstance().LosForMobs)
{
return true; // if this is an npc mob, and los for npcs if off, the npc mob sees all
}
else if (Utility.InRange(viewer, target, 7))
{
return true;
}
}
}
//------------------------------------------------------------------
// if LOS is not on on this facet, don't use LOS
//------------------------------------------------------------------
if (!LOS.Config.GetInstance().FacetOn(this.Map.Name))
{
return true;
}
//------------------------------------------------------------------
// if LOS is off, don't use LOS
//------------------------------------------------------------------
if (!LOS.Config.GetInstance().On)
{
return true;
}
//------------------------------------------------------------------
// Maybe perform symmetric los; this creates balance: if I can't LOS you,
// you can't LOS me. This has nothing to do with hidden or other characteristics
// at this point, just basic LOS. This can be used to remedy certain
// defects of the LOS system that some might regard as unfair...
//------------------------------------------------------------------
if (LOS.Config.GetInstance().Symmetric)
{
return
this.Map.LOS.Visible(viewer, target)
&&
this.Map.LOS.Visible(target, viewer)
;
}
else
{
return
this.Map.LOS.Visible(viewer, target)
;
}
}
//------------------------------------------------------------------------------
// InvalidateLos() -- this function sends a remove packet to mobiles that
// have just gone out of our line of site. This needs to be done because the
// client "dead reckons" (stores last position) mobiles by default.
//------------------------------------------------------------------------------
public void InvalidateLos()
{
if (m_LosCurrent.Count > 0)
{
Dictionary<Object, Object> culls = new Dictionary<Object, Object>();
foreach (Object o in m_LosCurrent.Keys)
{
if (o is Mobile)
{
Mobile m = (Mobile)o;
if (!CanSee(m)) culls.Add(m, m);
}
else if (o is Item)
{
Item i = (Item)o;
if (!CanSee(i)) culls.Add(i, i);
}
}
foreach (Object o in culls.Keys)
{
RemoveLos(o);
Packet p = o is Mobile ? ((Mobile)o).RemovePacket : ((Item)o).RemovePacket;
NetState state = this.NetState;
if (state != null)
{
state.Send(p);
}
}
}
}
public bool InLos(Object o)
{
if (m_LosCurrent.ContainsKey(o)) return true;
else return false;
}
public void AddLos(Object o)
{
if (m_NetState == null) return; // things without a netstate cannot benefit from LOS list optimization
if (!m_LosCurrent.ContainsKey(o)) m_LosCurrent.Add(o, o);
}
public void RemoveLos(Object o)
{
if (m_NetState == null) return; // things without a netstate cannot benefit from LOS list optimization
if (m_LosCurrent.ContainsKey(o)) m_LosCurrent.Remove(o);
}
// XXX LOS END