/// <summary> /// LoscheckVincinity can be used when source player isn't available to check Los /// </summary> /// <param name="source">GameObject from witch LoS check start</param> /// <param name="target">GameObject to check LoS to</param> /// <param name="notifier">GameObject to Notify when Check is made</param> /// <param name="cached">Use a cached result</param> /// <param name="timeout">Cache Timeout, 0 = default</param> public void LosCheckVincinity(GameObject source, GameObject target, IDOLEventHandler notifier, bool cached = true, int timeout = 0) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_WARN) log.Warn("LOSMGR_W : Starting Vincinity Los Check Between - Source : "+source.Name+" Target : "+target.Name+"."); if(timeout == 0) timeout = GetDefaultTimeouts(source, target); // check Threshold first if(source.IsWithinRadius(target, GetDefaultThreshold(source, target), false)) { //we need an arbitrary player foreach(GamePlayer player in source.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if(player.ObjectState == GameNPC.eObjectState.Active) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Vincinity Hitted Treshold ("+GetDefaultThreshold(source, target)+") - Source : "+source.Name+" Target : "+target.Name+"."); notifier.Notify(GameObjectEvent.FinishedLosCheck, player, new LosCheckData(source, target, GameTimer.GetTickCount(), true)); return; } } } // check cache then ! if(cached) { try { bool los = GetLosCheckFromCache(source, target, timeout); //we need an arbitrary player foreach(GamePlayer player in source.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if(player.ObjectState == GameNPC.eObjectState.Active) { notifier.Notify(GameObjectEvent.FinishedLosCheck, player, new LosCheckData(source, target, GameTimer.GetTickCount(), los)); return; } } } catch (LosUnavailableException) { // we have no cache } } // check pending lock(((ICollection)PendingChecks).SyncRoot) { IEnumerable<Tuple<GamePlayer, ushort, ushort>> pendings = (from pending in PendingChecks where (pending.Key.Item2 == source.ObjectID && pending.Key.Item3 == target.ObjectID) || (pending.Key.Item2 == target.ObjectID && pending.Key.Item3 == source.ObjectID) select pending.Key).Take(1); foreach(Tuple<GamePlayer, ushort, ushort> pend in pendings) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_INFO) log.Warn("LOSMGR_I : Vincinity Registered to an other LoS - Source : "+source.Name+" Target : "+target.Name+"."); AddRegisteredEvent(new Tuple<GameObject, GameObject>(source, target), notifier); return; } } // check if source is player and available for Los check if(IsAvailableForLosCheck(source, source, target)) { LosCheck((GamePlayer)source, source, target, notifier, cached, timeout); return; } // check if target is player and available for Los check if(IsAvailableForLosCheck(target, source, target)) { LosCheck((GamePlayer)target, source, target, notifier, cached, timeout); return; } // check if source has an available owner if(source is GameNPC && ((GameNPC)source).Brain != null && ((GameNPC)source).Brain is IControlledBrain) { GamePlayer owner = ((IControlledBrain)((GameNPC)source).Brain).GetPlayerOwner(); if(owner != null && IsAvailableForLosCheck(owner, source, target)) { LosCheck(owner, source, target, notifier, cached, timeout); return; } } // check if target has an available owner if(target is GameNPC && ((GameNPC)target).Brain != null && ((GameNPC)target).Brain is IControlledBrain) { GamePlayer tgtowner = ((IControlledBrain)((GameNPC)target).Brain).GetPlayerOwner(); if(tgtowner != null && IsAvailableForLosCheck(tgtowner, source, target)) { LosCheck(tgtowner, source, target, notifier, cached, timeout); return; } } GamePlayer checker = GetBestLosChecker(source, target); if(checker != null) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_INFO) log.Warn("LOSMGR_I : Vincinity found best checker "+checker.Name+" - Source : "+source.Name+" Target : "+target.Name+"."); LosCheck(checker, source, target, notifier, cached, timeout); return; } throw new LosUnavailableException(); }
/// <summary> /// Check LoS and wait for a reply before returning /// </summary> /// <param name="player">Client used to make the LoS check</param> /// <param name="source">GameObject from witch LoS check start</param> /// <param name="target">GameObject to check LoS to</param> /// <param name="notifier">GameObject to Notify when Check is made</param> /// <param name="cached">Use a cached result</param> /// <param name="timeout">Cache Timeout, 0 = default</param> public void LosCheck(GamePlayer player, GameObject source, GameObject target, IDOLEventHandler notifier, bool cached = true, int timeout = 0) { if(player == null || source == null || target == null) throw new LosUnavailableException(); // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_WARN) log.Warn("LOSMGR_W : Starting Los Check with - Player : "+player.Name+" Source : "+source.Name+" Target : "+target.Name+"."); if(timeout <= 0) timeout = GetDefaultTimeouts(source, target); // check Threshold first if(source.IsWithinRadius(target, GetDefaultThreshold(source, target), false)) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Threshold hitted ("+GetDefaultThreshold(source, target)+") with - Player : "+player.Name+" Source : "+source.Name+" Target : "+target.Name+"."); notifier.Notify(GameObjectEvent.FinishedLosCheck, player, new LosCheckData(source, target, GameTimer.GetTickCount(), true)); return; } // check in cache then ! if(cached) { try { bool los = GetLosCheckFromCache(source, target, timeout); notifier.Notify(GameObjectEvent.FinishedLosCheck, player, new LosCheckData(source, target, GameTimer.GetTickCount(), los)); return; } catch (LosUnavailableException) { // we have no cache } } // Check if a LoS is pending, or this player is already LoS Checking... Tuple<GameObject, GameObject> cacheKey = new Tuple<GameObject, GameObject>(source, target); // We need to lock the Pending list during the checks lock(((ICollection)PendingChecks).SyncRoot) { IEnumerable<Tuple<GamePlayer, ushort, ushort>> pendings = (from pending in PendingChecks where (pending.Key.Item2 == source.ObjectID && pending.Key.Item3 == target.ObjectID) || (pending.Key.Item2 == target.ObjectID && pending.Key.Item3 == source.ObjectID) select pending.Key).Take(1); // We have pending data not too old, Register this event handler foreach(Tuple<GamePlayer, ushort, ushort> pend in pendings) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_INFO) log.Warn("LOSMGR_D : Registered to an other LoS with - Player : "+player.Name+" Source : "+source.Name+" Target : "+target.Name+"."); AddRegisteredEvent(cacheKey, notifier); return; } } // Throttle if(IsPvpLosCheck(source, target) || IsAvailableForLosCheck(player, source, target)) { // Not pending, Not in Cache, let's work AddRegisteredEvent(cacheKey, notifier); EventNotifierLosCheck(player, source, target); } else { // Get best checker ! GamePlayer checker = GetBestLosChecker(source, target); if(checker != null) { // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_WARN) log.Warn("LOSMGR_D : Deferred LoSCheck to "+checker.Name+" From - Player : "+player.Name+" Source : "+source.Name+" Target : "+target.Name+"."); AddRegisteredEvent(cacheKey, notifier); EventNotifierLosCheck(checker, source, target); } else { // the Player checker is unavailable to make this LosCheck throw new LosUnavailableException(); } } }