Core/Groups: Fixes groups staying linked with players.

This commit is contained in:
Hondacrx
2025-09-02 22:43:56 -04:00
parent 6531cd9dc1
commit 3d23a9f162
34 changed files with 385 additions and 402 deletions
@@ -1,12 +1,28 @@
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved. // Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Framework.Collections namespace Framework.Collections
{ {
public class LinkedListElement public class LinkedListElement
{ {
internal LinkedListElement INext; internal LinkedListElement INext
internal LinkedListElement IPrev; {
get;
set
{
field = value;
}
}
internal LinkedListElement IPrev
{
get;
set
{
field = value;
}
}
public LinkedListElement() public LinkedListElement()
{ {
@@ -52,32 +68,31 @@ namespace Framework.Collections
public class LinkedListHead public class LinkedListHead
{ {
LinkedListElement _iFirst = new(); LinkedListElement iHeader = new();
LinkedListElement _iLast = new();
uint _iSize; uint _iSize;
public LinkedListHead() public LinkedListHead()
{ {
_iSize = 0; _iSize = 0;
// create empty list // create empty list
iHeader.INext = new();
_iFirst.INext = _iLast; iHeader.IPrev = new();
_iLast.IPrev = _iFirst;
} }
public bool IsEmpty() { return (!_iFirst.INext.IsInList()); } public bool IsEmpty() { return iHeader.INext == iHeader; }
public LinkedListElement GetFirstElement() { return (IsEmpty() ? null : _iFirst.INext); } public LinkedListElement GetFirstElement() { return (IsEmpty() ? null : iHeader.INext); }
public LinkedListElement GetLastElement() { return (IsEmpty() ? null : _iLast.IPrev); } public LinkedListElement GetLastElement() { return (IsEmpty() ? null : iHeader); }
public void InsertFirst(LinkedListElement pElem) public void InsertFirst(LinkedListElement pElem)
{ {
_iFirst.InsertAfter(pElem); iHeader.InsertBefore(pElem);
} }
public void InsertLast(LinkedListElement pElem) public void InsertLast(LinkedListElement pElem)
{ {
_iLast.InsertBefore(pElem); iHeader.InsertBefore(pElem);
} }
public uint GetSize() public uint GetSize()
+49 -13
View File
@@ -1,11 +1,14 @@
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved. // Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Collections; using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Framework.Dynamic namespace Framework.Dynamic
{ {
public class Reference<TO, FROM> : LinkedListElement where TO : class where FROM : class public class Reference<TO, FROM> where TO : class where FROM : class
{ {
TO _RefTo; TO _RefTo;
FROM _RefFrom; FROM _RefFrom;
@@ -21,7 +24,8 @@ namespace Framework.Dynamic
public Reference() public Reference()
{ {
_RefTo = null; _RefFrom = null; _RefTo = null;
_RefFrom = null;
} }
// Create new link // Create new link
@@ -43,7 +47,6 @@ namespace Framework.Dynamic
public void Unlink() public void Unlink()
{ {
TargetObjectDestroyLink(); TargetObjectDestroyLink();
Delink();
_RefTo = null; _RefTo = null;
_RefFrom = null; _RefFrom = null;
} }
@@ -53,7 +56,6 @@ namespace Framework.Dynamic
public void Invalidate() // the iRefFrom MUST remain!! public void Invalidate() // the iRefFrom MUST remain!!
{ {
SourceObjectDestroyLink(); SourceObjectDestroyLink();
Delink();
_RefTo = null; _RefTo = null;
} }
@@ -62,26 +64,60 @@ namespace Framework.Dynamic
return _RefTo != null; return _RefTo != null;
} }
public Reference<TO, FROM> Next() { return ((Reference<TO, FROM>)GetNextElement()); }
public Reference<TO, FROM> Prev() { return ((Reference<TO, FROM>)GetPrevElement()); }
public TO GetTarget() { return _RefTo; } public TO GetTarget() { return _RefTo; }
public FROM GetSource() { return _RefFrom; } public FROM GetSource() { return _RefFrom; }
} }
public class RefManager<TO, FROM> : LinkedListHead where TO : class where FROM : class public class RefManager<ReferenceType> : IEnumerable where ReferenceType : class, new()
{ {
LinkedList<ReferenceType> linkedList = new LinkedList<ReferenceType>();
~RefManager() { ClearReferences(); } ~RefManager() { ClearReferences(); }
public Reference<TO, FROM> GetFirst() { return (Reference<TO, FROM>)base.GetFirstElement(); } public void InsertFirst(ReferenceType pElem)
public Reference<TO, FROM> GetLast() { return (Reference<TO, FROM>)base.GetLastElement(); } {
linkedList.AddFirst(pElem);
}
public void InsertLast(ReferenceType pElem)
{
linkedList.AddLast(pElem);
}
public ReferenceType Find(Func<ReferenceType, bool> func)
{
return linkedList.FirstOrDefault(func);
}
public void Remove(Func<ReferenceType, bool> func)
{
linkedList.Remove(Find(func));
}
public int GetSize()
{
return linkedList.Count;
}
public ReferenceType GetFirst() { return linkedList.First?.Value; }
public ReferenceType GetLast() { return linkedList.Last?.Value; }
public IEnumerator<ReferenceType> GetEnumerator()
{
return linkedList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void ClearReferences() public void ClearReferences()
{ {
Reference<TO, FROM> refe; ReferenceType refe;
while ((refe = GetFirst()) != null) while ((refe = GetFirst()) != null)
refe.Invalidate(); linkedList.Remove(refe);
} }
} }
} }
+3 -3
View File
@@ -592,10 +592,10 @@ namespace Game.AI
_allySet.Add(me.GetGUID()); _allySet.Add(me.GetGUID());
if (group != null) // add group if (group != null) // add group
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player target = refe.GetSource(); Player target = groupRef.GetSource();
if (target == null || !target.IsInMap(owner) || !group.SameSubGroup(owner.ToPlayer(), target)) if (!target.IsInMap(owner) || !group.SameSubGroup(owner.ToPlayer(), target))
continue; continue;
if (target.GetGUID() == owner.GetGUID()) if (target.GetGUID() == owner.GetGUID())
@@ -83,12 +83,11 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member != null) if (member.IsInMap(player))
if (member.IsInMap(player)) member.FailQuest(_escortQuest.Id);
member.FailQuest(_escortQuest.Id);
} }
} }
else else
@@ -150,12 +149,11 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member != null) if (me.IsWithinDistInMap(member, GetMaxPlayerDistance()))
if (me.IsWithinDistInMap(member, GetMaxPlayerDistance())) return true;
return true;
} }
} }
else if (me.IsWithinDistInMap(player, GetMaxPlayerDistance())) else if (me.IsWithinDistInMap(player, GetMaxPlayerDistance()))
@@ -52,12 +52,11 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member != null) if (member.IsInMap(player))
if (member.IsInMap(player)) member.FailQuest(_questForFollow);
member.FailQuest(_questForFollow);
} }
} }
else else
@@ -109,12 +108,9 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null && (maxRangeExceeded || questAbandoned); groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member == null)
continue;
if (maxRangeExceeded && me.IsWithinDistInMap(member, 100.0f)) if (maxRangeExceeded && me.IsWithinDistInMap(member, 100.0f))
maxRangeExceeded = false; maxRangeExceeded = false;
@@ -253,10 +249,10 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member != null && me.IsWithinDistInMap(member, 100.0f) && member.IsAlive()) if (me.IsWithinDistInMap(member, 100.0f) && member.IsAlive())
{ {
Log.outDebug(LogFilter.Scripts, $"FollowerAI::GetLeaderForFollower: GetLeader changed and returned new leader. ({me.GetGUID()})"); Log.outDebug(LogFilter.Scripts, $"FollowerAI::GetLeaderForFollower: GetLeader changed and returned new leader. ({me.GetGUID()})");
_leaderGUID = member.GetGUID(); _leaderGUID = member.GetGUID();
+2 -2
View File
@@ -227,7 +227,7 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player groupGuy = groupRef.GetSource(); Player groupGuy = groupRef.GetSource();
if (!groupGuy.IsInMap(player)) if (!groupGuy.IsInMap(player))
@@ -333,7 +333,7 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player groupGuy = groupRef.GetSource(); Player groupGuy = groupRef.GetSource();
if (groupGuy.IsInMap(player) && me.GetDistance(groupGuy) <= checkDist) if (groupGuy.IsInMap(player) && me.GetDistance(groupGuy) <= checkDist)
+3 -4
View File
@@ -2889,12 +2889,11 @@ namespace Game.AI
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference groupRef = group.GetFirstMember(); groupRef != null; groupRef = groupRef.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = groupRef.GetSource(); Player member = groupRef.GetSource();
if (member != null) if (member.IsInMap(player))
if (member.IsInMap(player)) targets.Add(member);
targets.Add(member);
} }
} }
// We still add the player to the list if there is no group. If we do // We still add the player to the list if there is no group. If we do
@@ -671,7 +671,7 @@ namespace Game.Achievements
achievementEarned.Time += receiver.GetSession().GetTimezoneOffset(); achievementEarned.Time += receiver.GetSession().GetTimezoneOffset();
receiver.SendPacket(achievementEarned); receiver.SendPacket(achievementEarned);
}; };
achievementEarnedBuilder(_owner); achievementEarnedBuilder(_owner);
if (!achievement.Flags.HasAnyFlag(AchievementFlags.TrackingFlag)) if (!achievement.Flags.HasAnyFlag(AchievementFlags.TrackingFlag))
@@ -985,12 +985,11 @@ namespace Game.Achievements
Group group = referencePlayer.GetGroup(); Group group = referencePlayer.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player groupMember = refe.GetSource(); Player groupMember = groupRef.GetSource();
if (groupMember != null) if (groupMember.GetGuildId() == _owner.GetId())
if (groupMember.GetGuildId() == _owner.GetId()) ca.CompletingPlayers.Add(groupMember.GetGUID());
ca.CompletingPlayers.Add(groupMember.GetGUID());
} }
} }
} }
+13 -12
View File
@@ -9,6 +9,7 @@ using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Garrisons; using Game.Garrisons;
using Game.Groups;
using Game.Maps; using Game.Maps;
using Game.Miscellaneous; using Game.Miscellaneous;
using Game.Networking; using Game.Networking;
@@ -1725,8 +1726,8 @@ namespace Game.Achievements
var group = referencePlayer.GetGroup(); var group = referencePlayer.GetGroup();
if (group != null) if (group != null)
{ {
for (var itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRefe in group.GetMembers())
if (itr.GetSource().GetGuildId() == referencePlayer.GetGuildId()) if (groupRefe.GetSource().GetGuildId() == referencePlayer.GetGuildId())
++guildMemberCount; ++guildMemberCount;
} }
@@ -2739,8 +2740,8 @@ namespace Game.Achievements
var group = referencePlayer.GetGroup(); var group = referencePlayer.GetGroup();
if (group != null) if (group != null)
{ {
for (var itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
if (itr.GetSource() != referencePlayer && referencePlayer.m_playerData.VirtualPlayerRealm == itr.GetSource().m_playerData.VirtualPlayerRealm) if (groupRef.GetSource() != referencePlayer && referencePlayer.m_playerData.VirtualPlayerRealm == groupRef.GetSource().m_playerData.VirtualPlayerRealm)
++memberCount; ++memberCount;
} }
@@ -2845,8 +2846,8 @@ namespace Game.Achievements
if (group != null) if (group != null)
{ {
uint membersWithAchievement = 0; uint membersWithAchievement = 0;
for (var itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
if (itr.GetSource().HasAchieved((uint)secondaryAsset)) if (groupRef.GetSource().HasAchieved((uint)secondaryAsset))
++membersWithAchievement; ++membersWithAchievement;
if (membersWithAchievement > reqValue) if (membersWithAchievement > reqValue)
@@ -3283,8 +3284,8 @@ namespace Game.Achievements
if (group == null) if (group == null)
return false; return false;
for (var itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
if (itr.GetSource().GetSession().GetRecruiterId() == referencePlayer.GetSession().GetAccountId()) if (groupRef.GetSource().GetSession().GetRecruiterId() == referencePlayer.GetSession().GetAccountId())
return true; return true;
return false; return false;
@@ -3295,8 +3296,8 @@ namespace Game.Achievements
if (group == null) if (group == null)
return false; return false;
for (var itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
if (itr.GetSource().GetSession().GetAccountId() == referencePlayer.GetSession().GetRecruiterId()) if (groupRef.GetSource().GetSession().GetAccountId() == referencePlayer.GetSession().GetRecruiterId())
return true; return true;
return false; return false;
@@ -3430,8 +3431,8 @@ namespace Game.Achievements
var group = referencePlayer.GetGroup(); var group = referencePlayer.GetGroup();
if (group != null) if (group != null)
{ {
for (var itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
if (!itr.GetSource().HasAchieved(reqValue)) if (!groupRef.GetSource().HasAchieved(reqValue))
return false; return false;
} }
else if (!referencePlayer.HasAchieved(reqValue)) else if (!referencePlayer.HasAchieved(reqValue))
@@ -82,12 +82,9 @@ namespace Game.BattleGrounds
//add players from group to ginfo //add players from group to ginfo
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member == null)
continue; // this should never happen
PlayerQueueInfo pl_info = new(); PlayerQueueInfo pl_info = new();
pl_info.LastOnlineTime = lastOnlineTime; pl_info.LastOnlineTime = lastOnlineTime;
pl_info.GroupInfo = ginfo; pl_info.GroupInfo = ginfo;
+26 -37
View File
@@ -106,27 +106,24 @@ namespace Game.Chat
if (groupTarget == null) if (groupTarget == null)
return false; return false;
for (GroupReference it = groupTarget.GetFirstMember(); it != null; it = it.Next()) foreach (GroupReference groupRef in groupTarget.GetMembers())
{ {
target = it.GetSource(); target = groupRef.GetSource();
if (target != null) uint oldlevel = target.GetLevel();
if (level != oldlevel)
{ {
uint oldlevel = target.GetLevel(); target.SetLevel((uint)level);
target.InitTalentForLevel();
target.SetXP(0);
}
if (level != oldlevel) if (handler.NeedReportToTarget(target))
{ {
target.SetLevel((uint)level); if (oldlevel < level)
target.InitTalentForLevel(); target.SendSysMessage(CypherStrings.YoursLevelUp, handler.GetNameLink(), level);
target.SetXP(0); else // if (oldlevel > newlevel)
} target.SendSysMessage(CypherStrings.YoursLevelDown, handler.GetNameLink(), level);
if (handler.NeedReportToTarget(target))
{
if (oldlevel < level)
target.SendSysMessage(CypherStrings.YoursLevelUp, handler.GetNameLink(), level);
else // if (oldlevel > newlevel)
target.SendSysMessage(CypherStrings.YoursLevelDown, handler.GetNameLink(), level);
}
} }
} }
return true; return true;
@@ -248,12 +245,8 @@ namespace Game.Chat
if (groupTarget == null) if (groupTarget == null)
return false; return false;
for (GroupReference it = groupTarget.GetFirstMember(); it != null; it = it.Next()) foreach (GroupReference groupRef in groupTarget.GetMembers())
{ groupRef.GetSource().DurabilityRepairAll(false, 0, false);
Player target = it.GetSource();
if (target != null)
target.DurabilityRepairAll(false, 0, false);
}
return true; return true;
} }
@@ -270,15 +263,12 @@ namespace Game.Chat
if (groupTarget == null) if (groupTarget == null)
return false; return false;
for (GroupReference it = groupTarget.GetFirstMember(); it != null; it = it.Next()) foreach (GroupReference groupRef in groupTarget.GetMembers())
{ {
Player target = it.GetSource(); Player target = groupRef.GetSource();
if (target != null) target.ResurrectPlayer(target.GetSession().HasPermission(RBACPermissions.ResurrectWithFullHps) ? 1.0f : 0.5f);
{ target.SpawnCorpseBones();
target.ResurrectPlayer(target.GetSession().HasPermission(RBACPermissions.ResurrectWithFullHps) ? 1.0f : 0.5f); target.SaveToDB();
target.SpawnCorpseBones();
target.SaveToDB();
}
} }
return true; return true;
@@ -326,11 +316,10 @@ namespace Game.Chat
} }
} }
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == gmPlayer || player.GetSession() == null)
if (player == null || player == gmPlayer || player.GetSession() == null)
continue; continue;
// check online security // check online security
@@ -364,7 +353,7 @@ namespace Game.Chat
// stop flight if need // stop flight if need
if (player.IsInFlight()) if (player.IsInFlight())
player.FinishTaxiFlight(); player.FinishTaxiFlight();
else else
player.SaveRecallPosition(); // save only in non-flight case player.SaveRecallPosition(); // save only in non-flight case
+4 -6
View File
@@ -127,18 +127,16 @@ namespace Game.Chat
string nameLink = handler.GetNameLink(target); string nameLink = handler.GetNameLink(target);
Group grp = target.GetGroup(); Group group = target.GetGroup();
if (grp == null) if (group == null)
{ {
handler.SendSysMessage(CypherStrings.NotInGroup, nameLink); handler.SendSysMessage(CypherStrings.NotInGroup, nameLink);
return false; return false;
} }
for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == null || player.GetSession() == null)
continue;
// check online security // check online security
if (handler.HasLowerSecurity(player, ObjectGuid.Empty)) if (handler.HasLowerSecurity(player, ObjectGuid.Empty))
+51 -54
View File
@@ -397,27 +397,27 @@ namespace Game.DungeonFinding
else else
{ {
byte memberCount = 0; byte memberCount = 0;
for (GroupReference refe = grp.GetFirstMember(); refe != null && joinData.result == LfgJoinResult.Ok; refe = refe.Next()) foreach (GroupReference groupRef in grp.GetMembers())
{ {
Player groupPlayer = refe.GetSource(); Player groupPlayer = groupRef.GetSource();
if (groupPlayer != null) if (!groupPlayer.GetSession().HasPermission(RBACPermissions.JoinDungeonFinder))
joinData.result = LfgJoinResult.NoLfgObject;
if (groupPlayer.HasAura(SharedConst.LFGSpellDungeonDeserter))
joinData.result = LfgJoinResult.DeserterParty;
else if (!isContinue && groupPlayer.HasAura(SharedConst.LFGSpellDungeonCooldown))
joinData.result = LfgJoinResult.RandomCooldownParty;
else if (groupPlayer.InBattleground() || groupPlayer.InArena() || groupPlayer.InBattlegroundQueue())
joinData.result = LfgJoinResult.CantUseDungeons;
else if (groupPlayer.HasAura(9454)) // check Freeze debuff
{ {
if (!groupPlayer.GetSession().HasPermission(RBACPermissions.JoinDungeonFinder)) joinData.result = LfgJoinResult.NoSlots;
joinData.result = LfgJoinResult.NoLfgObject; joinData.playersMissingRequirement.Add(groupPlayer.GetName());
if (groupPlayer.HasAura(SharedConst.LFGSpellDungeonDeserter))
joinData.result = LfgJoinResult.DeserterParty;
else if (!isContinue && groupPlayer.HasAura(SharedConst.LFGSpellDungeonCooldown))
joinData.result = LfgJoinResult.RandomCooldownParty;
else if (groupPlayer.InBattleground() || groupPlayer.InArena() || groupPlayer.InBattlegroundQueue())
joinData.result = LfgJoinResult.CantUseDungeons;
else if (groupPlayer.HasAura(9454)) // check Freeze debuff
{
joinData.result = LfgJoinResult.NoSlots;
joinData.playersMissingRequirement.Add(groupPlayer.GetName());
}
++memberCount;
players.Add(groupPlayer.GetGUID());
} }
++memberCount;
players.Add(groupPlayer.GetGUID());
if (joinData.result != LfgJoinResult.Ok)
break;
} }
if (joinData.result == LfgJoinResult.Ok && memberCount != grp.GetMembersCount()) if (joinData.result == LfgJoinResult.Ok && memberCount != grp.GetMembersCount())
@@ -521,22 +521,19 @@ namespace Game.DungeonFinding
SetState(gguid, LfgState.Rolecheck); SetState(gguid, LfgState.Rolecheck);
// Send update to player // Send update to player
LfgUpdateData updateData = new(LfgUpdateType.JoinQueue, dungeons); LfgUpdateData updateData = new(LfgUpdateType.JoinQueue, dungeons);
for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in grp.GetMembers())
{ {
Player plrg = refe.GetSource(); Player plrg = groupRef.GetSource();
if (plrg != null) ObjectGuid pguid = plrg.GetGUID();
{ plrg.GetSession().SendLfgUpdateStatus(updateData, true);
ObjectGuid pguid = plrg.GetGUID(); SetState(pguid, LfgState.Rolecheck);
plrg.GetSession().SendLfgUpdateStatus(updateData, true); SetTicket(pguid, ticket);
SetState(pguid, LfgState.Rolecheck); if (!isContinue)
SetTicket(pguid, ticket); SetSelectedDungeons(pguid, dungeons);
if (!isContinue) roleCheck.roles[pguid] = 0;
SetSelectedDungeons(pguid, dungeons); if (!string.IsNullOrEmpty(debugNames))
roleCheck.roles[pguid] = 0; debugNames += ", ";
if (!string.IsNullOrEmpty(debugNames)) debugNames += plrg.GetName();
debugNames += ", ";
debugNames += plrg.GetName();
}
} }
// Update leader role // Update leader role
UpdateRoleCheck(gguid, guid, roles); UpdateRoleCheck(gguid, guid, roles);
@@ -615,27 +612,27 @@ namespace Game.DungeonFinding
UpdateRoleCheck(gguid); // No player to update role = LFG_ROLECHECK_ABORTED UpdateRoleCheck(gguid); // No player to update role = LFG_ROLECHECK_ABORTED
break; break;
case LfgState.Proposal: case LfgState.Proposal:
{
// Remove from Proposals
KeyValuePair<uint, LfgProposal> it = new();
ObjectGuid pguid = gguid == guid ? GetLeader(gguid) : guid;
foreach (var test in ProposalsStore)
{ {
// Remove from Proposals it = test;
KeyValuePair<uint, LfgProposal> it = new(); var itPlayer = it.Value.players.LookupByKey(pguid);
ObjectGuid pguid = gguid == guid ? GetLeader(gguid) : guid; if (itPlayer != null)
foreach (var test in ProposalsStore)
{ {
it = test; // Mark the player/leader of group who left as didn't accept the proposal
var itPlayer = it.Value.players.LookupByKey(pguid); itPlayer.accept = LfgAnswer.Deny;
if (itPlayer != null) break;
{
// Mark the player/leader of group who left as didn't accept the proposal
itPlayer.accept = LfgAnswer.Deny;
break;
}
} }
// Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
if (it.Value != null)
RemoveProposal(it, LfgUpdateType.ProposalDeclined);
break;
} }
// Remove from queue - if proposal is found, RemoveProposal will call RemoveFromQueue
if (it.Value != null)
RemoveProposal(it, LfgUpdateType.ProposalDeclined);
break;
}
case LfgState.None: case LfgState.None:
case LfgState.Raidbrowser: case LfgState.Raidbrowser:
break; break;
@@ -1303,10 +1300,10 @@ namespace Game.DungeonFinding
if (!fromOpcode) if (!fromOpcode)
{ {
// Select a player inside to be teleported to // Select a player inside to be teleported to
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player plrg = refe.GetSource(); Player plrg = groupRef.GetSource();
if (plrg != null && plrg != player && plrg.GetMapId() == dungeon.map) if (plrg != player && plrg.GetMapId() == dungeon.map)
{ {
mapid = plrg.GetMapId(); mapid = plrg.GetMapId();
x = plrg.GetPositionX(); x = plrg.GetPositionX();
@@ -1323,7 +1320,7 @@ namespace Game.DungeonFinding
player.FinishTaxiFlight(); player.FinishTaxiFlight();
if (!player.TeleportTo(new Game.Entities.TeleportLocation(){ Location = new WorldLocation(mapid, x, y, z, orientation), LfgDungeonsId = dungeon.id })) if (!player.TeleportTo(new Game.Entities.TeleportLocation() { Location = new WorldLocation(mapid, x, y, z, orientation), LfgDungeonsId = dungeon.id }))
error = LfgTeleportResult.NoReturnLocation; error = LfgTeleportResult.NoReturnLocation;
} }
else else
+6 -6
View File
@@ -1178,10 +1178,10 @@ namespace Game.Entities
foreach (Group partyToForceIntoCombat in partiesToForceIntoCombat) foreach (Group partyToForceIntoCombat in partiesToForceIntoCombat)
{ {
for (GroupReference refe = partyToForceIntoCombat.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in partyToForceIntoCombat.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == null || !player.IsInWorld || player.GetMap() != GetMap() || player.IsGameMaster()) if (!player.IsInWorld || player.GetMap() != GetMap() || player.IsGameMaster())
continue; continue;
EngageWithTarget(player); EngageWithTarget(player);
@@ -1334,9 +1334,9 @@ namespace Game.Entities
{ {
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
for (var itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
if (GetMap().IsRaid() || group.SameSubGroup(player, itr.GetSource())) if (GetMap().IsRaid() || group.SameSubGroup(player, groupRef.GetSource()))
m_tapList.Add(itr.GetSource().GetGUID()); m_tapList.Add(groupRef.GetSource().GetGUID());
} }
if (m_tapList.Count >= SharedConst.CreatureTappersSoftCap) if (m_tapList.Count >= SharedConst.CreatureTappersSoftCap)
@@ -1966,12 +1966,11 @@ namespace Game.Entities
Group group = player.GetGroup(); Group group = player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member != null) if (member.IsAtGroupRewardDistance(this))
if (member.IsAtGroupRewardDistance(this)) member.KillCreditGO(info.entry, GetGUID());
member.KillCreditGO(info.entry, GetGUID());
} }
} }
else else
@@ -3763,6 +3763,11 @@ namespace Game.Entities
public void SetLocationInstanceId(uint _instanceId) { instanceId = _instanceId; } public void SetLocationInstanceId(uint _instanceId) { instanceId = _instanceId; }
public override string ToString()
{
return GetName();
}
#region Fields #region Fields
public TypeMask ObjectTypeMask { get; set; } public TypeMask ObjectTypeMask { get; set; }
protected TypeId ObjectTypeId { get; set; } protected TypeId ObjectTypeId { get; set; }
+21 -27
View File
@@ -104,27 +104,24 @@ namespace Game.Entities
if (group != null) if (group != null)
{ {
// 2. In case when player is in group, initialize variables necessary for group calculations: // 2. In case when player is in group, initialize variables necessary for group calculations:
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member != null) if (killer == member || (member.IsAtGroupRewardDistance(_victim) && member.IsAlive()))
{ {
if (killer == member || (member.IsAtGroupRewardDistance(_victim) && member.IsAlive())) uint lvl = member.GetLevel();
{ // 2.1. _count - number of alive group members within reward distance;
uint lvl = member.GetLevel(); ++_count;
// 2.1. _count - number of alive group members within reward distance; // 2.2. _sumLevel - sum of levels of alive group members within reward distance;
++_count; _sumLevel += lvl;
// 2.2. _sumLevel - sum of levels of alive group members within reward distance; // 2.3. _maxLevel - maximum level of alive group member within reward distance;
_sumLevel += lvl; if (_maxLevel < lvl)
// 2.3. _maxLevel - maximum level of alive group member within reward distance; _maxLevel = (byte)lvl;
if (_maxLevel < lvl) // 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance,
_maxLevel = (byte)lvl; // for whom victim is not gray;
// 2.4. _maxNotGrayMember - maximum level of alive group member within reward distance, uint grayLevel = Formulas.GetGrayLevel(lvl);
// for whom victim is not gray; if (_victim.GetLevelForTarget(member) > grayLevel && (_maxNotGrayMember == null || _maxNotGrayMember.GetLevel() < lvl))
uint grayLevel = Formulas.GetGrayLevel(lvl); _maxNotGrayMember = member;
if (_victim.GetLevelForTarget(member) > grayLevel && (_maxNotGrayMember == null || _maxNotGrayMember.GetLevel() < lvl))
_maxNotGrayMember = member;
}
} }
} }
// 2.5. _isFullXP - flag identifying that for all group members victim is not gray, // 2.5. _isFullXP - flag identifying that for all group members victim is not gray,
@@ -254,15 +251,12 @@ namespace Game.Entities
_groupRate = Formulas.XPInGroupRate(_count, isRaid); _groupRate = Formulas.XPInGroupRate(_count, isRaid);
} }
// 3.1.3. Reward each group member (even dead or corpse) within reward distance. // 3.1.3. Reward each group member (even dead or corpse) within reward distance.
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member != null) // Killer may not be at reward distance, check directly
{ if (killer == member || member.IsAtGroupRewardDistance(_victim))
// Killer may not be at reward distance, check directly _RewardPlayer(member, isDungeon);
if (killer == member || member.IsAtGroupRewardDistance(_victim))
_RewardPlayer(member, isDungeon);
}
} }
} }
} }
+2 -5
View File
@@ -40,12 +40,9 @@ namespace Game.Entities
Group group = GetGroup(); Group group = GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == null)
continue;
if (!player.IsAtGroupRewardDistance(pRewardSource)) if (!player.IsAtGroupRewardDistance(pRewardSource))
continue; // member (alive or dead) or his corpse at req. distance continue; // member (alive or dead) or his corpse at req. distance
+14 -14
View File
@@ -18,14 +18,14 @@ namespace Game.Entities
List<Player> nearMembers = new(); List<Player> nearMembers = new();
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player Target = refe.GetSource(); Player target = groupRef.GetSource();
// IsHostileTo check duel and controlled by enemy // IsHostileTo check duel and controlled by enemy
if (Target != null && Target != this && IsWithinDistInMap(Target, radius) && if (target != this && IsWithinDistInMap(target, radius) &&
!Target.HasInvisibilityAura() && !IsHostileTo(Target)) !target.HasInvisibilityAura() && !IsHostileTo(target))
nearMembers.Add(Target); nearMembers.Add(target);
} }
if (nearMembers.Empty()) if (nearMembers.Empty())
@@ -37,13 +37,13 @@ namespace Game.Entities
public PartyResult CanUninviteFromGroup(ObjectGuid guidMember, byte? partyIndex) public PartyResult CanUninviteFromGroup(ObjectGuid guidMember, byte? partyIndex)
{ {
Group grp = GetGroup(partyIndex); Group group = GetGroup(partyIndex);
if (grp == null) if (group == null)
return PartyResult.NotInGroup; return PartyResult.NotInGroup;
if (grp.IsLFGGroup()) if (group.IsLFGGroup())
{ {
ObjectGuid gguid = grp.GetGUID(); ObjectGuid gguid = group.GetGUID();
if (Global.LFGMgr.GetKicksLeft(gguid) == 0) if (Global.LFGMgr.GetKicksLeft(gguid) == 0)
return PartyResult.PartyLfgBootLimit; return PartyResult.PartyLfgBootLimit;
@@ -51,7 +51,7 @@ namespace Game.Entities
if (Global.LFGMgr.IsVoteKickActive(gguid)) if (Global.LFGMgr.IsVoteKickActive(gguid))
return PartyResult.PartyLfgBootInProgress; return PartyResult.PartyLfgBootInProgress;
if (grp.GetMembersCount() <= SharedConst.LFGKickVotesNeeded) if (group.GetMembersCount() <= SharedConst.LFGKickVotesNeeded)
return PartyResult.PartyLfgBootTooFewPlayers; return PartyResult.PartyLfgBootTooFewPlayers;
if (state == LfgState.FinishedDungeon) if (state == LfgState.FinishedDungeon)
@@ -62,8 +62,8 @@ namespace Game.Entities
return PartyResult.PartyLfgBootLootRolls; return PartyResult.PartyLfgBootLootRolls;
// @todo Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer. // @todo Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer.
for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
if (refe.GetSource() != null && refe.GetSource().IsInMap(this) && refe.GetSource().IsInCombat()) if (groupRef.GetSource().IsInMap(this) && groupRef.GetSource().IsInCombat())
return PartyResult.PartyLfgBootInCombat; return PartyResult.PartyLfgBootInCombat;
/* Missing support for these types /* Missing support for these types
@@ -73,13 +73,13 @@ namespace Game.Entities
} }
else else
{ {
if (!grp.IsLeader(GetGUID()) && !grp.IsAssistant(GetGUID())) if (!group.IsLeader(GetGUID()) && !group.IsAssistant(GetGUID()))
return PartyResult.NotLeader; return PartyResult.NotLeader;
if (InBattleground()) if (InBattleground())
return PartyResult.InviteRestricted; return PartyResult.InviteRestricted;
if (grp.IsLeader(guidMember)) if (group.IsLeader(guidMember))
return PartyResult.NotLeader; return PartyResult.NotLeader;
} }
+4 -5
View File
@@ -2442,12 +2442,11 @@ namespace Game.Entities
var group = GetGroup(); var group = GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
// for any leave or dead (with not released body) group member at appropriate distance // for any leave or dead (with not released body) group member at appropriate distance
if (player != null && player.IsAtGroupRewardDistance(pEventObject) && player.GetCorpse() == null) if (player.IsAtGroupRewardDistance(pEventObject) && player.GetCorpse() == null)
player.AreaExploredOrEventHappens(questId); player.AreaExploredOrEventHappens(questId);
} }
} }
@@ -3481,7 +3480,7 @@ namespace Game.Entities
{ {
if (IsQuestRewarded(questObjective.QuestID) || IsQuestObjectiveComplete(questObjective.QuestID, questObjective.Id)) if (IsQuestRewarded(questObjective.QuestID) || IsQuestObjectiveComplete(questObjective.QuestID, questObjective.Id))
return SpawnTrackingState.Complete; return SpawnTrackingState.Complete;
if (GetQuestStatus(questObjective.QuestID) != QuestStatus.None && IsQuestObjectiveCompletable(questObjective.QuestID, questObjective.Id)) if (GetQuestStatus(questObjective.QuestID) != QuestStatus.None && IsQuestObjectiveCompletable(questObjective.QuestID, questObjective.Id))
{ {
var itr = m_QuestStatus.LookupByKey(questObjective.QuestID); var itr = m_QuestStatus.LookupByKey(questObjective.QuestID);
+5 -5
View File
@@ -147,6 +147,9 @@ namespace Game.Entities
WorldMgr.DecreasePlayerCount(); WorldMgr.DecreasePlayerCount();
m_group.Dispose();
m_originalGroup.Dispose();
base.Dispose(); base.Dispose();
} }
@@ -7531,12 +7534,9 @@ namespace Game.Entities
Group group = GetGroup(); Group group = GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == null)
continue;
if (!player.IsAtRecruitAFriendDistance(this)) if (!player.IsAtRecruitAFriendDistance(this))
continue; // member (alive or dead) or his corpse at req. distance continue; // member (alive or dead) or his corpse at req. distance
+3 -3
View File
@@ -123,10 +123,10 @@ namespace Game.Entities
Group group = owner.GetGroup(); Group group = owner.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player target = refe.GetSource(); Player target = groupRef.GetSource();
if (target != null && target.IsInMap(owner) && group.SameSubGroup(owner, target)) if (target.IsInMap(owner) && group.SameSubGroup(owner, target))
target.RemoveAurasDueToSpell(GetSpell(), GetGUID()); target.RemoveAurasDueToSpell(GetSpell(), GetGUID());
} }
} }
+10 -13
View File
@@ -3382,21 +3382,18 @@ namespace Game.Entities
List<Unit> nearMembers = new(); List<Unit> nearMembers = new();
// reserve place for players and pets because resizing vector every unit push is unefficient (vector is reallocated then) // reserve place for players and pets because resizing vector every unit push is unefficient (vector is reallocated then)
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player target = refe.GetSource(); Player target = groupRef.GetSource();
if (target != null) // IsHostileTo check duel and controlled by enemy
{ if (target != this && IsWithinDistInMap(target, radius) && target.IsAlive() && !IsHostileTo(target))
// IsHostileTo check duel and controlled by enemy nearMembers.Add(target);
if (target != this && IsWithinDistInMap(target, radius) && target.IsAlive() && !IsHostileTo(target))
nearMembers.Add(target);
// Push player's pet to vector // Push player's pet to vector
Unit pet = target.GetGuardianPet(); Unit pet = target.GetGuardianPet();
if (pet != null) if (pet != null)
if (pet != this && IsWithinDistInMap(pet, radius) && pet.IsAlive() && !IsHostileTo(pet)) if (pet != this && IsWithinDistInMap(pet, radius) && pet.IsAlive() && !IsHostileTo(pet))
nearMembers.Add(pet); nearMembers.Add(pet);
}
} }
if (nearMembers.Empty()) if (nearMembers.Empty())
+51 -74
View File
@@ -487,27 +487,24 @@ namespace Game.Groups
UpdateObject groupDataPacket; UpdateObject groupDataPacket;
// Broadcast group members' fields to player // Broadcast group members' fields to player
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
if (refe.GetSource() == player) Player existingMember = groupRef.GetSource();
if (existingMember == player)
continue; continue;
Player existingMember = refe.GetSource(); if (player.HaveAtClient(existingMember))
if (existingMember != null) existingMember.BuildValuesUpdateBlockForPlayerWithFlag(groupData, UpdateFieldFlag.PartyMember, player);
{
if (player.HaveAtClient(existingMember))
existingMember.BuildValuesUpdateBlockForPlayerWithFlag(groupData, UpdateFieldFlag.PartyMember, player);
if (existingMember.HaveAtClient(player)) if (existingMember.HaveAtClient(player))
{
UpdateData newData = new(player.GetMapId());
UpdateObject newDataPacket;
player.BuildValuesUpdateBlockForPlayerWithFlag(newData, UpdateFieldFlag.PartyMember, existingMember);
if (newData.HasData())
{ {
UpdateData newData = new(player.GetMapId()); newData.BuildPacket(out newDataPacket);
UpdateObject newDataPacket; existingMember.SendPacket(newDataPacket);
player.BuildValuesUpdateBlockForPlayerWithFlag(newData, UpdateFieldFlag.PartyMember, existingMember);
if (newData.HasData())
{
newData.BuildPacket(out newDataPacket);
existingMember.SendPacket(newDataPacket);
}
} }
} }
} }
@@ -531,17 +528,14 @@ namespace Game.Groups
Player player = Global.ObjAccessor.FindConnectedPlayer(guid); Player player = Global.ObjAccessor.FindConnectedPlayer(guid);
if (player != null) if (player != null)
{ {
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
Player groupMember = refe.GetSource(); Player groupMember = groupRef.GetSource();
if (groupMember != null) if (groupMember.GetGUID() == guid)
{ continue;
if (groupMember.GetGUID() == guid)
continue;
groupMember.RemoveAllGroupBuffsFromCaster(guid); groupMember.RemoveAllGroupBuffsFromCaster(guid);
player.RemoveAllGroupBuffsFromCaster(groupMember.GetGUID()); player.RemoveAllGroupBuffsFromCaster(groupMember.GetGUID());
}
} }
} }
@@ -925,37 +919,36 @@ namespace Game.Groups
PartyMemberFullState packet = new(); PartyMemberFullState packet = new();
packet.Initialize(player); packet.Initialize(player);
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member != null && member != player && (!member.IsInMap(player) || !member.IsWithinDist(player, member.GetSightRange(), false))) if (member != player && (!member.IsInMap(player) || !member.IsWithinDist(player, member.GetSightRange(), false)))
member.SendPacket(packet); member.SendPacket(packet);
} }
} }
public void BroadcastAddonMessagePacket(ServerPacket packet, string prefix, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignore = default) public void BroadcastAddonMessagePacket(ServerPacket packet, string prefix, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignore = default)
{ {
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == null || (!ignore.IsEmpty() && player.GetGUID() == ignore) || (ignorePlayersInBGRaid && player.GetGroup() != this)) if ((!ignore.IsEmpty() && player.GetGUID() == ignore) || (ignorePlayersInBGRaid && player.GetGroup() != this))
continue; continue;
if ((group == -1 || refe.GetSubGroup() == group)) if (player.GetSession().IsAddonRegistered(prefix) && (group == -1 || groupRef.GetSubGroup() == group))
if (player.GetSession().IsAddonRegistered(prefix)) player.SendPacket(packet);
player.SendPacket(packet);
} }
} }
public void BroadcastPacket(ServerPacket packet, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignore = default) public void BroadcastPacket(ServerPacket packet, bool ignorePlayersInBGRaid, int group = -1, ObjectGuid ignore = default)
{ {
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == null || (!ignore.IsEmpty() && player.GetGUID() == ignore) || (ignorePlayersInBGRaid && player.GetGroup() != this)) if ((!ignore.IsEmpty() && player.GetGUID() == ignore) || (ignorePlayersInBGRaid && player.GetGroup() != this))
continue; continue;
if (player.GetSession() != null && (group == -1 || refe.GetSubGroup() == group)) if (group == -1 || groupRef.GetSubGroup() == group)
player.SendPacket(packet); player.SendPacket(packet);
} }
} }
@@ -1183,11 +1176,12 @@ namespace Game.Groups
return GroupJoinBattlegroundResult.None; // ERR_GROUP_JOIN_Battleground_TOO_MANY handled on client side return GroupJoinBattlegroundResult.None; // ERR_GROUP_JOIN_Battleground_TOO_MANY handled on client side
// get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.) // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
Player reference = GetFirstMember().GetSource(); var membersRefe = GetMembers().GetFirst();
// no reference found, can't join this way // no reference found, can't join this way
if (reference == null) if (membersRefe == null)
return GroupJoinBattlegroundResult.BattlegroundJoinFailed; return GroupJoinBattlegroundResult.BattlegroundJoinFailed;
Player reference = membersRefe.GetSource();
PvpDifficultyRecord bracketEntry = Global.DB2Mgr.GetBattlegroundBracketByLevel((uint)bgOrTemplate.MapIDs[0], reference.GetLevel()); PvpDifficultyRecord bracketEntry = Global.DB2Mgr.GetBattlegroundBracketByLevel((uint)bgOrTemplate.MapIDs[0], reference.GetLevel());
if (bracketEntry == null) if (bracketEntry == null)
return GroupJoinBattlegroundResult.BattlegroundJoinFailed; return GroupJoinBattlegroundResult.BattlegroundJoinFailed;
@@ -1198,9 +1192,9 @@ namespace Game.Groups
// check every member of the group to be able to join // check every member of the group to be able to join
memberscount = 0; memberscount = 0;
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next(), ++memberscount) foreach (GroupReference groupRef in GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
// offline member? don't let join // offline member? don't let join
if (member == null) if (member == null)
return GroupJoinBattlegroundResult.BattlegroundJoinFailed; return GroupJoinBattlegroundResult.BattlegroundJoinFailed;
@@ -1243,6 +1237,8 @@ namespace Game.Groups
return GroupJoinBattlegroundResult.BattlegroundJoinFailed; return GroupJoinBattlegroundResult.BattlegroundJoinFailed;
if (isMercenary != (member.HasAura(BattlegroundConst.SpellMercenaryContractHorde) || member.HasAura(BattlegroundConst.SpellMercenaryContractAlliance))) if (isMercenary != (member.HasAura(BattlegroundConst.SpellMercenaryContractHorde) || member.HasAura(BattlegroundConst.SpellMercenaryContractAlliance)))
return GroupJoinBattlegroundResult.BattlegroundJoinMercenary; return GroupJoinBattlegroundResult.BattlegroundJoinMercenary;
memberscount++;
} }
errorGuid = ObjectGuid.Empty; errorGuid = ObjectGuid.Empty;
@@ -1267,12 +1263,9 @@ namespace Game.Groups
DB.Characters.Execute(stmt); DB.Characters.Execute(stmt);
} }
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player.GetSession() == null)
continue;
player.SetDungeonDifficultyID(difficulty); player.SetDungeonDifficultyID(difficulty);
player.SendDungeonDifficulty(); player.SendDungeonDifficulty();
} }
@@ -1291,12 +1284,9 @@ namespace Game.Groups
DB.Characters.Execute(stmt); DB.Characters.Execute(stmt);
} }
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player.GetSession() == null)
continue;
player.SetRaidDifficultyID(difficulty); player.SetRaidDifficultyID(difficulty);
player.SendRaidDifficulty(false); player.SendRaidDifficulty(false);
} }
@@ -1315,12 +1305,9 @@ namespace Game.Groups
DB.Characters.Execute(stmt); DB.Characters.Execute(stmt);
} }
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player.GetSession() == null)
continue;
player.SetLegacyRaidDifficultyID(difficulty); player.SetLegacyRaidDifficultyID(difficulty);
player.SendRaidDifficulty(true); player.SendRaidDifficulty(true);
} }
@@ -1348,9 +1335,9 @@ namespace Game.Groups
public void ResetInstances(InstanceResetMethod method, Player notifyPlayer) public void ResetInstances(InstanceResetMethod method, Player notifyPlayer)
{ {
for (GroupInstanceReference refe = m_ownedInstancesMgr.GetFirst(); refe != null; refe = refe.Next()) foreach (GroupInstanceReference groupInstanceRef in m_ownedInstancesMgr)
{ {
InstanceMap map = refe.GetSource(); InstanceMap map = groupInstanceRef.GetSource();
switch (map.Reset(method)) switch (map.Reset(method))
{ {
case InstanceResetResult.Success: case InstanceResetResult.Success:
@@ -1795,19 +1782,9 @@ namespace Game.Groups
m_memberMgr.InsertFirst(pRef); m_memberMgr.InsertFirst(pRef);
} }
void DelinkMember(ObjectGuid guid) public void DelinkMember(ObjectGuid guid)
{ {
GroupReference refe = m_memberMgr.GetFirst(); m_memberMgr.Remove(p => p.GetSource().GetGUID() == guid);
while (refe != null)
{
GroupReference nextRef = refe.Next();
if (refe.GetSource().GetGUID() == guid)
{
refe.Unlink();
break;
}
refe = nextRef;
}
} }
void _initRaidSubGroupsCounter() void _initRaidSubGroupsCounter()
@@ -1915,7 +1892,7 @@ namespace Game.Groups
public uint GetDbStoreId() { return m_dbStoreId; } public uint GetDbStoreId() { return m_dbStoreId; }
public List<MemberSlot> GetMemberSlots() { return m_memberSlots; } public List<MemberSlot> GetMemberSlots() { return m_memberSlots; }
public GroupReference GetFirstMember() { return (GroupReference)m_memberMgr.GetFirst(); } public GroupRefManager GetMembers() { return m_memberMgr; }
public uint GetMembersCount() { return (uint)m_memberSlots.Count; } public uint GetMembersCount() { return (uint)m_memberSlots.Count; }
public uint GetInviteeCount() { return (uint)m_invitees.Count; } public uint GetInviteeCount() { return (uint)m_invitees.Count; }
public GroupFlags GetGroupFlags() { return m_groupFlags; } public GroupFlags GetGroupFlags() { return m_groupFlags; }
@@ -1924,8 +1901,8 @@ namespace Game.Groups
public void BroadcastWorker(Action<Player> worker) public void BroadcastWorker(Action<Player> worker)
{ {
for (GroupReference refe = GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in GetMembers())
worker(refe.GetSource()); worker(groupRef.GetSource());
} }
public ObjectGuid GetRecentInstanceOwner(uint mapId) public ObjectGuid GetRecentInstanceOwner(uint mapId)
+2 -7
View File
@@ -8,9 +8,7 @@ namespace Game.Groups
{ {
public class GroupInstanceReference : Reference<Group, InstanceMap> public class GroupInstanceReference : Reference<Group, InstanceMap>
{ {
~GroupInstanceReference() { Unlink(); } public void Dispose() { Unlink(); }
public new GroupInstanceReference Next() { return (GroupInstanceReference)base.Next(); }
public override void TargetObjectBuildLink() public override void TargetObjectBuildLink()
{ {
@@ -18,8 +16,5 @@ namespace Game.Groups
} }
} }
class GroupInstanceRefManager : RefManager<Group, InstanceMap> class GroupInstanceRefManager : RefManager<GroupInstanceReference> { }
{
public new GroupInstanceReference GetFirst() { return (GroupInstanceReference)base.GetFirst(); }
}
} }
+6 -6
View File
@@ -13,14 +13,17 @@ namespace Game.Groups
iSubGroup = 0; iSubGroup = 0;
} }
~GroupReference() { Unlink(); } public void Dispose() { Unlink(); }
public override void TargetObjectBuildLink() public override void TargetObjectBuildLink()
{ {
GetTarget().LinkMember(this); GetTarget().LinkMember(this);
} }
public new GroupReference Next() { return (GroupReference)base.Next(); } public override void TargetObjectDestroyLink()
{
GetTarget()?.DelinkMember(GetSource().GetGUID());
}
public byte GetSubGroup() { return iSubGroup; } public byte GetSubGroup() { return iSubGroup; }
@@ -29,8 +32,5 @@ namespace Game.Groups
byte iSubGroup; byte iSubGroup;
} }
public class GroupRefManager : RefManager<Group, Player> public class GroupRefManager : RefManager<GroupReference> { }
{
public new GroupReference GetFirst() { return (GroupReference)base.GetFirst(); }
}
} }
+16 -22
View File
@@ -86,7 +86,7 @@ namespace Game
GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult.None; GroupJoinBattlegroundResult err = GroupJoinBattlegroundResult.None;
Group grp = _player.GetGroup(); Group group = _player.GetGroup();
Team getQueueTeam() Team getQueueTeam()
{ {
@@ -105,7 +105,7 @@ namespace Game
BattlefieldStatusFailed battlefieldStatusFailed; BattlefieldStatusFailed battlefieldStatusFailed;
// check queue conditions // check queue conditions
if (grp == null) if (group == null)
{ {
if (GetPlayer().IsUsingLfg()) if (GetPlayer().IsUsingLfg())
{ {
@@ -177,12 +177,12 @@ namespace Game
} }
else else
{ {
if (grp.GetLeaderGUID() != GetPlayer().GetGUID()) if (group.GetLeaderGUID() != GetPlayer().GetGUID())
return; return;
ObjectGuid errorGuid; ObjectGuid errorGuid;
err = grp.CanJoinBattlegroundQueue(bgTemplate, bgQueueTypeId, 0, bgTemplate.GetMaxPlayersPerTeam(), false, 0, out errorGuid); err = group.CanJoinBattlegroundQueue(bgTemplate, bgQueueTypeId, 0, bgTemplate.GetMaxPlayersPerTeam(), false, 0, out errorGuid);
isPremade = (grp.GetMembersCount() >= bgTemplate.GetMinPlayersPerTeam()); isPremade = (group.GetMembersCount() >= bgTemplate.GetMinPlayersPerTeam());
BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId); BattlegroundQueue bgQueue = Global.BattlegroundMgr.GetBattlegroundQueue(bgQueueTypeId);
GroupQueueInfo ginfo = null; GroupQueueInfo ginfo = null;
@@ -191,16 +191,13 @@ namespace Game
if (err == 0) if (err == 0)
{ {
Log.outDebug(LogFilter.Battleground, "Battleground: the following players are joining as group:"); Log.outDebug(LogFilter.Battleground, "Battleground: the following players are joining as group:");
ginfo = bgQueue.AddGroup(GetPlayer(), grp, getQueueTeam(), bracketEntry, isPremade, 0, 0); ginfo = bgQueue.AddGroup(GetPlayer(), group, getQueueTeam(), bracketEntry, isPremade, 0, 0);
avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId()); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
} }
for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member == null)
continue; // this should never happen
if (err != 0) if (err != 0)
{ {
BattlefieldStatusFailed battlefieldStatus; BattlefieldStatusFailed battlefieldStatus;
@@ -510,11 +507,11 @@ namespace Game
if (bracketEntry == null) if (bracketEntry == null)
return; return;
Group grp = GetPlayer().GetGroup(); Group group = GetPlayer().GetGroup();
// no group found, error // no group found, error
if (grp == null) if (group == null)
return; return;
if (grp.GetLeaderGUID() != GetPlayer().GetGUID()) if (group.GetLeaderGUID() != GetPlayer().GetGUID())
return; return;
uint ateamId = GetPlayer().GetArenaTeamId(packet.TeamSizeIndex); uint ateamId = GetPlayer().GetArenaTeamId(packet.TeamSizeIndex);
@@ -525,7 +522,7 @@ namespace Game
// get the team rating for queuing // get the team rating for queuing
uint arenaRating = at.GetRating(); uint arenaRating = at.GetRating();
uint matchmakerRating = at.GetAverageMMR(grp); uint matchmakerRating = at.GetAverageMMR(group);
// the arenateam id must match for everyone in the group // the arenateam id must match for everyone in the group
if (arenaRating <= 0) if (arenaRating <= 0)
@@ -537,21 +534,18 @@ namespace Game
GroupQueueInfo ginfo = null; GroupQueueInfo ginfo = null;
ObjectGuid errorGuid; ObjectGuid errorGuid;
var err = grp.CanJoinBattlegroundQueue(bgTemplate, bgQueueTypeId, (uint)arenatype, (uint)arenatype, true, packet.TeamSizeIndex, out errorGuid); var err = group.CanJoinBattlegroundQueue(bgTemplate, bgQueueTypeId, (uint)arenatype, (uint)arenatype, true, packet.TeamSizeIndex, out errorGuid);
if (err == 0) if (err == 0)
{ {
Log.outDebug(LogFilter.Battleground, "Battleground: arena team id {0}, leader {1} queued with matchmaker rating {2} for type {3}", GetPlayer().GetArenaTeamId(packet.TeamSizeIndex), GetPlayer().GetName(), matchmakerRating, arenatype); Log.outDebug(LogFilter.Battleground, "Battleground: arena team id {0}, leader {1} queued with matchmaker rating {2} for type {3}", GetPlayer().GetArenaTeamId(packet.TeamSizeIndex), GetPlayer().GetName(), matchmakerRating, arenatype);
ginfo = bgQueue.AddGroup(GetPlayer(), grp, _player.GetTeam(), bracketEntry, false, arenaRating, matchmakerRating, ateamId); ginfo = bgQueue.AddGroup(GetPlayer(), group, _player.GetTeam(), bracketEntry, false, arenaRating, matchmakerRating, ateamId);
avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId()); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry.GetBracketId());
} }
for (GroupReference refe = grp.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member == null)
continue;
if (err != 0) if (err != 0)
{ {
BattlefieldStatusFailed battlefieldStatus; BattlefieldStatusFailed battlefieldStatus;
+5 -5
View File
@@ -158,7 +158,7 @@ namespace Game
if (group == null) if (group == null)
return; return;
if (packet.PartyIndex != 0 && group.GetGroupCategory() != (GroupCategory)packet.PartyIndex) if (packet.PartyIndex.HasValue && group.GetGroupCategory() != (GroupCategory)packet.PartyIndex)
return; return;
if (packet.Accept) if (packet.Accept)
@@ -702,9 +702,9 @@ namespace Game
broadcastPingUnit.SpellOverrideNameID = pingUnit.SpellOverrideNameID; broadcastPingUnit.SpellOverrideNameID = pingUnit.SpellOverrideNameID;
broadcastPingUnit.Write(); broadcastPingUnit.Write();
for (GroupReference itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = itr.GetSource(); Player member = groupRef.GetSource();
if (_player == member || !_player.IsInMap(member)) if (_player == member || !_player.IsInMap(member))
continue; continue;
@@ -732,9 +732,9 @@ namespace Game
broadcastPingWorldPoint.PingDuration = pingWorldPoint.PingDuration; broadcastPingWorldPoint.PingDuration = pingWorldPoint.PingDuration;
broadcastPingWorldPoint.Write(); broadcastPingWorldPoint.Write();
for (GroupReference itr = group.GetFirstMember(); itr != null; itr = itr.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = itr.GetSource(); Player member = groupRef.GetSource();
if (_player == member || !_player.IsInMap(member)) if (_player == member || !_player.IsInMap(member))
continue; continue;
+2 -5
View File
@@ -205,12 +205,9 @@ namespace Game
LfgPartyInfo lfgPartyInfo = new(); LfgPartyInfo lfgPartyInfo = new();
// Get the Locked dungeons of the other party members // Get the Locked dungeons of the other party members
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player plrg = refe.GetSource(); Player plrg = groupRef.GetSource();
if (plrg == null)
continue;
ObjectGuid pguid = plrg.GetGUID(); ObjectGuid pguid = plrg.GetGUID();
if (pguid == guid) if (pguid == guid)
continue; continue;
+2 -5
View File
@@ -99,12 +99,9 @@ namespace Game
Group group = player.GetGroup(); Group group = player.GetGroup();
List<Player> playersNear = new(); List<Player> playersNear = new();
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player member = refe.GetSource(); Player member = groupRef.GetSource();
if (member == null)
continue;
if (!loot.HasAllowedLooter(member.GetGUID())) if (!loot.HasAllowedLooter(member.GetGUID()))
continue; continue;
+6 -8
View File
@@ -126,11 +126,10 @@ namespace Game
var group = _player.GetGroup(); var group = _player.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();
if (player == _player || !player.IsInMap(_player)) // not self and in same map
if (player == null || player == _player || !player.IsInMap(_player)) // not self and in same map
continue; continue;
if (player.CanTakeQuest(quest, true)) if (player.CanTakeQuest(quest, true))
@@ -551,11 +550,10 @@ namespace Game
return; return;
} }
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player receiver = refe.GetSource(); Player receiver = groupRef.GetSource();
if (receiver == sender)
if (receiver == null || receiver == sender)
continue; continue;
if (!receiver.GetPlayerSharingQuest().IsEmpty()) if (!receiver.GetPlayerSharingQuest().IsEmpty())
+4 -5
View File
@@ -936,12 +936,11 @@ namespace Game.Loots
if (loot_type == LootType.Corpse) if (loot_type == LootType.Corpse)
roundRobinPlayer = lootOwner.GetGUID(); roundRobinPlayer = lootOwner.GetGUID();
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player player = refe.GetSource(); Player player = groupRef.GetSource();// should actually be looted object instead of lootOwner but looter has to be really close so doesnt really matter
if (player != null) // should actually be looted object instead of lootOwner but looter has to be really close so doesnt really matter if (player.IsAtGroupRewardDistance(lootOwner))
if (player.IsAtGroupRewardDistance(lootOwner)) FillNotNormalLootFor(player);
FillNotNormalLootFor(player);
} }
foreach (LootItem item in items) foreach (LootItem item in items)
+18 -5
View File
@@ -3,7 +3,6 @@
using Framework.Constants; using Framework.Constants;
using Framework.Database; using Framework.Database;
using Framework.Dynamic;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.Collision; using Game.Collision;
using Game.DataStorage; using Game.DataStorage;
@@ -15,7 +14,6 @@ using Game.Scenarios;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
@@ -62,7 +60,7 @@ namespace Game.Maps
_worldStateValues = Global.WorldStateMgr.GetInitialWorldStatesForMap(this); _worldStateValues = Global.WorldStateMgr.GetInitialWorldStatesForMap(this);
} }
public void Dispose() public virtual void Dispose()
{ {
// Delete all waiting spawns // Delete all waiting spawns
// This doesn't delete from database. // This doesn't delete from database.
@@ -389,7 +387,6 @@ namespace Game.Maps
} }
} }
public void AddInfiniteAOIVignette(VignetteData vignette) public void AddInfiniteAOIVignette(VignetteData vignette)
{ {
_infiniteAOIVignettes.Add(vignette); _infiniteAOIVignettes.Add(vignette);
@@ -4905,10 +4902,14 @@ namespace Game.Maps
} }
} }
~InstanceMap() public override void Dispose()
{ {
if (i_instanceLock != null) if (i_instanceLock != null)
i_instanceLock.SetInUse(false); i_instanceLock.SetInUse(false);
i_owningGroupRef.Dispose();
base.Dispose();
} }
public override void InitVisibilityDistance() public override void InitVisibilityDistance()
@@ -5339,6 +5340,18 @@ namespace Game.Maps
InitVisibilityDistance(); InitVisibilityDistance();
} }
public override void Dispose()
{
if (m_bg != null)
{
//unlink to prevent crash, always unlink all pointer reference before destruction
m_bg.SetBgMap(null);
m_bg.Dispose();
}
base.Dispose();
}
public override void InitVisibilityDistance() public override void InitVisibilityDistance()
{ {
m_VisibleDistance = IsBattleArena() ? Global.WorldMgr.GetMaxVisibleDistanceInArenas() : Global.WorldMgr.GetMaxVisibleDistanceInBG(); m_VisibleDistance = IsBattleArena() ? Global.WorldMgr.GetMaxVisibleDistanceInArenas() : Global.WorldMgr.GetMaxVisibleDistanceInBG();
+2 -5
View File
@@ -61,12 +61,9 @@ namespace Game.PvP
Group group = killer.GetGroup(); Group group = killer.GetGroup();
if (group != null) if (group != null)
{ {
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next()) foreach (GroupReference groupRef in group.GetMembers())
{ {
Player groupGuy = refe.GetSource(); Player groupGuy = groupRef.GetSource();
if (groupGuy == null)
continue;
// skip if too far away // skip if too far away
if (!groupGuy.IsAtGroupRewardDistance(killed)) if (!groupGuy.IsAtGroupRewardDistance(killed))