/// <summary> /// Broadcasts a message to players within (whatever) distance from this object /// </summary> /// <param name="obj">The object that says the message</param> /// <param name="msg">The message that the object says</param> /// <param name="distance">The distance which the message is heard</param> /// <param name="IsSaying">Is this object saying the message if false the message will drop the 'npcname says' part</param> public static void BroadcastMsg(GameObject obj, string msg, int distance, bool IsSaying) { foreach (GamePlayer bPlayer in obj.GetPlayersInRadius((ushort)distance)) { if (IsSaying) { bPlayer.Out.SendMessage(obj.Name + " says \"" + msg + "\"", eChatType.CT_Broadcast, eChatLoc.CL_ChatWindow); } else { bPlayer.Out.SendMessage(msg, eChatType.CT_Broadcast, eChatLoc.CL_ChatWindow); } } return; }
/// <summary> /// Broadcasts a message to players within saydistance from this object /// </summary> /// <param name="obj">The object that says the message</param> /// <param name="msg">The message that the object says</param> /// <param name="chattype">The chattype of the message</param> /// <param name="IsSaying">Is this object saying the message if false the message will drop the 'objname says' part</param> public static void BroadcastMsg(GameObject obj, string msg, eChatType chattype, bool IsSaying) { foreach (GamePlayer bPlayer in obj.GetPlayersInRadius((ushort)WorldMgr.SAY_DISTANCE)) { if (IsSaying) { bPlayer.Out.SendMessage(obj.Name + " says \"" + msg + "\"", chattype, eChatLoc.CL_ChatWindow); } else { bPlayer.Out.SendMessage(msg, chattype, eChatLoc.CL_ChatWindow); } } return; }
/// <summary> /// Sends a text message to players within a specific radius of another object /// </summary> /// <param name="centerObject">The center object</param> /// <param name="message">The message to send</param> /// <param name="chatType">The chat typ</param> /// <param name="chatLoc">The chat location</param> /// <param name="distance">The distance</param> /// <param name="excludes">A list of GameObjects to exlude from the message</param> public static void MessageToArea(GameObject centerObject, string message, eChatType chatType, eChatLoc chatLoc, ushort distance, params GameObject[] excludes) { if (message == null || message.Length <= 0) return; bool excluded; foreach(GamePlayer player in centerObject.GetPlayersInRadius(distance)) { excluded = false; if(excludes!=null) { foreach(GameObject obj in excludes) if(obj == player) { excluded = true; break; } } if (!excluded) { player.MessageFromArea(centerObject, message, chatType, chatLoc); } } }
/// <summary> /// Sends a message to the system window of players inside /// INFO_DISTANCE radius of the center object /// </summary> /// <param name="centerObject">The center object of the message</param> /// <param name="chatType">The type of message to send</param> /// <param name="LanguageMessageID">The language message ID</param> /// <param name="args">The Translation args</param> /// <remarks>If the centerObject is a player, he won't receive the message</remarks> public static void SystemToOthers2(GameObject centerObject, eChatType chatType, string LanguageMessageID, params object[] args) { if (LanguageMessageID == null || LanguageMessageID.Length <= 0) return; foreach (GamePlayer player in centerObject.GetPlayersInRadius(WorldMgr.INFO_DISTANCE)) { if (!(centerObject is GamePlayer && centerObject == player)) { player.MessageFromArea(centerObject, LanguageMgr.GetTranslation(player.Client.Account.Language, LanguageMessageID, args), chatType, eChatLoc.CL_SystemWindow); } } }
/// <summary> /// Update nearest object with LoS results /// </summary> /// <param name="source">source of LoS</param> /// <param name="target">target of Los</param> /// <param name="losOK">is LoS ok ?</param> /// <param name="time">current time</param> private void UpdateVincinityLosCache(GameObject source, GameObject target, bool losOK, long time) { // Take NPCs in the largest Radius, should be EvE foreach(GameNPC contamined in source.GetNPCsInRadius((ushort)LOSMGR_MAX_CONTAMINATION_RADIUS)) { if(contamined == source || contamined == target) continue; // don't give LoS results to Peace NPC if((contamined.Flags & GameNPC.eFlags.PEACE) == GameNPC.eFlags.PEACE) continue; // player pet to player should use the special PET radius if((isObjectFromPlayer(target) || isObjectFromPlayer(source)) && isObjectFromPlayer(contamined)) { // Update using PvP cache Timeout if(LOSMGR_PET_CONTAMINATION_RADIUS > 0 && source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR) <= LOSMGR_PET_CONTAMINATION_RADIUS) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Contamination Los Check (Pet PvP) of "+source.Name+" and "+target.Name+" Contaminated "+contamined.Name+", range : "+source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR)); UpdateLosCacheItem(source, target, losOK, LOSMGR_PLAYER_VS_PLAYER_CACHE_TIMEOUT, time); } continue; } // guard to anything should use guard radius if(contamined is GameKeepGuard) { // Update using PvE cache Timeout if(LOSMGR_GUARD_CONTAMINATION_RADIUS > 0 && source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR) <= LOSMGR_GUARD_CONTAMINATION_RADIUS) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Contamination Los Check (Grd PvE) of "+source.Name+" and "+target.Name+" Contaminated "+contamined.Name+", range : "+source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR)); UpdateLosCacheItem(source, target, losOK, LOSMGR_PLAYER_VS_ENVIRONMENT_CACHE_TIMEOUT, time); } continue; } // if this NPC is targetting a player it's PvE, or I'm a pet not targeting a player it's PvE too if((isObjectFromPlayer(target) || isObjectFromPlayer(source)) || isObjectFromPlayer(contamined)) { // Update using PvE cache Timeout if(LOSMGR_NPC_CONTAMINATION_RADIUS > 0 && source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR) <= LOSMGR_NPC_CONTAMINATION_RADIUS) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Contamination Los Check (Mob PvE) of "+source.Name+" and "+target.Name+" Contaminated "+contamined.Name+", range : "+source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR)); UpdateLosCacheItem(source, target, losOK, LOSMGR_PLAYER_VS_ENVIRONMENT_CACHE_TIMEOUT, time); } continue; } // else it's EvE radius if(source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR) <= LOSMGR_MAX_CONTAMINATION_RADIUS) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Contamination Los Check (Mob EvE) of "+source.Name+" and "+target.Name+" Contaminated "+contamined.Name+", range : "+source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR)); UpdateLosCacheItem(source, target, losOK, LOSMGR_ENVIRONMENT_VS_ENVIRONMENT_CACHE_TIMEOUT, time); } } // Take Player in the largest Radius, should be PvE for players foreach(GamePlayer contamined in source.GetPlayersInRadius((ushort)LOSMGR_NPC_CONTAMINATION_RADIUS)) { if(contamined == source || contamined == target) continue; // P v P if(target is GamePlayer || source is GamePlayer) { if(LOSMGR_PLAYER_CONTAMINATION_RADIUS > 0 && source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR) <= LOSMGR_PLAYER_CONTAMINATION_RADIUS) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Contamination Los Check (Pl PvP) of "+source.Name+" and "+target.Name+" Contaminated "+contamined.Name+", range : "+source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR)); UpdateLosCacheItem(source, target, losOK, LOSMGR_PLAYER_VS_PLAYER_CACHE_TIMEOUT, time); } continue; } // Player to Pet if(isObjectFromPlayer(target) || isObjectFromPlayer(source)) { if(LOSMGR_PET_CONTAMINATION_RADIUS > 0 && source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR) <= LOSMGR_PET_CONTAMINATION_RADIUS) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Contamination Los Check (Pl PvPets) of "+source.Name+" and "+target.Name+" Contaminated "+contamined.Name+", range : "+source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR)); UpdateLosCacheItem(source, target, losOK, LOSMGR_PLAYER_VS_PLAYER_CACHE_TIMEOUT, time); } continue; } if(source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR) <= LOSMGR_NPC_CONTAMINATION_RADIUS) { // FIXME debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Contamination Los Check (Pl PvE) of "+source.Name+" and "+target.Name+" Contaminated "+contamined.Name+", range : "+source.GetDistanceTo(contamined, LOSMGR_CONTAMINATION_ZFACTOR)); // else we're in PvE, a player can't be in EvE UpdateLosCacheItem(source, target, losOK, LOSMGR_PLAYER_VS_ENVIRONMENT_CACHE_TIMEOUT, time); } } }
/// <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(); }
private GamePlayer GetBestLosChecker(GameObject source, GameObject target) { // Stealthed Player can't be third-party los Checked // FIXME could use player who can detect the Stealther (Realm mate) for a third party check if(source is GamePlayer && ((GamePlayer)source).IsStealthed) { // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Vincinity Player choosen because source is stealthed - "+source.Name); return (GamePlayer)source; } if(target is GamePlayer && ((GamePlayer)target).IsStealthed) { // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Vincinity Player choosen because target is stealthed - "+target.Name); return (GamePlayer)target; } // Get all players around able to check LoS IEnumerable<GamePlayer> playersQuery = (from GamePlayer player in source.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE) select player); List<GamePlayer> players = new List<GamePlayer>(); foreach(GamePlayer test in playersQuery) { if(target.IsWithinRadius(test, WorldMgr.VISIBILITY_DISTANCE)) players.Add(test); } // first get all players that haven't done anything lock(((ICollection)ClientChecks).SyncRoot) { IEnumerable<GamePlayer> checkers = (from checker in players where !ClientChecks.ContainsKey(checker) || !ClientStats.ContainsKey(checker) select checker).Take(1); // Pick one that isn't in cache foreach(GamePlayer choosed in checkers) { // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Vincinity Player choosen because inactive - "+choosed.Name); return choosed; } } lock(((ICollection)ClientStats).SyncRoot) { long currentTime = GameTimer.GetTickCount(); // We don't have player that aren't in cache try selecting available ones (lowest count && best instant checker) IEnumerable<GamePlayer> bestavails = (from best in ClientStats.Keys where players.Contains(best) && (ClientChecks.ContainsKey(best) && (currentTime-ClientChecks[best]) > LOSMGR_PLAYER_CHECK_FREQUENCY) orderby ClientStats[best].Item1, ClientStats[best].Item3 descending select best).Take(1); // Pick the best foreach(GamePlayer choosed in bestavails) { // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Vincinity Player choosen because available and best checker - "+choosed.Name); return choosed; } // All of them are busy pick the fastest instant checker IEnumerable<GamePlayer> betters = (from best in ClientStats.Keys where players.Contains(best) orderby ClientStats[best].Item3 descending, ClientStats[best].Item2 descending select best).Take(1); // Pick the best foreach(GamePlayer choosed in betters) { // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Vincinity Player choosen because best checker even if not available - "+choosed.Name); return choosed; } } // Return any default players foreach(GamePlayer choosed in players) { // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) log.Warn("LOSMGR_D : Vincinity Player choosen because there was no one else - "+choosed.Name); return choosed; } // FIXME Debug if(LOSMGR_DEBUG_LEVEL >= LOSMGR_DEBUG_DEBUG) { string concat = ""; foreach(GamePlayer choosed in players) concat += ", "+choosed.Name; log.Warn("LOSMGR_D : Vincinity Player could not be choosen amoung"+concat); } return null; }
/// <summary> /// Sends a message to the system window of players inside /// INFO_DISTANCE radius of the center object /// </summary> /// <param name="centerObject">The center object of the message</param> /// <param name="chatType">The type of message to send</param> /// <param name="LanguageMessageID">The language message ID</param> /// <param name="args">The Translation args</param> /// <remarks>If the centerObject is a player, he won't receive the message</remarks> public static void SystemToOthers2(GameObject centerObject, eChatType chatType, string LanguageMessageID, params object[] args) { if (LanguageMessageID == null || LanguageMessageID.Length <= 0) return; //bool excluded; foreach (GamePlayer player in centerObject.GetPlayersInRadius(WorldMgr.INFO_DISTANCE)) { /* excluded = false; if (excludes != null) { foreach (GameObject obj in excludes) if (obj == player) { excluded = true; break; } } if (!excluded) */ if (!(centerObject is GamePlayer && centerObject == player)) player.Out.SendMessage(LanguageMgr.GetTranslation(player.Client, LanguageMessageID, args), chatType, eChatLoc.CL_SystemWindow); } }