Core/Entities: Phasing rewrite
This commit is contained in:
@@ -1361,6 +1361,23 @@ namespace Framework.Constants
|
||||
HideIfUnknown = 0x40
|
||||
}
|
||||
|
||||
public enum PhaseEntryFlags : ushort
|
||||
{
|
||||
Normal = 0x08,
|
||||
Cosmetic = 0x10,
|
||||
Personal = 0x20
|
||||
}
|
||||
|
||||
// PhaseUseFlags fields in different db2s
|
||||
public enum PhaseUseFlagsValues : byte
|
||||
{
|
||||
None = 0x0,
|
||||
AlwaysVisible = 0x1,
|
||||
Inverse = 0x2,
|
||||
|
||||
All = AlwaysVisible | Inverse
|
||||
}
|
||||
|
||||
public enum PrestigeLevelInfoFlags : byte
|
||||
{
|
||||
Disabled = 0x01 // Prestige levels with this flag won't be included to calculate max prestigelevel.
|
||||
|
||||
@@ -232,16 +232,16 @@ namespace Framework.Constants
|
||||
LiquidStatus = 175,
|
||||
InvalidGameobjectType = 176,
|
||||
GameobjectDamaged = 177,
|
||||
GridPosition = 178,
|
||||
|
||||
PhasingSuccess = 178,
|
||||
PhasingFailed = 179,
|
||||
PhasingLastPhase = 180,
|
||||
PhasingList = 181,
|
||||
PhasingPhasemask = 182,
|
||||
PhasingReportStatus = 183,
|
||||
PhasingNoDefinitions = 184, // Phasing
|
||||
PhaseshiftStatus = 179,
|
||||
PhaseshiftPhases = 180,
|
||||
PhaseshiftVisibleMapIds = 181,
|
||||
PhaseshiftUiWorldMapAreaSwaps = 182,
|
||||
PhaseFlagCosmetic = 183,
|
||||
PhaseFlagPersonal = 184,
|
||||
|
||||
GridPosition = 185,
|
||||
// 185 not used
|
||||
TransportPosition = 186,
|
||||
// Room For More Level 1 187-199 Not Used
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Framework.Constants
|
||||
public const string mmapMagic = "MMAP";
|
||||
public const int mmapVersion = 8;
|
||||
|
||||
public const string VMapMagic = "VMAP_4.5";
|
||||
public const string VMapMagic = "VMAP_4.6";
|
||||
public const float VMAPInvalidHeightValue = -200000.0f;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,9 @@ namespace Framework.Networking
|
||||
|
||||
public void CloseSocket()
|
||||
{
|
||||
if (_socket == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_closed = true;
|
||||
|
||||
@@ -156,6 +156,11 @@ namespace System.Collections.Generic
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TSource, bool> comparer)
|
||||
{
|
||||
return first.Where(x => second.Count(y => comparer(x, y)) == 1);
|
||||
}
|
||||
|
||||
public static uint[] ToBlockRange(this BitSet array)
|
||||
{
|
||||
uint[] blockValues = new uint[array.Length / 32 + 1];
|
||||
|
||||
@@ -1090,7 +1090,12 @@ namespace Game.AI
|
||||
break;
|
||||
|
||||
foreach (var obj in targets)
|
||||
obj.SetInPhase(e.Action.ingamePhaseId.id, true, e.Action.ingamePhaseId.apply == 1);
|
||||
{
|
||||
if (e.Action.ingamePhaseId.apply == 1)
|
||||
PhasingHandler.AddPhase(obj, e.Action.ingamePhaseId.id, true);
|
||||
else
|
||||
PhasingHandler.RemovePhase(obj, e.Action.ingamePhaseId.id, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1101,12 +1106,12 @@ namespace Game.AI
|
||||
if (targets.Empty())
|
||||
break;
|
||||
|
||||
var phases = Global.DB2Mgr.GetPhasesForGroup(e.Action.ingamePhaseGroup.groupId);
|
||||
|
||||
foreach (var obj in targets)
|
||||
{
|
||||
foreach (var phase in phases)
|
||||
obj.SetInPhase(phase, true, e.Action.ingamePhaseGroup.apply == 1);
|
||||
if (e.Action.ingamePhaseGroup.apply == 1)
|
||||
PhasingHandler.AddPhaseGroup(obj, e.Action.ingamePhaseGroup.groupId, true);
|
||||
else
|
||||
PhasingHandler.RemovePhaseGroup(obj, e.Action.ingamePhaseGroup.groupId, true);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -730,14 +730,7 @@ namespace Game.Chat
|
||||
else if (target.GetDBPhase() < 0)
|
||||
handler.SendSysMessage($"Target creature's PhaseGroup in DB: {Math.Abs(target.GetDBPhase())}");
|
||||
|
||||
string phases = "";
|
||||
foreach (uint phase in target.GetPhases())
|
||||
phases += phase + " ";
|
||||
|
||||
if (!string.IsNullOrEmpty(phases))
|
||||
handler.SendSysMessage("Target's current phases: {0}", phases);
|
||||
else
|
||||
handler.SendSysMessage("Target is not phased");
|
||||
PhasingHandler.PrintToChat(handler, target.GetPhaseShift());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1171,17 +1164,18 @@ namespace Game.Chat
|
||||
if (args.Empty())
|
||||
return false;
|
||||
|
||||
List<uint> terrainswap = new List<uint>();
|
||||
List<uint> phaseId = new List<uint>();
|
||||
List<uint> worldMapSwap = new List<uint>();
|
||||
PhaseShift phaseShift = new PhaseShift();
|
||||
|
||||
if (uint.TryParse(args.NextString(), out uint terrain))
|
||||
terrainswap.Add(terrain);
|
||||
phaseShift.AddVisibleMapId(terrain, null);
|
||||
|
||||
if (uint.TryParse(args.NextString(), out uint phase))
|
||||
phaseId.Add(phase);
|
||||
phaseShift.AddPhase(phase, PhaseFlags.None, null);
|
||||
|
||||
handler.GetSession().SendSetPhaseShift(phaseId, terrainswap, worldMapSwap);
|
||||
if (uint.TryParse(args.NextString(), out uint map))
|
||||
phaseShift.AddUiWorldMapAreaIdSwap(map);
|
||||
|
||||
PhasingHandler.SendToPlayer(handler.GetSession().GetPlayer(), phaseShift);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -477,7 +477,7 @@ namespace Game.Chat
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
obj.CopyPhaseFrom(player);
|
||||
PhasingHandler.InheritPhaseShift(obj, player);
|
||||
|
||||
if (spawntimeSecs != 0)
|
||||
{
|
||||
@@ -616,6 +616,13 @@ namespace Game.Chat
|
||||
obj.SetByteValue(GameObjectFields.Bytes1, (byte)objectType, (byte)objectState);
|
||||
else if (objectType == 4)
|
||||
obj.SendCustomAnim(objectState);
|
||||
else if (objectType == 5)
|
||||
{
|
||||
if (objectState < 0 || objectState > (uint)GameObjectDestructibleState.Rebuilding)
|
||||
return false;
|
||||
|
||||
obj.SetDestructibleState((GameObjectDestructibleState)objectState);
|
||||
}
|
||||
|
||||
handler.SendSysMessage("Set gobject type {0} state {1}", objectType, objectState);
|
||||
return true;
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Game.Chat.Commands
|
||||
player.SaveRecallPosition();
|
||||
|
||||
Map map = Global.MapMgr.CreateBaseMap(mapId);
|
||||
float z = Math.Max(map.GetHeight(x, y, MapConst.MaxHeight), map.GetWaterLevel(x, y));
|
||||
float z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y));
|
||||
|
||||
player.TeleportTo(mapId, x, y, z, player.GetOrientation());
|
||||
return true;
|
||||
@@ -298,7 +298,7 @@ namespace Game.Chat.Commands
|
||||
player.SaveRecallPosition();
|
||||
|
||||
Map map = Global.MapMgr.CreateBaseMap(mapId);
|
||||
z = Math.Max(map.GetHeight(x, y, MapConst.MaxHeight), map.GetWaterLevel(x, y));
|
||||
z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y));
|
||||
|
||||
player.TeleportTo(mapId, x, y, z, 0.0f);
|
||||
return true;
|
||||
@@ -446,7 +446,7 @@ namespace Game.Chat.Commands
|
||||
else
|
||||
player.SaveRecallPosition();
|
||||
|
||||
float z = Math.Max(map.GetHeight(x, y, MapConst.MaxHeight), map.GetWaterLevel(x, y));
|
||||
float z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y));
|
||||
|
||||
player.TeleportTo(zoneEntry.ContinentID, x, y, z, player.GetOrientation());
|
||||
return true;
|
||||
@@ -495,7 +495,7 @@ namespace Game.Chat.Commands
|
||||
return false;
|
||||
}
|
||||
Map map = Global.MapMgr.CreateBaseMap(mapId);
|
||||
z = Math.Max(map.GetHeight(x, y, MapConst.MaxHeight), map.GetWaterLevel(x, y));
|
||||
z = Math.Max(map.GetStaticHeight(PhasingHandler.EmptyPhaseShift, x, y, MapConst.MaxHeight), map.GetWaterLevel(PhasingHandler.EmptyPhaseShift, x, y));
|
||||
}
|
||||
|
||||
// stop flight if need
|
||||
|
||||
@@ -321,7 +321,7 @@ namespace Game.Chat
|
||||
{
|
||||
// ... than, it prints information like "is online", where he is, etc...
|
||||
onlineState = "online";
|
||||
phases = string.Join(", ", p.GetPhases());
|
||||
phases = PhasingHandler.FormatPhases(p.GetPhaseShift());
|
||||
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(p.GetAreaId());
|
||||
if (area != null)
|
||||
|
||||
@@ -99,12 +99,16 @@ namespace Game.Chat
|
||||
int gx = (int)(32 - player.GetPositionX() / MapConst.SizeofGrids);
|
||||
int gy = (int)(32 - player.GetPositionY() / MapConst.SizeofGrids);
|
||||
|
||||
float x, y, z;
|
||||
player.GetPosition(out x, out y, out z);
|
||||
|
||||
handler.SendSysMessage("{0:D4}{1:D2}{2:D2}.mmtile", player.GetMapId(), gy, gx);
|
||||
handler.SendSysMessage("gridloc [{0}, {1}]", gx, gy);
|
||||
|
||||
// calculate navmesh tile location
|
||||
Detour.dtNavMesh navmesh = Global.MMapMgr.GetNavMesh(handler.GetPlayer().GetMapId());
|
||||
Detour.dtNavMeshQuery navmeshquery = Global.MMapMgr.GetNavMeshQuery(handler.GetPlayer().GetMapId(), player.GetInstanceId());
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(player.GetPhaseShift(), player.GetMap(), x, y);
|
||||
Detour.dtNavMesh navmesh = Global.MMapMgr.GetNavMesh(terrainMapId);
|
||||
Detour.dtNavMeshQuery navmeshquery = Global.MMapMgr.GetNavMeshQuery(terrainMapId, player.GetInstanceId());
|
||||
if (navmesh == null || navmeshquery == null)
|
||||
{
|
||||
handler.SendSysMessage("NavMesh not loaded for current map.");
|
||||
@@ -112,8 +116,6 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
float[] min = navmesh.getParams().orig;
|
||||
float x, y, z;
|
||||
player.GetPosition(out x, out y, out z);
|
||||
float[] location = { y, z, x };
|
||||
float[] extents = { 3.0f, 5.0f, 3.0f };
|
||||
|
||||
@@ -155,9 +157,10 @@ namespace Game.Chat
|
||||
[Command("loadedtiles", RBACPermissions.CommandMmapLoadedtiles)]
|
||||
static bool LoadedTilesCommand(StringArguments args, CommandHandler handler)
|
||||
{
|
||||
uint mapid = handler.GetPlayer().GetMapId();
|
||||
Detour.dtNavMesh navmesh = Global.MMapMgr.GetNavMesh(mapid);
|
||||
Detour.dtNavMeshQuery navmeshquery = Global.MMapMgr.GetNavMeshQuery(mapid, handler.GetPlayer().GetInstanceId());
|
||||
Player player = handler.GetSession().GetPlayer();
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(player.GetPhaseShift(), player.GetMap(), player.GetPositionX(), player.GetPositionY());
|
||||
Detour.dtNavMesh navmesh = Global.MMapMgr.GetNavMesh(terrainMapId);
|
||||
Detour.dtNavMeshQuery navmeshquery = Global.MMapMgr.GetNavMeshQuery(terrainMapId, handler.GetPlayer().GetInstanceId());
|
||||
if (navmesh == null || navmeshquery == null)
|
||||
{
|
||||
handler.SendSysMessage("NavMesh not loaded for current map.");
|
||||
@@ -180,12 +183,13 @@ namespace Game.Chat
|
||||
[Command("stats", RBACPermissions.CommandMmapStats)]
|
||||
static bool HandleMmapStatsCommand(StringArguments args, CommandHandler handler)
|
||||
{
|
||||
uint mapId = handler.GetPlayer().GetMapId();
|
||||
Player player = handler.GetSession().GetPlayer();
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(player.GetPhaseShift(), player.GetMap(), player.GetPositionX(), player.GetPositionY());
|
||||
handler.SendSysMessage("mmap stats:");
|
||||
handler.SendSysMessage(" global mmap pathfinding is {0}abled", Global.DisableMgr.IsPathfindingEnabled(mapId) ? "En" : "Dis");
|
||||
handler.SendSysMessage(" global mmap pathfinding is {0}abled", Global.DisableMgr.IsPathfindingEnabled(player.GetMapId()) ? "En" : "Dis");
|
||||
handler.SendSysMessage(" {0} maps loaded with {1} tiles overall", Global.MMapMgr.getLoadedMapsCount(), Global.MMapMgr.getLoadedTilesCount());
|
||||
|
||||
Detour.dtNavMesh navmesh = Global.MMapMgr.GetNavMesh(handler.GetPlayer().GetMapId());
|
||||
Detour.dtNavMesh navmesh = Global.MMapMgr.GetNavMesh(terrainMapId);
|
||||
if (navmesh == null)
|
||||
{
|
||||
handler.SendSysMessage("NavMesh not loaded for current map.");
|
||||
|
||||
@@ -195,8 +195,8 @@ namespace Game.Chat
|
||||
Global.DB2Mgr.Map2ZoneCoordinates(zoneId, ref zoneX, ref zoneY);
|
||||
|
||||
Map map = obj.GetMap();
|
||||
float groundZ = map.GetHeight(obj.GetPhases(), obj.GetPositionX(), obj.GetPositionY(), MapConst.MaxHeight);
|
||||
float floorZ = map.GetHeight(obj.GetPhases(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ());
|
||||
float groundZ = map.GetHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), MapConst.MaxHeight);
|
||||
float floorZ = map.GetHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ());
|
||||
|
||||
GridCoord gridCoord = GridDefines.ComputeGridCoord(obj.GetPositionX(), obj.GetPositionY());
|
||||
|
||||
@@ -210,13 +210,13 @@ namespace Game.Chat
|
||||
|
||||
if (haveVMap)
|
||||
{
|
||||
if (map.IsOutdoors(obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ()))
|
||||
handler.SendSysMessage("You are outdoors");
|
||||
if (map.IsOutdoors(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ()))
|
||||
handler.SendSysMessage(CypherStrings.GpsPositionOutdoors);
|
||||
else
|
||||
handler.SendSysMessage("You are indoors");
|
||||
handler.SendSysMessage(CypherStrings.GpsPositionIndoors);
|
||||
}
|
||||
else
|
||||
handler.SendSysMessage("no VMAP available for area info");
|
||||
handler.SendSysMessage(CypherStrings.GpsNoVmap);
|
||||
|
||||
string unknown = handler.GetCypherString(CypherStrings.Unknown);
|
||||
|
||||
@@ -224,7 +224,7 @@ namespace Game.Chat
|
||||
mapId, (mapEntry != null ? mapEntry.MapName[handler.GetSessionDbcLocale()] : unknown),
|
||||
zoneId, (zoneEntry != null ? zoneEntry.AreaName[handler.GetSessionDbcLocale()] : unknown),
|
||||
areaId, (areaEntry != null ? areaEntry.AreaName[handler.GetSessionDbcLocale()] : unknown),
|
||||
string.Join(", ", obj.GetPhases()), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), obj.GetOrientation());
|
||||
obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), obj.GetOrientation());
|
||||
|
||||
Transport transport = obj.GetTransport();
|
||||
if (transport)
|
||||
@@ -237,25 +237,12 @@ namespace Game.Chat
|
||||
zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap, haveMMap);
|
||||
|
||||
LiquidData liquidStatus;
|
||||
ZLiquidStatus status = map.getLiquidStatus(obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), MapConst.MapAllLiquidTypes, out liquidStatus);
|
||||
ZLiquidStatus status = map.getLiquidStatus(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), obj.GetPositionZ(), MapConst.MapAllLiquidTypes, out liquidStatus);
|
||||
|
||||
if (liquidStatus != null)
|
||||
handler.SendSysMessage(CypherStrings.LiquidStatus, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status);
|
||||
|
||||
if (!obj.GetTerrainSwaps().Empty())
|
||||
{
|
||||
string ss = "";
|
||||
foreach (uint swap in obj.GetTerrainSwaps())
|
||||
ss += swap + " ";
|
||||
handler.SendSysMessage("Target's active terrain swaps: {0}", ss);
|
||||
}
|
||||
if (!obj.GetWorldMapAreaSwaps().Empty())
|
||||
{
|
||||
string ss = "";
|
||||
foreach (uint swap in obj.GetWorldMapAreaSwaps())
|
||||
ss += swap + " ";
|
||||
handler.SendSysMessage("Target's active world map area swaps: {0}", ss);
|
||||
}
|
||||
PhasingHandler.PrintToChat(handler, obj.GetPhaseShift());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -602,7 +589,8 @@ namespace Game.Chat
|
||||
target.GetContactPoint(_player, out x, out y, out z);
|
||||
|
||||
_player.TeleportTo(target.GetMapId(), x, y, z, _player.GetAngle(target), TeleportToOptions.GMMode);
|
||||
_player.CopyPhaseFrom(target, true);
|
||||
PhasingHandler.InheritPhaseShift(_player, target);
|
||||
_player.UpdateObjectVisibility();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -727,7 +715,8 @@ namespace Game.Chat
|
||||
float x, y, z;
|
||||
handler.GetSession().GetPlayer().GetClosePoint(out x, out y, out z, target.GetObjectSize());
|
||||
target.TeleportTo(handler.GetSession().GetPlayer().GetMapId(), x, y, z, target.GetOrientation());
|
||||
target.CopyPhaseFrom(handler.GetSession().GetPlayer(), true);
|
||||
PhasingHandler.InheritPhaseShift(target, handler.GetSession().GetPlayer());
|
||||
target.UpdateObjectVisibility();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1385,7 +1374,6 @@ namespace Game.Chat
|
||||
// Position data print
|
||||
uint mapId;
|
||||
uint areaId;
|
||||
List<uint> phases = new List<uint>();
|
||||
string areaName = handler.GetCypherString(CypherStrings.Unknown);
|
||||
string zoneName = handler.GetCypherString(CypherStrings.Unknown);
|
||||
|
||||
@@ -1417,7 +1405,6 @@ namespace Game.Chat
|
||||
areaId = target.GetAreaId();
|
||||
alive = target.IsAlive() ? handler.GetCypherString(CypherStrings.Yes) : handler.GetCypherString(CypherStrings.No);
|
||||
gender = (Gender)target.GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetGender);
|
||||
phases = target.GetPhases();
|
||||
}
|
||||
// get additional information from DB
|
||||
else
|
||||
@@ -1582,9 +1569,9 @@ namespace Game.Chat
|
||||
// Output XII. LANG_PINFO_CHR_ALIVE
|
||||
handler.SendSysMessage(CypherStrings.PinfoChrAlive, alive);
|
||||
|
||||
// Output XIII. LANG_PINFO_CHR_PHASES
|
||||
if (target && !phases.Empty())
|
||||
handler.SendSysMessage(CypherStrings.PinfoChrPhases, string.Join(", ", phases));
|
||||
// Output XIII. phases
|
||||
if (target)
|
||||
PhasingHandler.PrintToChat(handler, target.GetPhaseShift());
|
||||
|
||||
// Output XIV. LANG_PINFO_CHR_MONEY
|
||||
ulong gold = money / MoneyConstants.Gold;
|
||||
|
||||
@@ -497,20 +497,38 @@ namespace Game.Chat
|
||||
return false;
|
||||
|
||||
uint phaseId = args.NextUInt32();
|
||||
if (!CliDB.PhaseStorage.ContainsKey(phaseId))
|
||||
uint visibleMapId = args.NextUInt32();
|
||||
|
||||
if (phaseId != 0 && !CliDB.PhaseStorage.ContainsKey(phaseId))
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.PhaseNotfound);
|
||||
return false;
|
||||
}
|
||||
|
||||
Unit target = handler.getSelectedUnit();
|
||||
if (!target)
|
||||
target = handler.GetSession().GetPlayer();
|
||||
|
||||
target.SetInPhase(phaseId, true, !target.IsInPhase(phaseId));
|
||||
if (visibleMapId != 0)
|
||||
{
|
||||
MapRecord visibleMap = CliDB.MapStorage.LookupByKey(visibleMapId);
|
||||
if (visibleMap == null || visibleMap.ParentMapID != target.GetMapId())
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.PhaseNotfound);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target.IsTypeId(TypeId.Player))
|
||||
target.ToPlayer().SendUpdatePhasing();
|
||||
if (!target.GetPhaseShift().HasVisibleMapId(visibleMapId))
|
||||
PhasingHandler.AddVisibleMapId(target, visibleMapId);
|
||||
else
|
||||
PhasingHandler.RemoveVisibleMapId(target, visibleMapId);
|
||||
}
|
||||
|
||||
if (phaseId != 0)
|
||||
{
|
||||
if (!target.GetPhaseShift().HasPhase(phaseId))
|
||||
PhasingHandler.AddPhase(target, phaseId, true);
|
||||
else
|
||||
PhasingHandler.RemovePhase(target, phaseId, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -87,16 +87,7 @@ namespace Game.Chat
|
||||
if (data != null)
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.NpcinfoPhases, data.phaseId, data.phaseGroup);
|
||||
if (data.phaseGroup != 0)
|
||||
{
|
||||
var _phases = target.GetPhases();
|
||||
if (!_phases.Empty())
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.NpcinfoPhaseIds);
|
||||
foreach (uint phaseId in _phases)
|
||||
handler.SendSysMessage("{0}", phaseId);
|
||||
}
|
||||
}
|
||||
PhasingHandler.PrintToChat(handler, target.GetPhaseShift());
|
||||
}
|
||||
|
||||
handler.SendSysMessage(CypherStrings.NpcinfoArmor, target.GetArmor());
|
||||
@@ -939,8 +930,8 @@ namespace Game.Chat
|
||||
return false;
|
||||
}
|
||||
|
||||
creature.ClearPhases();
|
||||
creature.SetInPhase(phaseId, true, true);
|
||||
PhasingHandler.ResetPhaseShift(creature);
|
||||
PhasingHandler.AddPhase(creature, phaseId, true);
|
||||
creature.SetDBPhase((int)phaseId);
|
||||
|
||||
creature.SaveToDB();
|
||||
@@ -962,12 +953,8 @@ namespace Game.Chat
|
||||
return false;
|
||||
}
|
||||
|
||||
creature.ClearPhases();
|
||||
|
||||
foreach (uint id in Global.DB2Mgr.GetPhasesForGroup((uint)phaseGroupId))
|
||||
creature.SetInPhase(id, false, true); // don't send update here for multiple phases, only send it once after adding all phases
|
||||
|
||||
creature.UpdateObjectVisibility();
|
||||
PhasingHandler.ResetPhaseShift(creature);
|
||||
PhasingHandler.AddPhaseGroup(creature, (uint)phaseGroupId, true);
|
||||
creature.SetDBPhase(-phaseGroupId);
|
||||
|
||||
creature.SaveToDB();
|
||||
@@ -1119,7 +1106,7 @@ namespace Game.Chat
|
||||
if (!creature)
|
||||
return false;
|
||||
|
||||
creature.CopyPhaseFrom(chr);
|
||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
||||
creature.SaveToDB(map.GetId(), 1ul << (int)map.GetSpawnMode());
|
||||
|
||||
ulong db_guid = creature.GetSpawnId();
|
||||
|
||||
@@ -552,7 +552,7 @@ namespace Game.Chat.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
creature.CopyPhaseFrom(chr);
|
||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
||||
creature.SaveToDB(map.GetId(), 1ul << (int)map.GetSpawnMode());
|
||||
|
||||
ulong dbGuid = creature.GetSpawnId();
|
||||
@@ -772,7 +772,7 @@ namespace Game.Chat.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
creature.CopyPhaseFrom(chr);
|
||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
||||
creature.SaveToDB(map.GetId(), 1ul << (int)map.GetSpawnMode());
|
||||
|
||||
ulong dbGuid = creature.GetSpawnId();
|
||||
@@ -838,7 +838,7 @@ namespace Game.Chat.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
creature.CopyPhaseFrom(chr);
|
||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
||||
creature.SaveToDB(map.GetId(), 1ul << (int)map.GetSpawnMode());
|
||||
|
||||
ulong dbGuid = creature.GetSpawnId();
|
||||
@@ -893,7 +893,7 @@ namespace Game.Chat.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
creature.CopyPhaseFrom(chr);
|
||||
PhasingHandler.InheritPhaseShift(creature, chr);
|
||||
creature.SaveToDB(map.GetId(), 1ul << (int)map.GetSpawnMode());
|
||||
|
||||
ulong dbGuid = creature.GetSpawnId();
|
||||
|
||||
@@ -227,22 +227,22 @@ namespace Game.Collision
|
||||
|
||||
public class DynamicTreeIntersectionCallback : WorkerCallback
|
||||
{
|
||||
public DynamicTreeIntersectionCallback(List<uint> phases)
|
||||
public DynamicTreeIntersectionCallback(PhaseShift phaseShift)
|
||||
{
|
||||
_didHit = false;
|
||||
_phases = phases;
|
||||
_phaseShift = phaseShift;
|
||||
}
|
||||
|
||||
public override bool Invoke(Ray r, IModel obj, ref float distance)
|
||||
{
|
||||
_didHit = obj.IntersectRay(r, ref distance, true, _phases);
|
||||
_didHit = obj.IntersectRay(r, ref distance, true, _phaseShift);
|
||||
return _didHit;
|
||||
}
|
||||
|
||||
public bool didHit() { return _didHit; }
|
||||
|
||||
bool _didHit;
|
||||
List<uint> _phases;
|
||||
PhaseShift _phaseShift;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,17 +57,17 @@ namespace Game.Collision
|
||||
impl.update(diff);
|
||||
}
|
||||
|
||||
public bool getIntersectionTime(List<uint> phases, Ray ray, Vector3 endPos, float maxDist)
|
||||
public bool getIntersectionTime(Ray ray, Vector3 endPos, PhaseShift phaseShift, float maxDist)
|
||||
{
|
||||
float distance = maxDist;
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phases);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phaseShift);
|
||||
impl.intersectRay(ray, callback, ref distance, endPos);
|
||||
if (callback.didHit())
|
||||
maxDist = distance;
|
||||
return callback.didHit();
|
||||
}
|
||||
|
||||
public bool getObjectHitPos(List<uint> phases, Vector3 startPos, Vector3 endPos, ref Vector3 resultHitPos, float modifyDist)
|
||||
public bool getObjectHitPos(Vector3 startPos, Vector3 endPos, ref Vector3 resultHitPos, float modifyDist, PhaseShift phaseShift)
|
||||
{
|
||||
bool result = false;
|
||||
float maxDist = (endPos - startPos).magnitude();
|
||||
@@ -82,7 +82,7 @@ namespace Game.Collision
|
||||
Vector3 dir = (endPos - startPos) / maxDist; // direction with length of 1
|
||||
Ray ray = new Ray(startPos, dir);
|
||||
float dist = maxDist;
|
||||
if (getIntersectionTime(phases, ray, endPos, dist))
|
||||
if (getIntersectionTime(ray, endPos, phaseShift, dist))
|
||||
{
|
||||
resultHitPos = startPos + dir * dist;
|
||||
if (modifyDist < 0)
|
||||
@@ -105,7 +105,7 @@ namespace Game.Collision
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(Vector3 startPos, Vector3 endPos, List<uint> phases)
|
||||
public bool isInLineOfSight(Vector3 startPos, Vector3 endPos, PhaseShift phaseShift)
|
||||
{
|
||||
float maxDist = (endPos - startPos).magnitude();
|
||||
|
||||
@@ -113,17 +113,17 @@ namespace Game.Collision
|
||||
return true;
|
||||
|
||||
Ray r = new Ray(startPos, (endPos - startPos) / maxDist);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phases);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phaseShift);
|
||||
impl.intersectRay(r, callback, ref maxDist, endPos);
|
||||
|
||||
return !callback.didHit();
|
||||
}
|
||||
|
||||
public float getHeight(float x, float y, float z, float maxSearchDist, List<uint> phases)
|
||||
public float getHeight(float x, float y, float z, float maxSearchDist, PhaseShift phaseShift)
|
||||
{
|
||||
Vector3 v = new Vector3(x, y, z + 0.5f);
|
||||
Ray r = new Ray(v, new Vector3(0, 0, -1));
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phases);
|
||||
DynamicTreeIntersectionCallback callback = new DynamicTreeIntersectionCallback(phaseShift);
|
||||
impl.intersectZAllignedRay(r, callback, ref maxSearchDist);
|
||||
|
||||
if (callback.didHit())
|
||||
|
||||
@@ -36,23 +36,39 @@ namespace Game.Collision
|
||||
|
||||
public static string VMapPath = Global.WorldMgr.GetDataPath() + "/vmaps/";
|
||||
|
||||
public void Initialize(MultiMap<uint, uint> mapData)
|
||||
{
|
||||
iChildMapData = mapData;
|
||||
foreach (var pair in mapData)
|
||||
iParentMapData[pair.Value] = pair.Key;
|
||||
}
|
||||
|
||||
public VMAPLoadResult loadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var result = VMAPLoadResult.Ignored;
|
||||
if (_loadMap(mapId, x, y))
|
||||
result = VMAPLoadResult.OK;
|
||||
else
|
||||
result = VMAPLoadResult.Error;
|
||||
if (isMapLoadingEnabled())
|
||||
{
|
||||
if (loadSingleMap(mapId, x, y))
|
||||
{
|
||||
result = VMAPLoadResult.OK;
|
||||
var childMaps = iChildMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
if (!loadSingleMap(childMapId, x, y))
|
||||
result = VMAPLoadResult.Error;
|
||||
}
|
||||
else
|
||||
result = VMAPLoadResult.Error;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool _loadMap(uint mapId, uint tileX, uint tileY)
|
||||
bool loadSingleMap(uint mapId, uint tileX, uint tileY)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree == null)
|
||||
{
|
||||
string filename = string.Format("{0}{1:D4}.vmtree", VMapPath, mapId);
|
||||
string filename = VMapPath + getMapFileName(mapId);
|
||||
StaticMapTree newTree = new StaticMapTree(mapId);
|
||||
if (!newTree.InitMap(filename, this))
|
||||
return false;
|
||||
@@ -65,72 +81,90 @@ namespace Game.Collision
|
||||
return instanceTree.LoadMapTile(tileX, tileY, this);
|
||||
}
|
||||
|
||||
public WorldModel acquireModelInstance(string filename)
|
||||
public void unloadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
var childMaps = iChildMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
unloadSingleMap(childMapId, x, y);
|
||||
|
||||
unloadSingleMap(mapId, x, y);
|
||||
}
|
||||
|
||||
void unloadSingleMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
WorldModel worldmodel = new WorldModel();
|
||||
if (!worldmodel.readFile(VMapPath + filename + ".vmo"))
|
||||
instanceTree.UnloadMapTile(x, y, this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: could not load '{0}.vmo'", filename);
|
||||
return null;
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: loading file '{0}'", filename);
|
||||
iLoadedModelFiles.Add(filename, new ManagedModel());
|
||||
model = iLoadedModelFiles.LookupByKey(filename);
|
||||
model.setModel(worldmodel);
|
||||
}
|
||||
model.incRefCount();
|
||||
return model.getModel();
|
||||
}
|
||||
|
||||
public void releaseModelInstance(string filename)
|
||||
public void unloadMap(uint mapId)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
var childMaps = iChildMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
unloadSingleMap(childMapId);
|
||||
|
||||
unloadSingleMap(mapId);
|
||||
}
|
||||
|
||||
void unloadSingleMap(uint mapId)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: trying to unload non-loaded file '{0}'", filename);
|
||||
return;
|
||||
instanceTree.UnloadMap(this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
}
|
||||
if (model.decRefCount() == 0)
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
if (!isLineOfSightCalcEnabled() || Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
return true;
|
||||
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: unloading file '{0}'", filename);
|
||||
iLoadedModelFiles.Remove(filename);
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
if (pos1 != pos2)
|
||||
return instanceTree.isInLineOfSight(pos1, pos2);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool existsMap(uint mapId, uint x, uint y)
|
||||
public bool getObjectHitPos(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
{
|
||||
return StaticMapTree.CanLoadMap(VMapPath, mapId, x, y);
|
||||
}
|
||||
|
||||
public static string getMapFileName(uint mapId)
|
||||
{
|
||||
return string.Format("{0:D4}.vmtree", mapId);
|
||||
}
|
||||
|
||||
public bool GetLiquidLevel(uint mapId, float x, float y, float z, byte reqLiquidType, ref float level, ref float floor, ref uint type)
|
||||
{
|
||||
if (!Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLiquidStatus))
|
||||
if (isLineOfSightCalcEnabled() && !Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
LocationInfo info = new LocationInfo();
|
||||
Vector3 pos = convertPositionToInternalRep(x, y, z);
|
||||
if (instanceTree.GetLocationInfo(pos, info))
|
||||
{
|
||||
floor = info.ground_Z;
|
||||
Contract.Assert(floor < float.MaxValue);
|
||||
type = info.hitModel.GetLiquidType(); // entry from LiquidType.dbc
|
||||
if (reqLiquidType != 0 && !Convert.ToBoolean(Global.DB2Mgr.GetLiquidFlags(type) & reqLiquidType))
|
||||
return false;
|
||||
if (info.hitInstance.GetLiquidLevel(pos, info, ref level))
|
||||
return true;
|
||||
}
|
||||
Vector3 resultPos;
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
bool result = instanceTree.getObjectHitPos(pos1, pos2, out resultPos, modifyDist);
|
||||
resultPos = convertPositionToInternalRep(resultPos.X, resultPos.Y, resultPos.Z);
|
||||
rx = resultPos.X;
|
||||
ry = resultPos.Y;
|
||||
rz = resultPos.Z;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rx = x2;
|
||||
ry = y2;
|
||||
rz = z2;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -175,6 +209,78 @@ namespace Game.Collision
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GetLiquidLevel(uint mapId, float x, float y, float z, byte reqLiquidType, ref float level, ref float floor, ref uint type)
|
||||
{
|
||||
if (!Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLiquidStatus))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
LocationInfo info = new LocationInfo();
|
||||
Vector3 pos = convertPositionToInternalRep(x, y, z);
|
||||
if (instanceTree.GetLocationInfo(pos, info))
|
||||
{
|
||||
floor = info.ground_Z;
|
||||
Contract.Assert(floor < float.MaxValue);
|
||||
type = info.hitModel.GetLiquidType(); // entry from LiquidType.dbc
|
||||
if (reqLiquidType != 0 && !Convert.ToBoolean(Global.DB2Mgr.GetLiquidFlags(type) & reqLiquidType))
|
||||
return false;
|
||||
if (info.hitInstance.GetLiquidLevel(pos, info, ref level))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public WorldModel acquireModelInstance(string filename)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
{
|
||||
WorldModel worldmodel = new WorldModel();
|
||||
if (!worldmodel.readFile(VMapPath + filename + ".vmo"))
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: could not load '{0}.vmo'", filename);
|
||||
return null;
|
||||
}
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: loading file '{0}'", filename);
|
||||
iLoadedModelFiles.Add(filename, new ManagedModel());
|
||||
model = iLoadedModelFiles.LookupByKey(filename);
|
||||
model.setModel(worldmodel);
|
||||
}
|
||||
model.incRefCount();
|
||||
return model.getModel();
|
||||
}
|
||||
|
||||
public void releaseModelInstance(string filename)
|
||||
{
|
||||
var model = iLoadedModelFiles.LookupByKey(filename);
|
||||
if (model == null)
|
||||
{
|
||||
Log.outError(LogFilter.Server, "VMapManager: trying to unload non-loaded file '{0}'", filename);
|
||||
return;
|
||||
}
|
||||
if (model.decRefCount() == 0)
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: unloading file '{0}'", filename);
|
||||
iLoadedModelFiles.Remove(filename);
|
||||
}
|
||||
}
|
||||
|
||||
public bool existsMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
return StaticMapTree.CanLoadMap(VMapPath, mapId, x, y, this);
|
||||
}
|
||||
|
||||
public int getParentMapId(uint mapId)
|
||||
{
|
||||
if (iParentMapData.ContainsKey(mapId))
|
||||
return (int)iParentMapData[mapId];
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Vector3 convertPositionToInternalRep(float x, float y, float z)
|
||||
{
|
||||
Vector3 pos = new Vector3();
|
||||
@@ -186,6 +292,11 @@ namespace Game.Collision
|
||||
return pos;
|
||||
}
|
||||
|
||||
public static string getMapFileName(uint mapId)
|
||||
{
|
||||
return string.Format("{0:D4}.vmtree", mapId);
|
||||
}
|
||||
|
||||
public void setEnableLineOfSightCalc(bool pVal) { _enableLineOfSightCalc = pVal; }
|
||||
public void setEnableHeightCalc(bool pVal) { _enableHeightCalc = pVal; }
|
||||
|
||||
@@ -193,79 +304,10 @@ namespace Game.Collision
|
||||
public bool isHeightCalcEnabled() { return _enableHeightCalc; }
|
||||
public bool isMapLoadingEnabled() { return _enableLineOfSightCalc || _enableHeightCalc; }
|
||||
|
||||
public bool getObjectHitPos(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
{
|
||||
if (isLineOfSightCalcEnabled() && !Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Vector3 resultPos;
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
bool result = instanceTree.getObjectHitPos(pos1, pos2, out resultPos, modifyDist);
|
||||
resultPos = convertPositionToInternalRep(resultPos.X, resultPos.Y, resultPos.Z);
|
||||
rx = resultPos.X;
|
||||
ry = resultPos.Y;
|
||||
rz = resultPos.Z;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
rx = x2;
|
||||
ry = y2;
|
||||
rz = z2;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
if (!isLineOfSightCalcEnabled() || Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
return true;
|
||||
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
if (pos1 != pos2)
|
||||
{
|
||||
return instanceTree.isInLineOfSight(pos1, pos2);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void unloadMap(uint mapId)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
instanceTree.UnloadMap(this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unloadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var instanceTree = iInstanceMapTrees.LookupByKey(mapId);
|
||||
if (instanceTree != null)
|
||||
{
|
||||
instanceTree.UnloadMapTile(x, y, this);
|
||||
if (instanceTree.numLoadedTiles() == 0)
|
||||
{
|
||||
iInstanceMapTrees.Remove(mapId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, ManagedModel> iLoadedModelFiles = new Dictionary<string, ManagedModel>();
|
||||
Dictionary<uint, StaticMapTree> iInstanceMapTrees = new Dictionary<uint, StaticMapTree>();
|
||||
MultiMap<uint, uint> iChildMapData = new MultiMap<uint, uint>();
|
||||
Dictionary<uint, uint> iParentMapData = new Dictionary<uint, uint>();
|
||||
bool _enableLineOfSightCalc;
|
||||
bool _enableHeightCalc;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace Game.Collision
|
||||
bool success = false;
|
||||
if (!File.Exists(fname))
|
||||
return false;
|
||||
|
||||
char tiled = '0';
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(fname, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
@@ -99,6 +100,21 @@ namespace Game.Collision
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.InitMap() : could not acquire WorldModel for '{0}'", spawn.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
success = reader.ReadStringFromChars(4) == "SIDX";
|
||||
if (success)
|
||||
{
|
||||
uint spawnIndicesSize = reader.ReadUInt32();
|
||||
for (uint i = 0; i < spawnIndicesSize && success; ++i)
|
||||
{
|
||||
uint spawnId = reader.ReadUInt32();
|
||||
uint spawnIndex = reader.ReadUInt32();
|
||||
iSpawnIndices[spawnId] = spawnIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -131,15 +147,14 @@ namespace Game.Collision
|
||||
}
|
||||
bool result = true;
|
||||
|
||||
string tilefile = VMapManager.VMapPath + getTileFileName(iMapID, tileX, tileY);
|
||||
|
||||
if (!File.Exists(tilefile))
|
||||
FileStream stream = OpenMapTileFile(VMapManager.VMapPath, iMapID, tileX, tileY, vm);
|
||||
if (stream == null)
|
||||
{
|
||||
iLoadedTiles[packTileID(tileX, tileY)] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(tilefile, FileMode.Open, FileAccess.Read)))
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
return false;
|
||||
@@ -159,18 +174,27 @@ namespace Game.Collision
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.LoadMapTile() : could not acquire WorldModel [{0}, {1}]", tileX, tileY);
|
||||
|
||||
// update tree
|
||||
uint referencedVal = reader.ReadUInt32();
|
||||
if (!iLoadedSpawns.ContainsKey(referencedVal))
|
||||
if (iSpawnIndices.ContainsKey(spawn.ID))
|
||||
{
|
||||
iTreeValues[referencedVal] = new ModelInstance(spawn, model);
|
||||
iLoadedSpawns[referencedVal] = 1;
|
||||
uint referencedVal = iSpawnIndices[spawn.ID];
|
||||
if (!iLoadedSpawns.ContainsKey(referencedVal))
|
||||
{
|
||||
if (referencedVal >= iNTreeValues)
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "StaticMapTree.LoadMapTile() : invalid tree element ({0}/{1}) referenced in tile {2}", referencedVal, iNTreeValues, stream.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
iTreeValues[referencedVal] = new ModelInstance(spawn, model);
|
||||
iLoadedSpawns[referencedVal] = 1;
|
||||
}
|
||||
else
|
||||
++iLoadedSpawns[referencedVal];
|
||||
}
|
||||
else
|
||||
++iLoadedSpawns[referencedVal];
|
||||
result = false;
|
||||
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
iLoadedTiles[packTileID(tileX, tileY)] = true;
|
||||
@@ -189,36 +213,42 @@ namespace Game.Collision
|
||||
}
|
||||
if (tile) // file associated with tile
|
||||
{
|
||||
string tilefile = VMapManager.VMapPath + getTileFileName(iMapID, tileX, tileY);
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(tilefile, FileMode.Open, FileAccess.Read)))
|
||||
FileStream stream = OpenMapTileFile(VMapManager.VMapPath, iMapID, tileX, tileY, vm);
|
||||
if (stream != null)
|
||||
{
|
||||
bool result = true;
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
result = false;
|
||||
|
||||
uint numSpawns = reader.ReadUInt32();
|
||||
for (uint i = 0; i < numSpawns && result; ++i)
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
// read model spawns
|
||||
ModelSpawn spawn;
|
||||
result = ModelSpawn.readFromFile(reader, out spawn);
|
||||
if (result)
|
||||
bool result = true;
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
result = false;
|
||||
|
||||
uint numSpawns = reader.ReadUInt32();
|
||||
for (uint i = 0; i < numSpawns && result; ++i)
|
||||
{
|
||||
// release model instance
|
||||
vm.releaseModelInstance(spawn.name);
|
||||
|
||||
// update tree
|
||||
uint referencedNode = reader.ReadUInt32();
|
||||
|
||||
|
||||
if (!iLoadedSpawns.ContainsKey(referencedNode))
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.UnloadMapTile() : trying to unload non-referenced model '{0}' (ID:{1})", spawn.name, spawn.ID);
|
||||
else if (--iLoadedSpawns[referencedNode] == 0)
|
||||
// read model spawns
|
||||
ModelSpawn spawn;
|
||||
result = ModelSpawn.readFromFile(reader, out spawn);
|
||||
if (result)
|
||||
{
|
||||
iTreeValues[referencedNode].setUnloaded();
|
||||
iLoadedSpawns.Remove(referencedNode);
|
||||
}
|
||||
// release model instance
|
||||
vm.releaseModelInstance(spawn.name);
|
||||
|
||||
// update tree
|
||||
if (!iSpawnIndices.ContainsKey(spawn.ID))
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
uint referencedNode = iSpawnIndices[spawn.ID];
|
||||
if (!iLoadedSpawns.ContainsKey(referencedNode))
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.UnloadMapTile() : trying to unload non-referenced model '{0}' (ID:{1})", spawn.name, spawn.ID);
|
||||
else if (--iLoadedSpawns[referencedNode] == 0)
|
||||
{
|
||||
iTreeValues[referencedNode].setUnloaded();
|
||||
iLoadedSpawns.Remove(referencedNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,10 +258,26 @@ namespace Game.Collision
|
||||
|
||||
static uint packTileID(uint tileX, uint tileY) { return tileX << 16 | tileY; }
|
||||
static void unpackTileID(uint ID, ref uint tileX, ref uint tileY) { tileX = ID >> 16; tileY = ID & 0xFF; }
|
||||
public static bool CanLoadMap(string vmapPath, uint mapID, uint tileX, uint tileY)
|
||||
|
||||
static FileStream OpenMapTileFile(string vmapPath, uint mapID, uint tileX, uint tileY, VMapManager vm)
|
||||
{
|
||||
string tilefile = vmapPath + getTileFileName(mapID, tileX, tileY);
|
||||
if (!File.Exists(tilefile))
|
||||
{
|
||||
int parentMapId = vm.getParentMapId(mapID);
|
||||
if (parentMapId != -1)
|
||||
tilefile = vmapPath + getTileFileName((uint)parentMapId, tileX, tileY);
|
||||
}
|
||||
|
||||
if (!File.Exists(tilefile))
|
||||
return null;
|
||||
|
||||
return new FileStream(tilefile, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
|
||||
public static bool CanLoadMap(string vmapPath, uint mapID, uint tileX, uint tileY, VMapManager vm)
|
||||
{
|
||||
string fullname = vmapPath + VMapManager.getMapFileName(mapID);
|
||||
bool success = true;
|
||||
if (!File.Exists(fullname))
|
||||
return false;
|
||||
|
||||
@@ -239,21 +285,24 @@ namespace Game.Collision
|
||||
{
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
return false;
|
||||
|
||||
char tiled = reader.ReadChar();
|
||||
if (tiled == 1)
|
||||
{
|
||||
string tilefile = vmapPath + getTileFileName(mapID, tileX, tileY);
|
||||
if (!File.Exists(tilefile))
|
||||
|
||||
FileStream stream = OpenMapTileFile(vmapPath, mapID, tileX, tileY, vm);
|
||||
if (stream == null)
|
||||
return false;
|
||||
|
||||
using (BinaryReader reader1 = new BinaryReader(new FileStream(tilefile, FileMode.Open, FileAccess.Read)))
|
||||
using (BinaryReader reader1 = new BinaryReader(stream))
|
||||
{
|
||||
if (reader1.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
success = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
|
||||
return true;
|
||||
}
|
||||
public static string getTileFileName(uint mapID, uint tileX, uint tileY)
|
||||
{
|
||||
@@ -380,6 +429,7 @@ namespace Game.Collision
|
||||
BIH iTree = new BIH();
|
||||
ModelInstance[] iTreeValues;
|
||||
uint iNTreeValues;
|
||||
Dictionary<uint, uint> iSpawnIndices = new Dictionary<uint, uint>();
|
||||
|
||||
Dictionary<uint, bool> iLoadedTiles = new Dictionary<uint, bool>();
|
||||
Dictionary<uint, uint> iLoadedSpawns = new Dictionary<uint, uint>();
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Game.Collision
|
||||
{
|
||||
public virtual bool IsSpawned() { return false; }
|
||||
public virtual uint GetDisplayId() { return 0; }
|
||||
public virtual bool IsInPhase(List<uint> phases) { return false; }
|
||||
public virtual bool IsInPhase(PhaseShift phaseShift) { return false; }
|
||||
public virtual Vector3 GetPosition() { return Vector3.Zero; }
|
||||
public virtual float GetOrientation() { return 0.0f; }
|
||||
public virtual float GetScale() { return 1.0f; }
|
||||
@@ -86,12 +86,12 @@ namespace Game.Collision
|
||||
return mdl;
|
||||
}
|
||||
|
||||
public override bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, List<uint> phases)
|
||||
public override bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift)
|
||||
{
|
||||
if (!isCollisionEnabled() || !owner.IsSpawned())
|
||||
return false;
|
||||
|
||||
if (!owner.IsInPhase(phases))
|
||||
if (!owner.IsInPhase(phaseShift))
|
||||
return false;
|
||||
|
||||
float time = ray.intersectionTime(iBound);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Game.Collision
|
||||
public virtual Vector3 getPosition() { return default(Vector3); }
|
||||
public virtual AxisAlignedBox getBounds() { return default(AxisAlignedBox); }
|
||||
|
||||
public virtual bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, List<uint> phases) { return false; }
|
||||
public virtual bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift) { return false; }
|
||||
public virtual bool IntersectRay(Ray ray, ref float distance, bool stopAtFirstHit) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ namespace Game.Conditions
|
||||
condMeets = (ConditionValue2 == Global.WorldMgr.getWorldState((WorldStates)ConditionValue1));
|
||||
break;
|
||||
case ConditionTypes.PhaseId:
|
||||
condMeets = obj.IsInPhase(ConditionValue1);
|
||||
condMeets = obj.GetPhaseShift().HasPhase(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.Title:
|
||||
if (player != null)
|
||||
@@ -303,7 +303,7 @@ namespace Game.Conditions
|
||||
condMeets = unit.IsInWater();
|
||||
break;
|
||||
case ConditionTypes.TerrainSwap:
|
||||
condMeets = obj.IsInTerrainSwap(ConditionValue1);
|
||||
condMeets = obj.GetPhaseShift().HasVisibleMapId(ConditionValue1);
|
||||
break;
|
||||
case ConditionTypes.StandState:
|
||||
{
|
||||
|
||||
@@ -307,17 +307,7 @@ namespace Game
|
||||
Global.ObjectMgr.LoadGossipMenuItems();
|
||||
Global.SpellMgr.UnloadSpellInfoImplicitTargetConditionLists();
|
||||
|
||||
Log.outInfo(LogFilter.Server, "Re-Loading `terrain_phase_info` Table for Conditions!");
|
||||
Global.ObjectMgr.LoadTerrainPhaseInfo();
|
||||
|
||||
Log.outInfo(LogFilter.Server, "Re-Loading `terrain_swap_defaults` Table for Conditions!");
|
||||
Global.ObjectMgr.LoadTerrainSwapDefaults();
|
||||
|
||||
Log.outInfo(LogFilter.Server, "Re-Loading `terrain_worldmap` Table for Conditions!");
|
||||
Global.ObjectMgr.LoadTerrainWorldMaps();
|
||||
|
||||
Log.outInfo(LogFilter.Server, "Re-Loading `phase_area` Table for Conditions!");
|
||||
Global.ObjectMgr.LoadAreaPhases();
|
||||
Global.ObjectMgr.UnloadPhaseConditions();
|
||||
}
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, " +
|
||||
@@ -689,29 +679,36 @@ namespace Game
|
||||
{
|
||||
if (cond.SourceEntry == 0)
|
||||
{
|
||||
bool found = false;
|
||||
var map = Global.ObjectMgr.GetAreaAndZonePhases();
|
||||
foreach (var key in map.Keys)
|
||||
PhaseInfoStruct phaseInfo = Global.ObjectMgr.GetPhaseInfo(cond.SourceGroup);
|
||||
if (phaseInfo != null)
|
||||
{
|
||||
foreach (PhaseInfoStruct phase in map[key])
|
||||
bool found = false;
|
||||
foreach (uint areaId in phaseInfo.Areas)
|
||||
{
|
||||
if (phase.Id == cond.SourceGroup)
|
||||
List<PhaseAreaInfo> phases = Global.ObjectMgr.GetPhasesForArea(areaId);
|
||||
if (phases != null)
|
||||
{
|
||||
phase.Conditions.Add(cond);
|
||||
found = true;
|
||||
foreach (PhaseAreaInfo phase in phases)
|
||||
{
|
||||
if (phase.PhaseInfo.Id == cond.SourceGroup)
|
||||
{
|
||||
phase.Conditions.Add(cond);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
return true;
|
||||
if (found)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var phases = Global.ObjectMgr.GetPhasesForAreaOrZoneForLoading((uint)cond.SourceEntry);
|
||||
foreach (PhaseInfoStruct phase in phases)
|
||||
var phases = Global.ObjectMgr.GetPhasesForArea((uint)cond.SourceEntry);
|
||||
foreach (PhaseAreaInfo phase in phases)
|
||||
{
|
||||
if (phase.Id == cond.SourceGroup)
|
||||
if (phase.PhaseInfo.Id == cond.SourceGroup)
|
||||
{
|
||||
phase.Conditions.Add(cond);
|
||||
return true;
|
||||
@@ -1990,15 +1987,9 @@ namespace Game
|
||||
|| condition.MinExpansionLevel > WorldConfig.GetIntValue(WorldCfg.Expansion)))
|
||||
return false;
|
||||
|
||||
if (condition.PhaseID != 0 && !player.IsInPhase(condition.PhaseID))
|
||||
return false;
|
||||
|
||||
if (condition.PhaseGroupID != 0)
|
||||
{
|
||||
var phases = Global.DB2Mgr.GetPhasesForGroup(condition.PhaseGroupID);
|
||||
if (!phases.Intersect(player.GetPhases()).Any())
|
||||
if (condition.PhaseID != 0 || condition.PhaseGroupID != 0 || condition.PhaseUseFlags != 0)
|
||||
if (!PhasingHandler.InDbPhaseShift(player, (PhaseUseFlagsValues)condition.PhaseUseFlags, condition.PhaseID, condition.PhaseGroupID))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (condition.QuestKillID != 0)
|
||||
{
|
||||
|
||||
@@ -498,8 +498,6 @@ namespace Game.DataStorage
|
||||
|
||||
foreach (WorldMapAreaRecord worldMapArea in CliDB.WorldMapAreaStorage.Values)
|
||||
_worldMapAreaByAreaID[worldMapArea.AreaID] = worldMapArea;
|
||||
|
||||
CliDB.WorldMapAreaStorage.Clear();
|
||||
}
|
||||
|
||||
public IDB2Storage GetStorage(uint type)
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Game.DataStorage
|
||||
public sealed class PhaseRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort Flags;
|
||||
public PhaseEntryFlags Flags;
|
||||
}
|
||||
|
||||
public sealed class PhaseXPhaseGroupRecord
|
||||
|
||||
@@ -552,6 +552,6 @@ namespace Game.DataStorage
|
||||
public SummonCategory Control;
|
||||
public ushort Faction;
|
||||
public SummonType Title;
|
||||
public byte Slot;
|
||||
public sbyte Slot;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ using Game.Network.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Game;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
@@ -125,7 +126,7 @@ namespace Game.Entities
|
||||
if (GetMiscTemplate().ScaleInfo.ExtraScale[scaleCurveIndex].AsInt32 != 0)
|
||||
SetUInt32Value(AreaTriggerFields.ExtraScaleCurve + scaleCurveIndex, (uint)GetMiscTemplate().ScaleInfo.ExtraScale[scaleCurveIndex].AsInt32);
|
||||
|
||||
CopyPhaseFrom(caster);
|
||||
PhasingHandler.InheritPhaseShift(this, caster);
|
||||
|
||||
if (target && GetTemplate().HasFlag(AreaTriggerFlags.HasAttached))
|
||||
{
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Game.Entities
|
||||
Relocate(pos);
|
||||
|
||||
base._Create(ObjectGuid.Create(HighGuid.Conversation, GetMapId(), conversationEntry, lowGuid));
|
||||
CopyPhaseFrom(creator);
|
||||
PhasingHandler.InheritPhaseShift(this, creator);
|
||||
|
||||
SetEntry(conversationEntry);
|
||||
SetObjectScale(1.0f);
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Game.Entities
|
||||
|
||||
_cellCoord = GridDefines.ComputeCellCoord(GetPositionX(), GetPositionY());
|
||||
|
||||
CopyPhaseFrom(owner);
|
||||
PhasingHandler.InheritPhaseShift(this, owner);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -114,12 +114,12 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, GetInstanceId()); // instanceId
|
||||
trans.Append(stmt);
|
||||
|
||||
foreach (uint phaseId in GetPhases())
|
||||
foreach (PhaseRef phase in GetPhaseShift().GetPhases())
|
||||
{
|
||||
index = 0;
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CORPSE_PHASES);
|
||||
stmt.AddValue(index++, GetOwnerGUID().GetCounter()); // OwnerGuid
|
||||
stmt.AddValue(index++, phaseId); // PhaseId
|
||||
stmt.AddValue(index++, phase.Id); // PhaseId
|
||||
trans.Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,12 +741,11 @@ namespace Game.Entities
|
||||
{
|
||||
SetMap(map);
|
||||
|
||||
if (data != null && data.phaseId != 0)
|
||||
SetInPhase(data.phaseId, false, true);
|
||||
|
||||
if (data != null && data.phaseGroup != 0)
|
||||
foreach (var ph in Global.DB2Mgr.GetPhasesForGroup(data.phaseGroup))
|
||||
SetInPhase(ph, false, true);
|
||||
if (data != null)
|
||||
{
|
||||
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
|
||||
PhasingHandler.InitDbVisibleMapId(GetPhaseShift(), data.terrainSwapMap);
|
||||
}
|
||||
|
||||
CreatureTemplate cinfo = Global.ObjectMgr.GetCreatureTemplate(entry);
|
||||
if (cinfo == null)
|
||||
@@ -2623,7 +2622,7 @@ namespace Game.Entities
|
||||
return;
|
||||
|
||||
// Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
|
||||
float ground = GetMap().GetHeight(GetPhases(), GetPositionX(), GetPositionY(), GetPositionZMinusOffset());
|
||||
float ground = GetMap().GetHeight(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZMinusOffset());
|
||||
|
||||
bool isInAir = (MathFunctions.fuzzyGt(GetPositionZMinusOffset(), ground + 0.05f) || MathFunctions.fuzzyLt(GetPositionZMinusOffset(), ground - 0.05f)); // Can be underground too, prevent the falling
|
||||
|
||||
@@ -2934,7 +2933,7 @@ namespace Game.Entities
|
||||
m_deathState = DeathState.Dead;
|
||||
if (CanFly())
|
||||
{
|
||||
float tz = map.GetHeight(GetPhases(), data.posX, data.posY, data.posZ, true, MapConst.MaxFallDistance);
|
||||
float tz = map.GetHeight(GetPhaseShift(), data.posX, data.posY, data.posZ, true, MapConst.MaxFallDistance);
|
||||
if (data.posZ - tz > 0.1f && GridDefines.IsValidMapCoord(tz))
|
||||
Relocate(data.posX, data.posY, tz);
|
||||
}
|
||||
|
||||
@@ -297,8 +297,10 @@ namespace Game.Entities
|
||||
public uint unit_flags2; // enum UnitFlags2 mask values
|
||||
public uint unit_flags3; // enum UnitFlags3 mask values
|
||||
public uint dynamicflags;
|
||||
public PhaseUseFlagsValues phaseUseFlags;
|
||||
public uint phaseId;
|
||||
public uint phaseGroup;
|
||||
public int terrainSwapMap;
|
||||
public uint ScriptId;
|
||||
public bool dbData;
|
||||
}
|
||||
|
||||
@@ -948,15 +948,8 @@ namespace Game.Entities
|
||||
if (!Create(entry, map, pos, data.rotation, animprogress, go_state, artKit))
|
||||
return false;
|
||||
|
||||
if (data.phaseId != 0)
|
||||
SetInPhase(data.phaseId, false, true);
|
||||
|
||||
if (data.phaseGroup != 0)
|
||||
{
|
||||
// Set the gameobject in all the phases of the phasegroup
|
||||
foreach (var ph in Global.DB2Mgr.GetPhasesForGroup(data.phaseGroup))
|
||||
SetInPhase(ph, false, true);
|
||||
}
|
||||
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
|
||||
PhasingHandler.InitDbVisibleMapId(GetPhaseShift(), data.terrainSwapMap);
|
||||
|
||||
if (data.spawntimesecs >= 0)
|
||||
{
|
||||
@@ -2766,7 +2759,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
public override uint GetDisplayId() { return _owner.GetDisplayId(); }
|
||||
public override bool IsInPhase(List<uint> phases) { return _owner.IsInPhase(phases); }
|
||||
public override bool IsInPhase(PhaseShift phaseShift) { return _owner.GetPhaseShift().CanSee(phaseShift); }
|
||||
public override Vector3 GetPosition() { return new Vector3(_owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ()); }
|
||||
public override float GetOrientation() { return _owner.GetOrientation(); }
|
||||
public override float GetScale() { return _owner.GetObjectScale(); }
|
||||
|
||||
@@ -1089,8 +1089,10 @@ namespace Game.Entities
|
||||
public GameObjectState go_state;
|
||||
public ulong spawnMask;
|
||||
public byte artKit;
|
||||
public PhaseUseFlagsValues phaseUseFlags;
|
||||
public uint phaseId;
|
||||
public uint phaseGroup;
|
||||
public int terrainSwapMap;
|
||||
public uint ScriptId;
|
||||
public bool dbData = true;
|
||||
}
|
||||
|
||||
@@ -1608,17 +1608,17 @@ namespace Game.Entities
|
||||
|
||||
public uint GetZoneId()
|
||||
{
|
||||
return GetMap().GetZoneId(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
return GetMap().GetZoneId(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
}
|
||||
|
||||
public uint GetAreaId()
|
||||
{
|
||||
return GetMap().GetAreaId(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
return GetMap().GetAreaId(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
}
|
||||
|
||||
public void GetZoneAndAreaId(out uint zoneid, out uint areaid)
|
||||
{
|
||||
GetMap().GetZoneAndAreaId(out zoneid, out areaid, posX, posY, posZ);
|
||||
GetMap().GetZoneAndAreaId(GetPhaseShift(), out zoneid, out areaid, posX, posY, posZ);
|
||||
}
|
||||
|
||||
public InstanceScript GetInstanceScript()
|
||||
@@ -2047,7 +2047,7 @@ namespace Game.Entities
|
||||
if (!go)
|
||||
return null;
|
||||
|
||||
go.CopyPhaseFrom(this);
|
||||
PhasingHandler.InheritPhaseShift(go, this);
|
||||
|
||||
go.SetRespawnTime((int)respawnTime);
|
||||
if (IsTypeId(TypeId.Player) || IsTypeId(TypeId.Unit)) //not sure how to handle this
|
||||
@@ -2154,242 +2154,15 @@ namespace Game.Entities
|
||||
return (valuesCount > (uint)UnitFields.CombatReach) ? GetFloatValue(UnitFields.CombatReach) : SharedConst.DefaultWorldObjectSize;
|
||||
}
|
||||
|
||||
bool HasInPhaseList(uint phase)
|
||||
{
|
||||
return _phases.Contains(phase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates Area based phases, does not remove phases from auras
|
||||
/// Phases from gm commands are not taken into calculations, they can be lost!!
|
||||
/// </summary>
|
||||
public void UpdateAreaAndZonePhase()
|
||||
{
|
||||
bool updateNeeded = false;
|
||||
var allAreasPhases = Global.ObjectMgr.GetAreaAndZonePhases();
|
||||
uint[] zoneAndArea = { GetZoneId(), GetAreaId() };
|
||||
|
||||
// We first remove all phases from other areas & zones
|
||||
foreach (var key in allAreasPhases.Keys)
|
||||
foreach (PhaseInfoStruct phase in allAreasPhases[key])
|
||||
if (!Global.DB2Mgr.IsInArea(GetAreaId(), key))
|
||||
updateNeeded = SetInPhase(phase.Id, false, false) || updateNeeded; // not in area, remove phase, true if there was something removed
|
||||
|
||||
// Then we add the phases from this area and zone if conditions are met
|
||||
// Zone is done before Area, so if Area does not meet condition, the phase will be removed
|
||||
foreach (uint area in zoneAndArea)
|
||||
{
|
||||
var currentPhases = Global.ObjectMgr.GetPhasesForArea(area);
|
||||
if (currentPhases != null)
|
||||
{
|
||||
foreach (PhaseInfoStruct phaseInfoStruct in currentPhases)
|
||||
{
|
||||
bool apply = Global.ConditionMgr.IsObjectMeetToConditions(this, phaseInfoStruct.Conditions);
|
||||
|
||||
// add or remove phase depending of condition
|
||||
updateNeeded = SetInPhase(phaseInfoStruct.Id, false, apply) || updateNeeded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do not remove a phase if it would be removed by an area but we have the same phase from an aura
|
||||
Unit unit = ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
var auraPhaseList = unit.GetAuraEffectsByType(AuraType.Phase);
|
||||
foreach (var eff in auraPhaseList)
|
||||
{
|
||||
uint phase = (uint)eff.GetMiscValueB();
|
||||
updateNeeded = SetInPhase(phase, false, true) || updateNeeded;
|
||||
}
|
||||
var auraPhaseGroupList = unit.GetAuraEffectsByType(AuraType.PhaseGroup);
|
||||
foreach (var eff in auraPhaseGroupList)
|
||||
{
|
||||
uint phaseGroup = (uint)eff.GetMiscValueB();
|
||||
foreach (uint phase in Global.DB2Mgr.GetPhasesForGroup(phaseGroup))
|
||||
updateNeeded = SetInPhase(phase, false, true) || updateNeeded;
|
||||
}
|
||||
}
|
||||
|
||||
// only update visibility and send packets if there was a change in the phase list
|
||||
|
||||
if (updateNeeded && IsTypeId(TypeId.Player) && IsInWorld)
|
||||
ToPlayer().GetSession().SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps());
|
||||
|
||||
// only update visibilty once, to prevent objects appearing for a moment while adding in multiple phases
|
||||
if (updateNeeded && IsInWorld)
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
|
||||
public virtual bool SetInPhase(uint id, bool update, bool apply)
|
||||
{
|
||||
if (id != 0)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
// do not run the updates if we are already in this phase
|
||||
if (_phases.Contains(id))
|
||||
return false;
|
||||
|
||||
_phases.Add(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_phases.Contains(id))
|
||||
return false;
|
||||
|
||||
// if area phase passes the condition we should not remove it (ie: if remove called from aura remove)
|
||||
// this however breaks the .mod phase command, you wont be able to remove any area based phases with it
|
||||
var phases = Global.ObjectMgr.GetPhasesForArea(GetAreaId());
|
||||
if (phases != null)
|
||||
{
|
||||
foreach (PhaseInfoStruct phase in phases)
|
||||
{
|
||||
if (id == phase.Id)
|
||||
if (Global.ConditionMgr.IsObjectMeetToConditions(this, phase.Conditions))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_phases.Remove(id);
|
||||
}
|
||||
}
|
||||
RebuildTerrainSwaps();
|
||||
|
||||
if (update && IsInWorld)
|
||||
UpdateObjectVisibility();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void CopyPhaseFrom(WorldObject obj, bool update = false)
|
||||
{
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
foreach (uint phase in obj.GetPhases())
|
||||
SetInPhase(phase, false, true);
|
||||
|
||||
if (update && IsInWorld)
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
|
||||
public void ClearPhases(bool update = false)
|
||||
{
|
||||
_phases.Clear();
|
||||
|
||||
RebuildTerrainSwaps();
|
||||
|
||||
if (update && IsInWorld)
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
|
||||
public bool IsInPhase(uint phase) { return _phases.Contains(phase); }
|
||||
|
||||
public bool IsInPhase(List<uint> phases)
|
||||
{
|
||||
// PhaseId 169 is the default fallback phase
|
||||
if (_phases.Empty() && phases.Empty())
|
||||
return true;
|
||||
|
||||
if (_phases.Empty() && phases.Contains(169))
|
||||
return true;
|
||||
|
||||
if (phases.Empty() && _phases.Contains(169))
|
||||
return true;
|
||||
|
||||
return _phases.Intersect(phases).Any();
|
||||
}
|
||||
|
||||
public bool IsInPhase(WorldObject obj)
|
||||
{
|
||||
// PhaseId 169 is the default fallback phase
|
||||
if (_phases.Empty() && obj.GetPhases().Empty())
|
||||
return true;
|
||||
|
||||
if (_phases.Empty() && obj.IsInPhase(169))
|
||||
return true;
|
||||
|
||||
if (obj.GetPhases().Empty() && IsInPhase(169))
|
||||
return true;
|
||||
|
||||
if (IsTypeId(TypeId.Player) && ToPlayer().IsGameMaster())
|
||||
return true;
|
||||
|
||||
return IsInPhase(obj.GetPhases());
|
||||
return GetPhaseShift().CanSee(obj.GetPhaseShift());
|
||||
}
|
||||
|
||||
public bool IsInTerrainSwap(uint terrainSwap) { return _terrainSwaps.Contains(terrainSwap); }
|
||||
|
||||
public void RebuildTerrainSwaps()
|
||||
{
|
||||
// Clear all terrain swaps, will be rebuilt below
|
||||
// Reason for this is, multiple phases can have the same terrain swap, we should not remove the swap if another phase still use it
|
||||
_terrainSwaps.Clear();
|
||||
|
||||
// Check all applied phases for terrain swap and add it only once
|
||||
foreach (uint phaseId in _phases)
|
||||
{
|
||||
var swaps = Global.ObjectMgr.GetPhaseTerrainSwaps(phaseId);
|
||||
foreach (uint swap in swaps)
|
||||
{
|
||||
// only add terrain swaps for current map
|
||||
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(swap);
|
||||
if (mapEntry == null || mapEntry.ParentMapID != GetMapId())
|
||||
continue;
|
||||
|
||||
if (Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.TerrainSwap, swap, this))
|
||||
_terrainSwaps.Add(swap);
|
||||
}
|
||||
}
|
||||
|
||||
// get default terrain swaps, only for current map always
|
||||
var mapSwaps = Global.ObjectMgr.GetDefaultTerrainSwaps(GetMapId());
|
||||
foreach (uint swap in mapSwaps)
|
||||
{
|
||||
if (Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.TerrainSwap, swap, this))
|
||||
_terrainSwaps.Add(swap);
|
||||
}
|
||||
|
||||
// online players have a game client with world map display
|
||||
if (IsTypeId(TypeId.Player))
|
||||
RebuildWorldMapAreaSwaps();
|
||||
}
|
||||
|
||||
void RebuildWorldMapAreaSwaps()
|
||||
{
|
||||
// Clear all world map area swaps, will be rebuilt below
|
||||
_worldMapAreaSwaps.Clear();
|
||||
|
||||
// get ALL default terrain swaps, if we are using it (condition is true)
|
||||
// send the worldmaparea for it, to see swapped worldmaparea in client from other maps too, not just from our current
|
||||
var defaults = Global.ObjectMgr.GetDefaultTerrainSwapStore();
|
||||
foreach (uint swap in defaults.Values)
|
||||
{
|
||||
var uiMapSwaps = Global.ObjectMgr.GetTerrainWorldMaps(swap);
|
||||
if (Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.TerrainSwap, swap, this))
|
||||
{
|
||||
foreach (uint worldMapAreaId in uiMapSwaps)
|
||||
_worldMapAreaSwaps.Add(worldMapAreaId);
|
||||
}
|
||||
}
|
||||
|
||||
// Check all applied phases for world map area swaps
|
||||
foreach (uint phaseId in _phases)
|
||||
{
|
||||
var swaps = Global.ObjectMgr.GetPhaseTerrainSwaps(phaseId);
|
||||
foreach (uint swap in swaps)
|
||||
{
|
||||
var uiMapSwaps = Global.ObjectMgr.GetTerrainWorldMaps(swap);
|
||||
if (Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.TerrainSwap, swap, this))
|
||||
foreach (uint worldMapAreaId in uiMapSwaps)
|
||||
_worldMapAreaSwaps.Add(worldMapAreaId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<uint> GetPhases() { return _phases; }
|
||||
public List<uint> GetTerrainSwaps() { return _terrainSwaps; }
|
||||
public List<uint> GetWorldMapAreaSwaps() { return _worldMapAreaSwaps; }
|
||||
public PhaseShift GetPhaseShift() { return _phaseShift; }
|
||||
public void SetPhaseShift(PhaseShift phaseShift) { _phaseShift = phaseShift; }
|
||||
public PhaseShift GetSuppressedPhaseShift() { return _suppressedPhaseShift; }
|
||||
public void SetSuppressedPhaseShift(PhaseShift phaseShift) { _suppressedPhaseShift = phaseShift; }
|
||||
public int GetDBPhase() { return _dbPhase; }
|
||||
|
||||
// if negative it is used as PhaseGroupId
|
||||
@@ -2707,7 +2480,7 @@ namespace Game.Entities
|
||||
else
|
||||
GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z);
|
||||
|
||||
return GetMap().isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhases());
|
||||
return GetMap().isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2838,7 +2611,7 @@ namespace Game.Entities
|
||||
|
||||
public void UpdateGroundPositionZ(float x, float y, ref float z)
|
||||
{
|
||||
float new_z = GetMap().GetHeight(GetPhases(), x, y, z, true);
|
||||
float new_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true);
|
||||
if (new_z > MapConst.InvalidHeight)
|
||||
z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface
|
||||
}
|
||||
@@ -2860,8 +2633,8 @@ namespace Game.Entities
|
||||
bool canSwim = ToCreature().CanSwim();
|
||||
float ground_z = z;
|
||||
float max_z = canSwim
|
||||
? GetMap().GetWaterOrGroundLevel(GetPhases(), x, y, z, ref ground_z, !ToUnit().HasAuraType(AuraType.WaterWalk))
|
||||
: ((ground_z = GetMap().GetHeight(GetPhases(), x, y, z, true)));
|
||||
? GetMap().GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ref ground_z, !ToUnit().HasAuraType(AuraType.WaterWalk))
|
||||
: ((ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true)));
|
||||
if (max_z > MapConst.InvalidHeight)
|
||||
{
|
||||
if (z > max_z)
|
||||
@@ -2872,7 +2645,7 @@ namespace Game.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetMap().GetHeight(GetPhases(), x, y, z, true);
|
||||
float ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true);
|
||||
if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
@@ -2884,7 +2657,7 @@ namespace Game.Entities
|
||||
if (!ToPlayer().CanFly())
|
||||
{
|
||||
float ground_z = z;
|
||||
float max_z = GetMap().GetWaterOrGroundLevel(GetPhases(), x, y, z, ref ground_z, !ToUnit().HasAuraType(AuraType.WaterWalk));
|
||||
float max_z = GetMap().GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ref ground_z, !ToUnit().HasAuraType(AuraType.WaterWalk));
|
||||
if (max_z > MapConst.InvalidHeight)
|
||||
{
|
||||
if (z > max_z)
|
||||
@@ -2895,7 +2668,7 @@ namespace Game.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
float ground_z = GetMap().GetHeight(GetPhases(), x, y, z, true);
|
||||
float ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true);
|
||||
if (z < ground_z)
|
||||
z = ground_z;
|
||||
}
|
||||
@@ -2903,7 +2676,7 @@ namespace Game.Entities
|
||||
}
|
||||
default:
|
||||
{
|
||||
float ground_z = GetMap().GetHeight(GetPhases(), x, y, z, true);
|
||||
float ground_z = GetMap().GetHeight(GetPhaseShift(), x, y, z, true);
|
||||
if (ground_z > MapConst.InvalidHeight)
|
||||
z = ground_z;
|
||||
break;
|
||||
@@ -3002,8 +2775,8 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
ground = GetMap().GetHeight(GetPhases(), destx, desty, MapConst.MaxHeight, true);
|
||||
floor = GetMap().GetHeight(GetPhases(), destx, desty, pos.posZ, true);
|
||||
ground = GetMap().GetHeight(GetPhaseShift(), destx, desty, MapConst.MaxHeight, true);
|
||||
floor = GetMap().GetHeight(GetPhaseShift(), destx, desty, pos.posZ, true);
|
||||
destz = Math.Abs(ground - pos.posZ) <= Math.Abs(floor - pos.posZ) ? ground : floor;
|
||||
|
||||
float step = dist / 10.0f;
|
||||
@@ -3015,8 +2788,8 @@ namespace Game.Entities
|
||||
{
|
||||
destx -= step * (float)Math.Cos(angle);
|
||||
desty -= step * (float)Math.Sin(angle);
|
||||
ground = GetMap().GetHeight(GetPhases(), destx, desty, MapConst.MaxHeight, true);
|
||||
floor = GetMap().GetHeight(GetPhases(), destx, desty, pos.posZ, true);
|
||||
ground = GetMap().GetHeight(GetPhaseShift(), destx, desty, MapConst.MaxHeight, true);
|
||||
floor = GetMap().GetHeight(GetPhaseShift(), destx, desty, pos.posZ, true);
|
||||
destz = Math.Abs(ground - pos.posZ) <= Math.Abs(floor - pos.posZ) ? ground : floor;
|
||||
}
|
||||
// we have correct destz now
|
||||
@@ -3035,8 +2808,8 @@ namespace Game.Entities
|
||||
|
||||
float NormalizeZforCollision(WorldObject obj, float x, float y, float z)
|
||||
{
|
||||
float ground = obj.GetMap().GetHeight(obj.GetPhases(), x, y, MapConst.MaxHeight, true);
|
||||
float floor = obj.GetMap().GetHeight(obj.GetPhases(), x, y, z + 2.0f, true);
|
||||
float ground = obj.GetMap().GetHeight(obj.GetPhaseShift(), x, y, MapConst.MaxHeight, true);
|
||||
float floor = obj.GetMap().GetHeight(obj.GetPhaseShift(), x, y, z + 2.0f, true);
|
||||
float helper = Math.Abs(ground - z) <= Math.Abs(floor - z) ? ground : floor;
|
||||
if (z > helper) // must be above ground
|
||||
{
|
||||
@@ -3047,7 +2820,7 @@ namespace Game.Entities
|
||||
return z;
|
||||
}
|
||||
LiquidData liquid_status;
|
||||
ZLiquidStatus res = obj.GetMap().getLiquidStatus(x, y, z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
ZLiquidStatus res = obj.GetMap().getLiquidStatus(obj.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
if (res != 0 && liquid_status.level > helper) // water must be above ground
|
||||
{
|
||||
if (liquid_status.level > z) // z is underwater
|
||||
@@ -3074,7 +2847,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ());
|
||||
bool col = Global.VMapMgr.getObjectHitPos(GetMapId(), pos.posX, pos.posY, pos.posZ + 0.5f, destx, desty, destz + 0.5f, out destx, out desty, out destz, -0.5f);
|
||||
bool col = Global.VMapMgr.getObjectHitPos(PhasingHandler.GetTerrainMapId(GetPhaseShift(), GetMap(), pos.posX, pos.posY), pos.posX, pos.posY, pos.posZ + 0.5f, destx, desty, destz + 0.5f, out destx, out desty, out destz, -0.5f);
|
||||
|
||||
// collision occured
|
||||
if (col)
|
||||
@@ -3086,7 +2859,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// check dynamic collision
|
||||
col = GetMap().getObjectHitPos(GetPhases(), pos.posX, pos.posY, pos.posZ + 0.5f, destx, desty, destz + 0.5f, out destx, out desty, out destz, -0.5f);
|
||||
col = GetMap().getObjectHitPos(GetPhaseShift(), pos.posX, pos.posY, pos.posZ + 0.5f, destx, desty, destz + 0.5f, out destx, out desty, out destz, -0.5f);
|
||||
|
||||
// Collided with a gameobject
|
||||
if (col)
|
||||
@@ -3150,9 +2923,8 @@ namespace Game.Entities
|
||||
Transport m_transport;
|
||||
Map _currMap;
|
||||
uint instanceId;
|
||||
List<uint> _phases = new List<uint>();
|
||||
List<uint> _terrainSwaps = new List<uint>();
|
||||
List<uint> _worldMapAreaSwaps = new List<uint>();
|
||||
PhaseShift _phaseShift= new PhaseShift();
|
||||
PhaseShift _suppressedPhaseShift = new PhaseShift(); // contains phases for current area but not applied due to conditions
|
||||
int _dbPhase;
|
||||
public bool IsInWorld { get; set; }
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace Game.Entities
|
||||
if (!Create(map.GenerateLowGuid(HighGuid.Pet), map, petEntry))
|
||||
return false;
|
||||
|
||||
CopyPhaseFrom(owner);
|
||||
PhasingHandler.InheritPhaseShift(this, owner);
|
||||
|
||||
setPetType(petType);
|
||||
SetFaction(owner.getFaction());
|
||||
|
||||
@@ -3550,7 +3550,7 @@ namespace Game.Entities
|
||||
if (!CliDB.MapStorage.ContainsKey(map))
|
||||
return 0;
|
||||
|
||||
zone = Global.MapMgr.GetZoneId(map, posx, posy, posz);
|
||||
zone = Global.MapMgr.GetZoneId(PhasingHandler.EmptyPhaseShift, map, posx, posy, posz);
|
||||
|
||||
if (zone > 0)
|
||||
{
|
||||
|
||||
@@ -191,6 +191,7 @@ namespace Game.Entities
|
||||
|
||||
SpecializationInfo _specializationInfo;
|
||||
public List<ObjectGuid> m_clientGUIDs = new List<ObjectGuid>();
|
||||
public List<ObjectGuid> m_visibleTransports = new List<ObjectGuid>();
|
||||
public WorldObject seerView;
|
||||
// only changed for direct client control (possess, vehicle etc.), not stuff you control using pet commands
|
||||
public Unit m_unitMovedByMe;
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace Game.Entities
|
||||
UpdatePvPState(true);
|
||||
|
||||
UpdateAreaDependentAuras(newArea);
|
||||
UpdateAreaAndZonePhase();
|
||||
PhasingHandler.OnAreaChange(this);
|
||||
|
||||
if (IsAreaThatActivatesPvpTalents(newArea))
|
||||
EnablePvpRules();
|
||||
@@ -232,8 +232,6 @@ namespace Game.Entities
|
||||
UpdateLocalChannels(newZone);
|
||||
|
||||
UpdateZoneDependentAuras(newZone);
|
||||
|
||||
UpdateAreaAndZonePhase();
|
||||
}
|
||||
|
||||
public InstanceBind GetBoundInstance(uint mapid, Difficulty difficulty, bool withExpired = false)
|
||||
@@ -721,7 +719,7 @@ namespace Game.Entities
|
||||
public override void UpdateUnderwaterState(Map m, float x, float y, float z)
|
||||
{
|
||||
LiquidData liquid_status;
|
||||
ZLiquidStatus res = m.getLiquidStatus(x, y, z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
ZLiquidStatus res = m.getLiquidStatus(GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
if (res == 0)
|
||||
{
|
||||
m_MirrorTimerFlags &= ~(PlayerUnderwaterState.InWater | PlayerUnderwaterState.InLava | PlayerUnderwaterState.InSlime | PlayerUnderwaterState.InDarkWater);
|
||||
|
||||
@@ -1817,7 +1817,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
UpdateForQuestWorldObjects();
|
||||
SendUpdatePhasing();
|
||||
PhasingHandler.OnConditionChange(this);
|
||||
}
|
||||
|
||||
public QuestGiverStatus GetQuestDialogStatus(WorldObject questgiver)
|
||||
|
||||
@@ -1937,7 +1937,7 @@ namespace Game.Entities
|
||||
public override bool IsUnderWater()
|
||||
{
|
||||
return IsInWater() &&
|
||||
GetPositionZ() < (GetMap().GetWaterLevel(GetPositionX(), GetPositionY()) - 2);
|
||||
GetPositionZ() < (GetMap().GetWaterLevel(GetPhaseShift(), GetPositionX(), GetPositionY()) - 2);
|
||||
}
|
||||
public override bool IsInWater()
|
||||
{
|
||||
@@ -2117,9 +2117,16 @@ namespace Game.Entities
|
||||
}
|
||||
public bool IsInAreaTriggerRadius(AreaTriggerRecord trigger)
|
||||
{
|
||||
if (trigger == null || GetMapId() != trigger.ContinentID)
|
||||
if (trigger == null)
|
||||
return false;
|
||||
|
||||
if (GetMapId() != trigger.ContinentID && !GetPhaseShift().HasVisibleMapId(trigger.ContinentID))
|
||||
return false;
|
||||
|
||||
if (trigger.PhaseID != 0 || trigger.PhaseGroupID != 0 || trigger.PhaseUseFlags != 0)
|
||||
if (!PhasingHandler.InDbPhaseShift(this, (PhaseUseFlagsValues)trigger.PhaseUseFlags, trigger.PhaseID, trigger.PhaseGroupID))
|
||||
return false;
|
||||
|
||||
if (trigger.Radius > 0.0f)
|
||||
{
|
||||
// if we have radius check it
|
||||
@@ -2203,10 +2210,13 @@ namespace Game.Entities
|
||||
getHostileRefManager().setOnlineOfflineState(false);
|
||||
CombatStopWithPets();
|
||||
|
||||
PhasingHandler.SetAlwaysVisible(GetPhaseShift(), true);
|
||||
m_serverSideVisibilityDetect.SetValue(ServerSideVisibilityType.GM, GetSession().GetSecurity());
|
||||
}
|
||||
else
|
||||
{
|
||||
PhasingHandler.SetAlwaysVisible(GetPhaseShift(), false);
|
||||
|
||||
m_ExtraFlags &= ~PlayerExtraFlags.GMOn;
|
||||
SetFactionForRace(GetRace());
|
||||
RemoveFlag(PlayerFields.Flags, PlayerFlags.GM);
|
||||
@@ -4820,7 +4830,7 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
pet.CopyPhaseFrom(this);
|
||||
PhasingHandler.InheritPhaseShift(pet, this);
|
||||
|
||||
pet.SetCreatorGUID(GetGUID());
|
||||
pet.SetUInt32Value(UnitFields.FactionTemplate, getFaction());
|
||||
@@ -5691,6 +5701,8 @@ namespace Game.Entities
|
||||
SendRaidDifficulty(difficulty.Flags.HasAnyFlag(DifficultyFlags.Legacy));
|
||||
}
|
||||
|
||||
PhasingHandler.OnMapChange(this);
|
||||
|
||||
if (_garrison != null)
|
||||
_garrison.SendRemoteInfo();
|
||||
|
||||
@@ -6202,7 +6214,7 @@ namespace Game.Entities
|
||||
return;
|
||||
|
||||
bool isOutdoor;
|
||||
uint areaId = GetMap().GetAreaId(GetPositionX(), GetPositionY(), GetPositionZ(), out isOutdoor);
|
||||
uint areaId = GetMap().GetAreaId(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), out isOutdoor);
|
||||
AreaTableRecord areaEntry = CliDB.AreaTableStorage.LookupByKey(areaId);
|
||||
|
||||
if (WorldConfig.GetBoolValue(WorldCfg.VmapIndoorCheck) && !isOutdoor)
|
||||
@@ -7307,16 +7319,6 @@ namespace Game.Entities
|
||||
SendMessageToSet(cancelAutoRepeat, false);
|
||||
}
|
||||
|
||||
public void SendUpdatePhasing()
|
||||
{
|
||||
if (!IsInWorld)
|
||||
return;
|
||||
|
||||
RebuildTerrainSwaps(); // to set default map swaps
|
||||
|
||||
GetSession().SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps());
|
||||
}
|
||||
|
||||
public override void BuildCreateUpdateBlockForPlayer(UpdateData data, Player target)
|
||||
{
|
||||
if (target == this)
|
||||
|
||||
@@ -338,15 +338,8 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data.phaseId != 0)
|
||||
creature.SetInPhase(data.phaseId, false, true);
|
||||
else if (data.phaseGroup != 0)
|
||||
{
|
||||
foreach (var phase in Global.DB2Mgr.GetPhasesForGroup(data.phaseGroup))
|
||||
creature.SetInPhase(phase, false, true);
|
||||
}
|
||||
else
|
||||
creature.CopyPhaseFrom(this);
|
||||
PhasingHandler.InitDbPhaseShift(creature.GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
|
||||
PhasingHandler.InitDbVisibleMapId(creature.GetPhaseShift(), data.terrainSwapMap);
|
||||
|
||||
if (!map.AddToMap(creature))
|
||||
return null;
|
||||
@@ -383,6 +376,9 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
PhasingHandler.InitDbPhaseShift(go.GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
|
||||
PhasingHandler.InitDbVisibleMapId(go.GetPhaseShift(), data.terrainSwapMap);
|
||||
|
||||
if (!map.AddToMap(go))
|
||||
return null;
|
||||
|
||||
@@ -444,12 +440,6 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
List<uint> phases = new List<uint>();
|
||||
if (summoner)
|
||||
phases = summoner.GetPhases();
|
||||
else
|
||||
phases = GetPhases(); // If there was no summoner, try to use the transport phases
|
||||
|
||||
TempSummon summon = null;
|
||||
switch (mask)
|
||||
{
|
||||
@@ -477,8 +467,7 @@ namespace Game.Entities
|
||||
if (!summon.Create(map.GenerateLowGuid(HighGuid.Creature), map, entry, x, y, z, o, null, vehId))
|
||||
return null;
|
||||
|
||||
foreach (var phase in phases)
|
||||
summon.SetInPhase(phase, false, true);
|
||||
PhasingHandler.InheritPhaseShift(summon, summoner ? (WorldObject)summoner : this);
|
||||
|
||||
summon.SetUInt32Value(UnitFields.CreatedBySpell, spellId);
|
||||
|
||||
|
||||
@@ -64,11 +64,11 @@ namespace Game.Entities
|
||||
}
|
||||
public virtual bool IsInWater()
|
||||
{
|
||||
return GetMap().IsInWater(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
return GetMap().IsInWater(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
}
|
||||
public virtual bool IsUnderWater()
|
||||
{
|
||||
return GetMap().IsUnderWater(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
return GetMap().IsUnderWater(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
}
|
||||
|
||||
void propagateSpeedChange() { GetMotionMaster().propagateSpeedChange(); }
|
||||
@@ -677,7 +677,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
LiquidData liquid;
|
||||
ZLiquidStatus liquidStatus = GetMap().getLiquidStatus(GetPositionX(), GetPositionY(), GetPositionZ(), MapConst.MapAllLiquidTypes, out liquid);
|
||||
ZLiquidStatus liquidStatus = GetMap().getLiquidStatus(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), MapConst.MapAllLiquidTypes, out liquid);
|
||||
isSubmerged = liquidStatus.HasAnyFlag(ZLiquidStatus.UnderWater) || HasUnitMovementFlag(MovementFlag.Swimming);
|
||||
isInWater = liquidStatus.HasAnyFlag(ZLiquidStatus.InWater | ZLiquidStatus.UnderWater);
|
||||
|
||||
@@ -748,7 +748,7 @@ namespace Game.Entities
|
||||
return;
|
||||
|
||||
LiquidData liquid_status;
|
||||
ZLiquidStatus res = m.getLiquidStatus(x, y, z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
ZLiquidStatus res = m.getLiquidStatus(GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
if (res == 0)
|
||||
{
|
||||
if (_lastLiquid != null && _lastLiquid.SpellID != 0)
|
||||
|
||||
@@ -784,7 +784,7 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
pet.CopyPhaseFrom(this);
|
||||
PhasingHandler.InheritPhaseShift(pet, this);
|
||||
|
||||
pet.GetCharmInfo().SetPetNumber(Global.ObjectMgr.GeneratePetNumber(), true);
|
||||
// this enables pet details window (Shift+P)
|
||||
|
||||
@@ -3313,7 +3313,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
}
|
||||
public void RemoveNotOwnSingleTargetAuras(uint newPhase = 0, bool phaseid = false)
|
||||
public void RemoveNotOwnSingleTargetAuras(bool onPhaseChange = false)
|
||||
{
|
||||
// Iterate m_ownedAuras - aura is marked as single target in Unit::AddAura (and pushed to m_ownedAuras).
|
||||
// m_appliedAuras will NOT contain the aura before first Unit::Update after adding it to m_ownedAuras.
|
||||
@@ -3330,12 +3330,12 @@ namespace Game.Entities
|
||||
|
||||
if (aura.GetCasterGUID() != GetGUID() && aura.IsSingleTarget())
|
||||
{
|
||||
if (newPhase == 0 && !phaseid)
|
||||
if (onPhaseChange)
|
||||
RemoveOwnedAura(list[i]);
|
||||
else
|
||||
{
|
||||
Unit caster = aura.GetCaster();
|
||||
if (!caster || (newPhase != 0 && !caster.IsInPhase(newPhase)) || (newPhase == 0 && !caster.IsInPhase(this)))
|
||||
if (!caster || !caster.IsInPhase(this))
|
||||
RemoveOwnedAura(list[i]);
|
||||
}
|
||||
}
|
||||
@@ -3345,7 +3345,7 @@ namespace Game.Entities
|
||||
for (var i = 0; i < m_scAuras.Count; i++)
|
||||
{
|
||||
var aura = m_scAuras[i];
|
||||
if (aura.GetUnitOwner() != this && !aura.GetUnitOwner().IsInPhase(newPhase))
|
||||
if (aura.GetUnitOwner() != this && (!onPhaseChange || !aura.GetUnitOwner().IsInPhase(this)))
|
||||
aura.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,15 +416,6 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddToWorld()
|
||||
{
|
||||
if (!IsInWorld)
|
||||
{
|
||||
base.AddToWorld();
|
||||
}
|
||||
RebuildTerrainSwaps();
|
||||
}
|
||||
|
||||
public override void RemoveFromWorld()
|
||||
{
|
||||
// cleanup
|
||||
@@ -935,7 +926,7 @@ namespace Game.Entities
|
||||
MoveSplineInit init = new MoveSplineInit(this);
|
||||
|
||||
// Creatures without inhabit type air should begin falling after exiting the vehicle
|
||||
if (IsTypeId(TypeId.Unit) && !ToCreature().CanFly() && height > GetMap().GetWaterOrGroundLevel(GetPhases(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), ref height) + 0.1f)
|
||||
if (IsTypeId(TypeId.Unit) && !ToCreature().CanFly() && height > GetMap().GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), ref height) + 0.1f)
|
||||
init.SetFall();
|
||||
|
||||
init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false);
|
||||
@@ -1099,14 +1090,12 @@ namespace Game.Entities
|
||||
|
||||
public HostileRefManager getHostileRefManager() { return m_HostileRefManager; }
|
||||
|
||||
public override bool SetInPhase(uint id, bool update, bool apply)
|
||||
public void OnPhaseChange()
|
||||
{
|
||||
bool res = base.SetInPhase(id, update, apply);
|
||||
|
||||
if (!IsInWorld)
|
||||
return res;
|
||||
return;
|
||||
|
||||
if (IsTypeId(TypeId.Unit) || (!ToPlayer().IsGameMaster() && !ToPlayer().GetSession().PlayerLogout()))
|
||||
if (IsTypeId(TypeId.Unit) || !ToPlayer().GetSession().PlayerLogout())
|
||||
{
|
||||
HostileRefManager refManager = getHostileRefManager();
|
||||
HostileReference refe = refManager.getFirst();
|
||||
@@ -1143,26 +1132,8 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var unit in m_Controlled)
|
||||
if (unit.IsTypeId(TypeId.Unit))
|
||||
unit.SetInPhase(id, true, apply);
|
||||
|
||||
for (byte i = 0; i < SharedConst.MaxSummonSlot; ++i)
|
||||
{
|
||||
if (!m_SummonSlot[i].IsEmpty())
|
||||
{
|
||||
Creature summon = GetMap().GetCreature(m_SummonSlot[i]);
|
||||
if (summon != null)
|
||||
summon.SetInPhase(id, true, apply);
|
||||
}
|
||||
}
|
||||
|
||||
RemoveNotOwnSingleTargetAuras(0, true);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public uint GetModelForForm(ShapeShiftForm form)
|
||||
{
|
||||
if (IsTypeId(TypeId.Player))
|
||||
|
||||
@@ -232,7 +232,7 @@ namespace Game.Garrisons
|
||||
GarrisonCreateResult garrisonCreateResult = new GarrisonCreateResult();
|
||||
garrisonCreateResult.GarrSiteLevelID = _siteLevel.Id;
|
||||
_owner.SendPacket(garrisonCreateResult);
|
||||
_owner.SendUpdatePhasing();
|
||||
PhasingHandler.OnConditionChange(_owner);
|
||||
SendRemoteInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -842,7 +842,7 @@ namespace Game
|
||||
uint MapId = location.GetMapId();
|
||||
|
||||
// search for zone associated closest graveyard
|
||||
uint zoneId = Global.MapMgr.GetZoneId(MapId, x, y, z);
|
||||
uint zoneId = Global.MapMgr.GetZoneId(conditionObject ? conditionObject.GetPhaseShift() : PhasingHandler.EmptyPhaseShift, MapId, x, y, z);
|
||||
if (zoneId == 0)
|
||||
{
|
||||
if (z > -500)
|
||||
@@ -899,11 +899,17 @@ namespace Game
|
||||
if (data.team != 0 && team != 0 && data.team != (uint)team)
|
||||
continue;
|
||||
|
||||
if (conditionObject != null && !Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.Graveyard, data.safeLocId, conditionSource))
|
||||
continue;
|
||||
if (conditionObject)
|
||||
{
|
||||
if (!Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.Graveyard, data.safeLocId, conditionSource))
|
||||
continue;
|
||||
|
||||
if (entry.MapID == mapEntry.ParentMapID && !conditionObject.GetPhaseShift().HasVisibleMapId(entry.MapID))
|
||||
continue;
|
||||
}
|
||||
|
||||
// find now nearest graveyard at other map
|
||||
if (MapId != entry.MapID)
|
||||
if (MapId != entry.MapID && entry.MapID != mapEntry.ParentMapID)
|
||||
{
|
||||
// if find graveyard at different map from where entrance placed (or no entrance data), use any first
|
||||
if (mapEntry == null
|
||||
@@ -3218,8 +3224,8 @@ namespace Game
|
||||
SQLResult result = DB.World.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, " +
|
||||
// 11 12 13 14 15 16 17 18 19 20 21
|
||||
"currentwaypoint, curhealth, curmana, MovementType, spawnMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.unit_flags2, creature.unit_flags3, " +
|
||||
// 22 23 24 25
|
||||
"creature.dynamicflags, creature.phaseid, creature.phasegroup, creature.ScriptName " +
|
||||
// 22 23 24 25 26 27
|
||||
"creature.dynamicflags, creature.phaseUseFlags, creature.phaseid, creature.phasegroup, creature.terrainSwapMap, creature.ScriptName " +
|
||||
"FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid");
|
||||
|
||||
if (result.IsEmpty())
|
||||
@@ -3240,6 +3246,8 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
PhaseShift phaseShift = new PhaseShift();
|
||||
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
@@ -3276,9 +3284,11 @@ namespace Game
|
||||
data.unit_flags2 = result.Read<uint>(20);
|
||||
data.unit_flags3 = result.Read<uint>(21);
|
||||
data.dynamicflags = result.Read<uint>(22);
|
||||
data.phaseId = result.Read<uint>(23);
|
||||
data.phaseGroup = result.Read<uint>(24);
|
||||
data.ScriptId = GetScriptId(result.Read<string>(25));
|
||||
data.phaseUseFlags = (PhaseUseFlagsValues)result.Read<byte>(23);
|
||||
data.phaseId = result.Read<uint>(24);
|
||||
data.phaseGroup = result.Read<uint>(25);
|
||||
data.terrainSwapMap = result.Read<int>(26);
|
||||
data.ScriptId = GetScriptId(result.Read<string>(27));
|
||||
if (data.ScriptId == 0)
|
||||
data.ScriptId = cInfo.ScriptID;
|
||||
|
||||
@@ -3349,6 +3359,19 @@ namespace Game
|
||||
data.orientation = Position.NormalizeOrientation(data.orientation);
|
||||
}
|
||||
|
||||
if (Convert.ToBoolean(data.phaseUseFlags & ~PhaseUseFlagsValues.All))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) has unknown `phaseUseFlags` set, removed unknown value.", guid, data.id);
|
||||
data.phaseUseFlags &= PhaseUseFlagsValues.All;
|
||||
}
|
||||
|
||||
if (data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.AlwaysVisible) && data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.Inverse))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE," +
|
||||
" removing PHASE_USE_FLAGS_INVERSE.", guid, data.id);
|
||||
data.phaseUseFlags &= ~PhaseUseFlagsValues.Inverse;
|
||||
}
|
||||
|
||||
if (data.phaseGroup != 0 && data.phaseId != 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.id);
|
||||
@@ -3373,11 +3396,27 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
if (data.terrainSwapMap != -1)
|
||||
{
|
||||
MapRecord terrainSwapEntry = CliDB.MapStorage.LookupByKey(data.terrainSwapMap);
|
||||
if (terrainSwapEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) with `terrainSwapMap` {2} does not exist, set to -1", guid, data.id, data.terrainSwapMap);
|
||||
data.terrainSwapMap = -1;
|
||||
}
|
||||
else if (terrainSwapEntry.ParentMapID != data.mapid)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) with `terrainSwapMap` {2} which cannot be used on spawn map, set to -1", guid, data.id, data.terrainSwapMap);
|
||||
data.terrainSwapMap = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (WorldConfig.GetBoolValue(WorldCfg.CalculateCreatureZoneAreaData))
|
||||
{
|
||||
uint zoneId = 0;
|
||||
uint areaId = 0;
|
||||
Global.MapMgr.GetZoneAndAreaId(out zoneId, out areaId, data.mapid, data.posX, data.posY, data.posZ);
|
||||
PhasingHandler.InitDbVisibleMapId(phaseShift, data.terrainSwapMap);
|
||||
Global.MapMgr.GetZoneAndAreaId(phaseShift, out zoneId, out areaId, data.mapid, data.posX, data.posY, data.posZ);
|
||||
|
||||
PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.UPD_CREATURE_ZONE_AREA_DATA);
|
||||
stmt.AddValue(0, zoneId);
|
||||
@@ -3883,8 +3922,8 @@ namespace Game
|
||||
SQLResult result = DB.World.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, " +
|
||||
// 7 8 9 10 11 12 13 14 15 16
|
||||
"rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, eventEntry, pool_entry, " +
|
||||
// 17 18 19
|
||||
"phaseid, phasegroup, ScriptName " +
|
||||
// 17 18 19 20 21
|
||||
"phaseUseFlags, phaseid, phasegroup, terrainSwapMap, ScriptName " +
|
||||
"FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid " +
|
||||
"LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid");
|
||||
|
||||
@@ -3908,6 +3947,8 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
PhaseShift phaseShift = new PhaseShift();
|
||||
|
||||
do
|
||||
{
|
||||
ulong guid = result.Read<ulong>(0);
|
||||
@@ -3986,8 +4027,22 @@ namespace Game
|
||||
|
||||
short gameEvent = result.Read<sbyte>(15);
|
||||
uint PoolId = result.Read<uint>(16);
|
||||
data.phaseId = result.Read<uint>(17);
|
||||
data.phaseGroup = result.Read<uint>(18);
|
||||
data.phaseUseFlags = (PhaseUseFlagsValues)result.Read<byte>(17);
|
||||
data.phaseId = result.Read<uint>(18);
|
||||
data.phaseGroup = result.Read<uint>(19);
|
||||
|
||||
if (Convert.ToBoolean(data.phaseUseFlags & ~PhaseUseFlagsValues.All))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) has unknown `phaseUseFlags` set, removed unknown value.", guid, data.id);
|
||||
data.phaseUseFlags &= PhaseUseFlagsValues.All;
|
||||
}
|
||||
|
||||
if (data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.AlwaysVisible) && data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.Inverse))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE," +
|
||||
" removing PHASE_USE_FLAGS_INVERSE.", guid, data.id);
|
||||
data.phaseUseFlags &= ~PhaseUseFlagsValues.Inverse;
|
||||
}
|
||||
|
||||
if (data.phaseGroup != 0 && data.phaseId != 0)
|
||||
{
|
||||
@@ -4013,7 +4068,23 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
data.ScriptId = GetScriptId(result.Read<string>(19));
|
||||
data.terrainSwapMap = result.Read<int>(20);
|
||||
if (data.terrainSwapMap != -1)
|
||||
{
|
||||
MapRecord terrainSwapEntry = CliDB.MapStorage.LookupByKey(data.terrainSwapMap);
|
||||
if (terrainSwapEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) with `terrainSwapMap` {2} does not exist, set to -1", guid, data.id, data.terrainSwapMap);
|
||||
data.terrainSwapMap = -1;
|
||||
}
|
||||
else if (terrainSwapEntry.ParentMapID != data.mapid)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) with `terrainSwapMap` {2} which cannot be used on spawn map, set to -1", guid, data.id, data.terrainSwapMap);
|
||||
data.terrainSwapMap = -1;
|
||||
}
|
||||
}
|
||||
|
||||
data.ScriptId = GetScriptId(result.Read<string>(21));
|
||||
if (data.ScriptId == 0)
|
||||
data.ScriptId = gInfo.ScriptId;
|
||||
|
||||
@@ -4057,7 +4128,8 @@ namespace Game
|
||||
{
|
||||
uint zoneId = 0;
|
||||
uint areaId = 0;
|
||||
Global.MapMgr.GetZoneAndAreaId(out zoneId, out areaId, data.mapid, data.posX, data.posY, data.posZ);
|
||||
PhasingHandler.InitDbVisibleMapId(phaseShift, data.terrainSwapMap);
|
||||
Global.MapMgr.GetZoneAndAreaId(phaseShift, out zoneId, out areaId, data.mapid, data.posX, data.posY, data.posZ);
|
||||
|
||||
PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.UPD_GAMEOBJECT_ZONE_AREA_DATA);
|
||||
stmt.AddValue(0, zoneId);
|
||||
@@ -7365,10 +7437,74 @@ namespace Game
|
||||
}
|
||||
|
||||
//Spells /Skills / Phases
|
||||
public void LoadTerrainSwapDefaults()
|
||||
public void LoadPhases()
|
||||
{
|
||||
_terrainMapDefaultStore.Clear();
|
||||
foreach (PhaseRecord phase in CliDB.PhaseStorage.Values)
|
||||
_phaseInfoById.Add(phase.Id, new PhaseInfoStruct(phase.Id));
|
||||
|
||||
foreach (MapRecord map in CliDB.MapStorage.Values)
|
||||
if (map.ParentMapID != -1)
|
||||
_terrainSwapInfoById.Add(map.Id, new TerrainSwapInfo(map.Id));
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Terrain World Map definitions...");
|
||||
LoadTerrainWorldMaps();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Terrain Swap Default definitions...");
|
||||
LoadTerrainSwapDefaults();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Phase Area definitions...");
|
||||
LoadAreaPhases();
|
||||
}
|
||||
public void UnloadPhaseConditions()
|
||||
{
|
||||
foreach (var pair in _phaseInfoByArea)
|
||||
pair.Value.Conditions.Clear();
|
||||
}
|
||||
void LoadTerrainWorldMaps()
|
||||
{
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
// 0 1
|
||||
SQLResult result = DB.World.Query("SELECT TerrainSwapMap, WorldMapArea FROM `terrain_worldmap`");
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 terrain world maps. DB table `terrain_worldmap` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
uint mapId = result.Read<uint>(0);
|
||||
uint worldMapArea = result.Read<uint>(1);
|
||||
|
||||
if (!CliDB.MapStorage.ContainsKey(mapId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "TerrainSwapMap {0} defined in `terrain_worldmap` does not exist, skipped.", mapId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CliDB.WorldMapAreaStorage.ContainsKey(worldMapArea))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "WorldMapArea {0} defined in `terrain_worldmap` does not exist, skipped.", worldMapArea);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_terrainSwapInfoById.ContainsKey(mapId))
|
||||
_terrainSwapInfoById.Add(mapId, new TerrainSwapInfo());
|
||||
|
||||
TerrainSwapInfo terrainSwapInfo = _terrainSwapInfoById[mapId];
|
||||
terrainSwapInfo.Id = mapId;
|
||||
terrainSwapInfo.UiWorldMapAreaIDSwaps.Add(worldMapArea);
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} terrain world maps in {1} ms.", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
void LoadTerrainSwapDefaults()
|
||||
{
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT MapId, TerrainSwapMap FROM `terrain_swap_defaults`");
|
||||
@@ -7395,87 +7531,20 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
_terrainMapDefaultStore.Add(mapId, terrainSwap);
|
||||
TerrainSwapInfo terrainSwapInfo = _terrainSwapInfoById[terrainSwap];
|
||||
terrainSwapInfo.Id = terrainSwap;
|
||||
_terrainSwapInfoByMap[mapId].Add(terrainSwapInfo);
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} terrain swap defaults in {1} ms.", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
public void LoadTerrainPhaseInfo()
|
||||
void LoadAreaPhases()
|
||||
{
|
||||
_terrainPhaseInfoStore.Clear();
|
||||
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT Id, TerrainSwapMap FROM `terrain_phase_info`");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 terrain phase infos. DB table `terrain_phase_info` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
uint phaseId = result.Read<uint>(0);
|
||||
if (!CliDB.PhaseStorage.ContainsKey(phaseId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Phase {0} defined in `terrain_phase_info` does not exist, skipped.", phaseId);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint terrainSwap = result.Read<uint>(1);
|
||||
|
||||
_terrainPhaseInfoStore.Add(phaseId, terrainSwap);
|
||||
|
||||
++count;
|
||||
}
|
||||
while (result.NextRow());
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} phase infos in {1} ms.", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
public void LoadTerrainWorldMaps()
|
||||
{
|
||||
_terrainWorldMapStore.Clear();
|
||||
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
// 0 1
|
||||
SQLResult result = DB.World.Query("SELECT TerrainSwapMap, WorldMapArea FROM `terrain_worldmap`");
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 terrain world maps. DB table `terrain_worldmap` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
uint mapId = result.Read<uint>(0);
|
||||
|
||||
if (!CliDB.MapStorage.ContainsKey(mapId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "TerrainSwapMap {0} defined in `terrain_worldmap` does not exist, skipped.", mapId);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint worldMapArea = result.Read<uint>(1);
|
||||
|
||||
_terrainWorldMapStore.Add(mapId, worldMapArea);
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} terrain world maps in {1} ms.", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
public void LoadAreaPhases()
|
||||
{
|
||||
_phases.Clear();
|
||||
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
// 0 1
|
||||
// 0 1
|
||||
SQLResult result = DB.World.Query("SELECT AreaId, PhaseId FROM `phase_area`");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
@@ -7483,19 +7552,60 @@ namespace Game
|
||||
return;
|
||||
}
|
||||
|
||||
Func<uint, PhaseInfoStruct> getOrCreatePhaseIfMissing = phaseId =>
|
||||
{
|
||||
PhaseInfoStruct phaseInfo = _phaseInfoById[phaseId];
|
||||
phaseInfo.Id = phaseId;
|
||||
return phaseInfo;
|
||||
};
|
||||
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
PhaseInfoStruct phase = new PhaseInfoStruct();
|
||||
uint area = result.Read<uint>(0);
|
||||
phase.Id = result.Read<uint>(1);
|
||||
uint phaseId = result.Read<uint>(1);
|
||||
|
||||
_phases.Add(area, phase);
|
||||
if (!CliDB.AreaTableStorage.ContainsKey(area))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Area {area} defined in `phase_area` does not exist, skipped.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CliDB.PhaseStorage.ContainsKey(phaseId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Phase {phaseId} defined in `phase_area` does not exist, skipped.");
|
||||
continue;
|
||||
}
|
||||
|
||||
PhaseInfoStruct phase = getOrCreatePhaseIfMissing(phaseId);
|
||||
phase.Areas.Add(area);
|
||||
_phaseInfoByArea[area].Add(new PhaseAreaInfo(phase));
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} phase areas in {1} ms.", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
foreach (var pair in _phaseInfoByArea)
|
||||
{
|
||||
uint parentAreaId = pair.Key;
|
||||
do
|
||||
{
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(parentAreaId);
|
||||
if (area == null)
|
||||
break;
|
||||
|
||||
parentAreaId = area.ParentAreaID;
|
||||
if (parentAreaId == 0)
|
||||
break;
|
||||
|
||||
var parentAreaPhases = _phaseInfoByArea.LookupByKey(parentAreaId);
|
||||
foreach (PhaseAreaInfo parentAreaPhase in parentAreaPhases)
|
||||
if (parentAreaPhase.PhaseInfo.Id == pair.Value.PhaseInfo.Id)
|
||||
parentAreaPhase.SubAreaExclusions.Add(pair.Key);
|
||||
|
||||
} while (true);
|
||||
}
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} phase areas in {Time.GetMSTimeDiffToNow(oldMSTime)} ms.");
|
||||
}
|
||||
public void LoadNPCSpellClickSpells()
|
||||
{
|
||||
@@ -7623,15 +7733,21 @@ namespace Game
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} skill max values in {1} ms", _skillTiers.Count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
public List<uint> GetPhaseTerrainSwaps(uint phaseid) { return _terrainPhaseInfoStore[phaseid]; }
|
||||
public List<uint> GetDefaultTerrainSwaps(uint mapid) { return _terrainMapDefaultStore[mapid]; }
|
||||
public List<uint> GetTerrainWorldMaps(uint terrainId) { return _terrainWorldMapStore[terrainId]; }
|
||||
public MultiMap<uint, uint> GetDefaultTerrainSwapStore() { return _terrainMapDefaultStore; }
|
||||
public List<PhaseInfoStruct> GetPhasesForArea(uint area) { return _phases[area]; }
|
||||
public MultiMap<uint, PhaseInfoStruct> GetAreaAndZonePhases() { return _phases; }
|
||||
public List<PhaseInfoStruct> GetPhasesForAreaOrZoneForLoading(uint areaOrZone)
|
||||
public PhaseInfoStruct GetPhaseInfo(uint phaseId)
|
||||
{
|
||||
return _phases.LookupByKey(areaOrZone);
|
||||
return _phaseInfoById.LookupByKey(phaseId);
|
||||
}
|
||||
public List<PhaseAreaInfo> GetPhasesForArea(uint areaId)
|
||||
{
|
||||
return _phaseInfoByArea.LookupByKey(areaId);
|
||||
}
|
||||
public TerrainSwapInfo GetTerrainSwapInfo(uint terrainSwapId)
|
||||
{
|
||||
return _terrainSwapInfoById.LookupByKey(terrainSwapId);
|
||||
}
|
||||
public List<TerrainSwapInfo> GetTerrainSwapsForMap(uint mapId)
|
||||
{
|
||||
return _terrainSwapInfoByMap.LookupByKey(mapId);
|
||||
}
|
||||
public List<SpellClickInfo> GetSpellClickInfoMapBounds(uint creature_id)
|
||||
{
|
||||
@@ -9481,10 +9597,10 @@ namespace Game
|
||||
List<ushort> _transportMaps = new List<ushort>();
|
||||
|
||||
//Spells /Skills / Phases
|
||||
MultiMap<uint, uint> _terrainPhaseInfoStore = new MultiMap<uint, uint>();
|
||||
MultiMap<uint, uint> _terrainMapDefaultStore = new MultiMap<uint, uint>();
|
||||
MultiMap<uint, uint> _terrainWorldMapStore = new MultiMap<uint, uint>();
|
||||
MultiMap<uint, PhaseInfoStruct> _phases = new MultiMap<uint, PhaseInfoStruct>();
|
||||
Dictionary<uint, PhaseInfoStruct> _phaseInfoById = new Dictionary<uint, PhaseInfoStruct>();
|
||||
Dictionary<uint, TerrainSwapInfo> _terrainSwapInfoById = new Dictionary<uint, TerrainSwapInfo>();
|
||||
MultiMap<uint, PhaseAreaInfo> _phaseInfoByArea = new MultiMap<uint, PhaseAreaInfo>();
|
||||
MultiMap<uint, TerrainSwapInfo> _terrainSwapInfoByMap = new MultiMap<uint, TerrainSwapInfo>();
|
||||
MultiMap<uint, SpellClickInfo> _spellClickInfoStorage = new MultiMap<uint, SpellClickInfo>();
|
||||
Dictionary<uint, int> _fishingBaseForAreaStorage = new Dictionary<uint, int>();
|
||||
Dictionary<uint, SkillTiersEntry> _skillTiers = new Dictionary<uint, SkillTiersEntry>();
|
||||
@@ -10296,9 +10412,46 @@ namespace Game
|
||||
public uint[] Value = new uint[SkillConst.MaxSkillStep];
|
||||
}
|
||||
|
||||
public class TerrainSwapInfo
|
||||
{
|
||||
public TerrainSwapInfo() { }
|
||||
public TerrainSwapInfo(uint id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public uint Id;
|
||||
public List<uint> UiWorldMapAreaIDSwaps = new List<uint>();
|
||||
}
|
||||
|
||||
public class PhaseInfoStruct
|
||||
{
|
||||
public PhaseInfoStruct(uint id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public bool IsAllowedInArea(uint areaId)
|
||||
{
|
||||
return Areas.Any(areaToCheck =>
|
||||
{
|
||||
return Global.DB2Mgr.IsInArea(areaId, areaToCheck);
|
||||
});
|
||||
}
|
||||
|
||||
public uint Id;
|
||||
public List<uint> Areas = new List<uint>();
|
||||
}
|
||||
|
||||
public class PhaseAreaInfo
|
||||
{
|
||||
public PhaseAreaInfo(PhaseInfoStruct phaseInfo)
|
||||
{
|
||||
PhaseInfo = phaseInfo;
|
||||
}
|
||||
|
||||
public PhaseInfoStruct PhaseInfo;
|
||||
public List<uint> SubAreaExclusions = new List<uint>();
|
||||
public List<Condition> Conditions = new List<Condition>();
|
||||
}
|
||||
|
||||
|
||||
@@ -713,17 +713,6 @@ namespace Game
|
||||
_player.ApplyModFlag(PlayerFields.Flags, PlayerFlags.TaxiBenchmark, packet.Enable);
|
||||
}
|
||||
|
||||
public void SendSetPhaseShift(List<uint> phaseIds, List<uint> terrainswaps, List<uint> worldMapAreaSwaps)
|
||||
{
|
||||
PhaseShift phaseShift = new PhaseShift();
|
||||
phaseShift.ClientGUID = GetPlayer().GetGUID();
|
||||
phaseShift.PersonalGUID = GetPlayer().GetGUID();
|
||||
phaseShift.PhaseShifts = phaseIds;
|
||||
phaseShift.VisibleMapIDs = terrainswaps;
|
||||
phaseShift.UiWorldMapAreaIDSwaps = worldMapAreaSwaps;
|
||||
SendPacket(phaseShift);
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.GuildSetFocusedAchievement)]
|
||||
void HandleGuildSetFocusedAchievement(GuildSetFocusedAchievement setFocusedAchievement)
|
||||
{
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Game
|
||||
if (plrMover && movementInfo.HasMovementFlag(MovementFlag.Swimming) != plrMover.IsInWater())
|
||||
{
|
||||
// now client not include swimming flag in case jumping under water
|
||||
plrMover.SetInWater(!plrMover.IsInWater() || plrMover.GetMap().IsUnderWater(movementInfo.Pos.posX, movementInfo.Pos.posY, movementInfo.Pos.posZ));
|
||||
plrMover.SetInWater(!plrMover.IsInWater() || plrMover.GetMap().IsUnderWater(plrMover.GetPhaseShift(), movementInfo.Pos.posX, movementInfo.Pos.posY, movementInfo.Pos.posZ));
|
||||
}
|
||||
|
||||
uint mstime = Time.GetMSTime();
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace Game
|
||||
mapID = (uint)corpseMapEntry.CorpseMapID;
|
||||
x = corpseMapEntry.Corpse.X;
|
||||
y = corpseMapEntry.Corpse.Y;
|
||||
z = entranceMap.GetHeight(player.GetPhases(), x, y, MapConst.MaxHeight);
|
||||
z = entranceMap.GetHeight(player.GetPhaseShift(), x, y, MapConst.MaxHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace Game.Maps
|
||||
if (!File.Exists(filename))
|
||||
return true;
|
||||
|
||||
_fileExists = true;
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
mapFileHeader header = reader.ReadStruct<mapFileHeader>();
|
||||
@@ -72,6 +73,7 @@ namespace Game.Maps
|
||||
_liquidFlags = null;
|
||||
_liquidMap = null;
|
||||
_gridGetHeight = getHeightFromFlat;
|
||||
_fileExists = false;
|
||||
}
|
||||
|
||||
void LoadAreaData(BinaryReader reader, uint offset)
|
||||
@@ -435,8 +437,8 @@ namespace Game.Maps
|
||||
};
|
||||
|
||||
Cell cell = new Cell(x, y);
|
||||
float gx = x - (cell.GetGridX() - MapConst.CenterGridId + 1) *MapConst.SizeofGrids;
|
||||
float gy = y - (cell.GetGridY() - MapConst.CenterGridId + 1) *MapConst.SizeofGrids;
|
||||
float gx = x - (cell.GetGridX() - MapConst.CenterGridId + 1) * MapConst.SizeofGrids;
|
||||
float gy = y - (cell.GetGridY() - MapConst.CenterGridId + 1) * MapConst.SizeofGrids;
|
||||
|
||||
uint quarterIndex = 0;
|
||||
if (cell.GetCellY() < MapConst.MaxCells / 2)
|
||||
@@ -595,6 +597,8 @@ namespace Game.Maps
|
||||
|
||||
public float getHeight(float x, float y) { return _gridGetHeight(x, y); }
|
||||
|
||||
public bool fileExists() { return _fileExists; }
|
||||
|
||||
#region Fields
|
||||
delegate float GetHeight(float x, float y);
|
||||
|
||||
@@ -627,6 +631,7 @@ namespace Game.Maps
|
||||
byte _liquidOffY;
|
||||
byte _liquidWidth;
|
||||
byte _liquidHeight;
|
||||
bool _fileExists;
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -727,7 +727,7 @@ namespace Game.Maps
|
||||
{
|
||||
var players = instance.GetPlayers();
|
||||
foreach (var player in players)
|
||||
player.SendUpdatePhasing();
|
||||
PhasingHandler.SendToPlayer(player);
|
||||
}
|
||||
|
||||
public void UpdateCombatResurrection(uint diff)
|
||||
|
||||
@@ -34,19 +34,27 @@ namespace Game
|
||||
const string MAP_FILE_NAME_FORMAT = "{0}/mmaps/{1:D4}.mmap";
|
||||
const string TILE_FILE_NAME_FORMAT = "{0}/mmaps/{1:D4}{2:D2}{3:D2}.mmtile";
|
||||
|
||||
public void Initialize(MultiMap<uint, uint> mapData)
|
||||
{
|
||||
childMapData = mapData;
|
||||
|
||||
foreach (var pair in mapData)
|
||||
parentMapData[pair.Value] = pair.Key;
|
||||
}
|
||||
|
||||
MMapData GetMMapData(uint mapId)
|
||||
{
|
||||
return loadedMMaps.LookupByKey(mapId);
|
||||
}
|
||||
|
||||
bool loadMapData(uint mapId)
|
||||
bool loadMapData(string basePath, uint mapId)
|
||||
{
|
||||
// we already have this map loaded?
|
||||
if (loadedMMaps.ContainsKey(mapId) && loadedMMaps[mapId] != null)
|
||||
return true;
|
||||
|
||||
// load and init dtNavMesh - read parameters from file
|
||||
string filename = string.Format(MAP_FILE_NAME_FORMAT, Global.WorldMgr.GetDataPath(), mapId);
|
||||
string filename = string.Format(MAP_FILE_NAME_FORMAT, basePath, mapId);
|
||||
if (!File.Exists(filename))
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "Could not open mmap file {0}", filename);
|
||||
@@ -80,15 +88,30 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
uint packTileID(int x, int y)
|
||||
uint packTileID(uint x, uint y)
|
||||
{
|
||||
return (uint)(x << 16 | y);
|
||||
return (x << 16 | y);
|
||||
}
|
||||
|
||||
public bool loadMap(uint mapId, int x, int y)
|
||||
public bool loadMap(string basePath, uint mapId, uint x, uint y)
|
||||
{
|
||||
// make sure the mmap is loaded and ready to load tiles
|
||||
if (!loadMapData(mapId))
|
||||
if (!loadMapImpl(basePath, mapId, x, y))
|
||||
return false;
|
||||
|
||||
bool success = true;
|
||||
var childMaps = childMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
if (!loadMapImpl(basePath, childMapId, x, y))
|
||||
success = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool loadMapImpl(string basePath, uint mapId, uint x, uint y)
|
||||
{
|
||||
// make sure the mmap is loaded and ready to load tiles
|
||||
if (!loadMapData(basePath, mapId))
|
||||
return false;
|
||||
|
||||
// get this mmap data
|
||||
@@ -101,14 +124,20 @@ namespace Game
|
||||
return false;
|
||||
|
||||
// load this tile . mmaps/MMMXXYY.mmtile
|
||||
string filename = string.Format(TILE_FILE_NAME_FORMAT, Global.WorldMgr.GetDataPath(), mapId, x, y);
|
||||
if (!File.Exists(filename))
|
||||
string fileName = string.Format(TILE_FILE_NAME_FORMAT, basePath, mapId, x, y);
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "MMAP:loadMap: Could not open mmtile file '{0}'", filename);
|
||||
if (parentMapData.ContainsKey(mapId))
|
||||
fileName = string.Format(TILE_FILE_NAME_FORMAT, basePath, parentMapData[mapId], x, y);
|
||||
}
|
||||
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "MMAP:loadMap: Could not open mmtile file '{0}'", fileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
MmapTileHeader fileHeader = reader.ReadStruct<MmapTileHeader>();
|
||||
Array.Reverse(fileHeader.mmapMagic);
|
||||
@@ -144,7 +173,52 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
public bool loadMapInstance(string basePath, uint mapId, uint instanceId)
|
||||
{
|
||||
if (!loadMapInstanceImpl(basePath, mapId, instanceId))
|
||||
return false;
|
||||
|
||||
bool success = true;
|
||||
var childMaps = childMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
if (!loadMapInstanceImpl(basePath, childMapId, instanceId))
|
||||
success = false;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool loadMapInstanceImpl(string basePath, uint mapId, uint instanceId)
|
||||
{
|
||||
if (!loadMapData(basePath, mapId))
|
||||
return false;
|
||||
|
||||
MMapData mmap = loadedMMaps[mapId];
|
||||
if (mmap.navMeshQueries.ContainsKey(instanceId))
|
||||
return true;
|
||||
|
||||
// allocate mesh query
|
||||
Detour.dtNavMeshQuery query = new Detour.dtNavMeshQuery();
|
||||
if (Detour.dtStatusFailed(query.init(mmap.navMesh, 1024)))
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "MMAP.GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {0:D4} instanceId {1}", mapId, instanceId);
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.outDebug(LogFilter.Maps, "MMAP.GetNavMeshQuery: created dtNavMeshQuery for mapId {0:D4} instanceId {1}", mapId, instanceId);
|
||||
mmap.navMeshQueries.Add(instanceId, query);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool unloadMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
var childMaps = childMapData.LookupByKey(mapId);
|
||||
foreach (uint childMapId in childMaps)
|
||||
unloadMapImpl(childMapId, x, y);
|
||||
|
||||
return unloadMapImpl(mapId, x, y);
|
||||
}
|
||||
|
||||
bool unloadMapImpl(uint mapId, uint x, uint y)
|
||||
{
|
||||
// check if we have this map loaded
|
||||
MMapData mmap = GetMMapData(mapId);
|
||||
@@ -156,7 +230,7 @@ namespace Game
|
||||
}
|
||||
|
||||
// check if we have this tile loaded
|
||||
uint packedGridPos = packTileID((int)x, (int)y);
|
||||
uint packedGridPos = packTileID(x, y);
|
||||
if (!mmap.loadedTileRefs.ContainsKey(packedGridPos))
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
@@ -164,7 +238,7 @@ namespace Game
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong tileRef = mmap.loadedTileRefs.LookupByKey(packedGridPos);
|
||||
ulong tileRef = mmap.loadedTileRefs[packedGridPos];
|
||||
|
||||
// unload, and mark as non loaded
|
||||
Detour.dtRawTileData data;
|
||||
@@ -256,20 +330,6 @@ namespace Game
|
||||
if (mmap == null)
|
||||
return null;
|
||||
|
||||
if (!mmap.navMeshQueries.ContainsKey(instanceId))
|
||||
{
|
||||
// allocate mesh query
|
||||
Detour.dtNavMeshQuery query = new Detour.dtNavMeshQuery();
|
||||
if (Detour.dtStatusFailed(query.init(mmap.navMesh, 1024)))
|
||||
{
|
||||
Log.outError(LogFilter.Maps, "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId {0} instanceId {1}", mapId, instanceId);
|
||||
return null;
|
||||
}
|
||||
|
||||
Log.outInfo(LogFilter.Maps, "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId {0} instanceId {1}", mapId, instanceId);
|
||||
mmap.navMeshQueries.Add(instanceId, query);
|
||||
}
|
||||
|
||||
return mmap.navMeshQueries[instanceId];
|
||||
}
|
||||
|
||||
@@ -278,6 +338,9 @@ namespace Game
|
||||
|
||||
Dictionary<uint, MMapData> loadedMMaps = new Dictionary<uint, MMapData>();
|
||||
uint loadedTiles;
|
||||
|
||||
MultiMap<uint, uint> childMapData = new MultiMap<uint, uint>();
|
||||
Dictionary<uint, uint> parentMapData = new Dictionary<uint, uint>();
|
||||
}
|
||||
|
||||
public class MMapData
|
||||
|
||||
+199
-108
@@ -48,7 +48,16 @@ namespace Game.Maps
|
||||
i_gridExpiry = expiry;
|
||||
_defaultLight = Global.DB2Mgr.GetDefaultMapLight(id);
|
||||
|
||||
m_parentMap = parent ?? this;
|
||||
if (parent)
|
||||
{
|
||||
m_parentMap = parent;
|
||||
m_childTerrainMaps = m_parentMap.m_childTerrainMaps;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_parentMap = this;
|
||||
m_childTerrainMaps = new List<Map>();
|
||||
}
|
||||
|
||||
for (uint x = 0; x < MapConst.MaxGrids; ++x)
|
||||
{
|
||||
@@ -69,6 +78,8 @@ namespace Game.Maps
|
||||
|
||||
GetGuidSequenceGenerator(HighGuid.Transport).Set(Global.ObjectMgr.GetGenerator(HighGuid.Transport).GetNextAfterMaxUsed());
|
||||
|
||||
Global.MMapMgr.loadMapInstance(Global.WorldMgr.GetDataPath(), GetId(), i_InstanceId);
|
||||
|
||||
Global.ScriptMgr.OnCreateMap(this);
|
||||
}
|
||||
|
||||
@@ -112,7 +123,10 @@ namespace Game.Maps
|
||||
|
||||
void LoadMMap(uint gx, uint gy)
|
||||
{
|
||||
if (Global.MMapMgr.loadMap(GetId(), (int)gx, (int)gy))
|
||||
if (!Global.DisableMgr.IsPathfindingEnabled(GetId()))
|
||||
return;
|
||||
|
||||
if (Global.MMapMgr.loadMap(Global.WorldMgr.GetDataPath(), GetId(), gx, gy))
|
||||
Log.outInfo(LogFilter.Maps, "MMAP loaded name:{0}, id:{1}, x:{2}, y:{3} (mmap rep.: x:{4}, y:{5})", GetMapName(), GetId(), gx, gy, gx, gy);
|
||||
else
|
||||
Log.outInfo(LogFilter.Maps, "Could not load MMAP name:{0}, id:{1}, x:{2}, y:{3} (mmap rep.: x:{4}, y:{5})", GetMapName(), GetId(), gx, gy, gx, gy);
|
||||
@@ -138,39 +152,62 @@ namespace Game.Maps
|
||||
|
||||
void LoadMap(uint gx, uint gy, bool reload = false)
|
||||
{
|
||||
if (i_InstanceId != 0)
|
||||
LoadMapImpl(this, gx, gy, reload);
|
||||
foreach (Map childBaseMap in m_childTerrainMaps)
|
||||
LoadMapImpl(childBaseMap, gx, gy, reload);
|
||||
}
|
||||
|
||||
void LoadMapImpl(Map map, uint gx, uint gy, bool reload)
|
||||
{
|
||||
if (map.i_InstanceId != 0)
|
||||
{
|
||||
if (GridMaps[gx][gy] != null)
|
||||
if (map.GridMaps[gx][gy] != null)
|
||||
return;
|
||||
|
||||
// load grid map for base map
|
||||
if (m_parentMap.GridMaps[gx][gy] == null)
|
||||
m_parentMap.EnsureGridCreated(new GridCoord(63 - gx, 63 - gy));
|
||||
if (map.m_parentMap.GridMaps[gx][gy] == null)
|
||||
map.m_parentMap.EnsureGridCreated(new GridCoord(63 - gx, 63 - gy));
|
||||
|
||||
((MapInstanced)m_parentMap).AddGridMapReference(new GridCoord(gx, gy));
|
||||
GridMaps[gx][gy] = m_parentMap.GridMaps[gx][gy];
|
||||
map.m_parentMap.ToMapInstanced().AddGridMapReference(new GridCoord(gx, gy));
|
||||
map.GridMaps[gx][gy] = map.m_parentMap.GridMaps[gx][gy];
|
||||
return;
|
||||
}
|
||||
|
||||
if (GridMaps[gx][gy] != null && !reload)
|
||||
if (map.GridMaps[gx][gy] != null && !reload)
|
||||
return;
|
||||
|
||||
if (GridMaps[gx][gy] != null)
|
||||
if (map.GridMaps[gx][gy] != null)
|
||||
{
|
||||
Log.outInfo(LogFilter.Maps, "Unloading previously loaded map {0} before reloading.", GetId());
|
||||
Global.ScriptMgr.OnUnloadGridMap(this, GridMaps[gx][gy], gx, gy);
|
||||
Log.outInfo(LogFilter.Maps, "Unloading previously loaded map {0} before reloading.", map.GetId());
|
||||
Global.ScriptMgr.OnUnloadGridMap(map, map.GridMaps[gx][gy], gx, gy);
|
||||
|
||||
GridMaps[gx][gy] = null;
|
||||
map.GridMaps[gx][gy] = null;
|
||||
}
|
||||
// map file name
|
||||
string filename = string.Format("{0}/maps/{1:D4}_{2:D2}_{3:D2}.map", Global.WorldMgr.GetDataPath(), GetId(), gx, gy);
|
||||
string filename = string.Format("{0}/maps/{1:D4}_{2:D2}_{3:D2}.map", Global.WorldMgr.GetDataPath(), map.GetId(), gx, gy);
|
||||
Log.outInfo(LogFilter.Maps, "Loading map {0}", filename);
|
||||
// loading data
|
||||
GridMaps[gx][gy] = new GridMap();
|
||||
if (!GridMaps[gx][gy].loadData(filename))
|
||||
map.GridMaps[gx][gy] = new GridMap();
|
||||
if (!map.GridMaps[gx][gy].loadData(filename))
|
||||
Log.outError(LogFilter.Maps, "Error loading map file: {0}", filename);
|
||||
|
||||
Global.ScriptMgr.OnLoadGridMap(this, GridMaps[gx][gy], gx, gy);
|
||||
Global.ScriptMgr.OnLoadGridMap(map, map.GridMaps[gx][gy], gx, gy);
|
||||
}
|
||||
|
||||
void UnloadMap(Map map, uint gx, uint gy)
|
||||
{
|
||||
if (map.i_InstanceId == 0)
|
||||
{
|
||||
if (map.GridMaps[gx][gy] != null)
|
||||
{
|
||||
map.GridMaps[gx][gy].unloadData();
|
||||
map.GridMaps[gx][gy] = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
map.m_parentMap.ToMapInstanced().RemoveGridMapReference(new GridCoord(gx, gy));
|
||||
|
||||
map.GridMaps[gx][gy] = null;
|
||||
}
|
||||
|
||||
void LoadMapAndVMap(uint gx, uint gy)
|
||||
@@ -415,7 +452,7 @@ namespace Game.Maps
|
||||
player.m_clientGUIDs.Clear();
|
||||
|
||||
player.UpdateObjectVisibility(false);
|
||||
player.SendUpdatePhasing();
|
||||
PhasingHandler.SendToPlayer(player);
|
||||
|
||||
if (player.IsAlive())
|
||||
ConvertCorpseToBones(player.GetGUID());
|
||||
@@ -466,8 +503,6 @@ namespace Game.Maps
|
||||
if (obj.isActiveObject())
|
||||
AddToActive(obj);
|
||||
|
||||
obj.RebuildTerrainSwaps();
|
||||
|
||||
//something, such as vehicle, needs to be update immediately
|
||||
//also, trigger needs to cast spell, if not update, cannot see visual
|
||||
obj.UpdateObjectVisibilityOnCreate();
|
||||
@@ -499,6 +534,7 @@ namespace Game.Maps
|
||||
{
|
||||
var data = new UpdateData(GetId());
|
||||
obj.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
player.m_visibleTransports.Add(obj.GetGUID());
|
||||
UpdateObject packet;
|
||||
data.BuildPacket(out packet);
|
||||
player.SendPacket(packet);
|
||||
@@ -804,9 +840,14 @@ namespace Game.Maps
|
||||
UpdateObject packet;
|
||||
data.BuildPacket(out packet);
|
||||
|
||||
foreach (var pl in players)
|
||||
if (pl.GetTransport() != obj)
|
||||
pl.SendPacket(packet);
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player.GetTransport() != obj)
|
||||
{
|
||||
player.SendPacket(packet);
|
||||
player.m_visibleTransports.Remove(obj.GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_transports.Contains(obj))
|
||||
@@ -1541,20 +1582,19 @@ namespace Game.Maps
|
||||
uint gx = (MapConst.MaxGrids - 1) - x;
|
||||
uint gy = (MapConst.MaxGrids - 1) - y;
|
||||
|
||||
// delete grid map, but don't delete if it is from parent map (and thus only reference)
|
||||
//+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps
|
||||
{
|
||||
foreach (Map childBaseMap in m_childTerrainMaps)
|
||||
UnloadMap(childBaseMap, gx, gy);
|
||||
|
||||
UnloadMap(this, gx, gy);
|
||||
|
||||
if (i_InstanceId == 0)
|
||||
{
|
||||
if (GridMaps[gx][gy] != null)
|
||||
{
|
||||
GridMaps[gx][gy].unloadData();
|
||||
}
|
||||
Global.VMapMgr.unloadMap(GetId(), gx, gy);
|
||||
Global.MMapMgr.unloadMap(GetId(), gx, gy);
|
||||
}
|
||||
else
|
||||
((MapInstanced)m_parentMap).RemoveGridMapReference(new GridCoord(gx, gy));
|
||||
|
||||
GridMaps[gx][gy] = null;
|
||||
}
|
||||
Log.outDebug(LogFilter.Maps, "Unloading grid[{0}, {1}] for map {2} finished", x, y, GetId());
|
||||
return true;
|
||||
@@ -1624,49 +1664,79 @@ namespace Game.Maps
|
||||
if (!m_scriptSchedule.Empty())
|
||||
Global.MapMgr.DecreaseScheduledScriptCount((uint)m_scriptSchedule.Count);
|
||||
|
||||
if (m_parentMap == this)
|
||||
m_childTerrainMaps = null;
|
||||
|
||||
Global.MMapMgr.unloadMapInstance(GetId(), i_InstanceId);
|
||||
}
|
||||
|
||||
private GridMap GetGridMap(float x, float y)
|
||||
{
|
||||
// half opt method
|
||||
var gx = (uint)(32 - x / MapConst.SizeofGrids); //grid x
|
||||
var gy = (uint)(32 - y / MapConst.SizeofGrids); //grid y
|
||||
var gx = (uint)(MapConst.CenterGridId - x / MapConst.SizeofGrids); //grid x
|
||||
var gy = (uint)(MapConst.CenterGridId - y / MapConst.SizeofGrids); //grid y
|
||||
|
||||
// ensure GridMap is loaded
|
||||
EnsureGridCreated(new GridCoord(63 - gx, 63 - gy));
|
||||
EnsureGridCreated(new GridCoord((MapConst.MaxGrids - 1) - gx, (MapConst.MaxGrids - 1) - gy));
|
||||
|
||||
return GridMaps[gx][gy];
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(List<uint> phases, float x, float y, float z)
|
||||
GridMap GetGridMap(uint mapId, float x, float y)
|
||||
{
|
||||
float ground = 0f;
|
||||
return GetWaterOrGroundLevel(phases, x, y, z, ref ground);
|
||||
if (GetId() == mapId)
|
||||
return GetGridMap(x, y);
|
||||
|
||||
// half opt method
|
||||
uint gx = (uint)(MapConst.CenterGridId - x / MapConst.SizeofGrids); //grid x
|
||||
uint gy = (uint)(MapConst.CenterGridId - y / MapConst.SizeofGrids); //grid y
|
||||
|
||||
// ensure GridMap is loaded
|
||||
EnsureGridCreated(new GridCoord((MapConst.MaxGrids - 1) - gx, (MapConst.MaxGrids - 1) - gy));
|
||||
|
||||
GridMap grid = GridMaps[gx][gy];
|
||||
var childMap = m_childTerrainMaps.Find(childTerrainMap => childTerrainMap.GetId() == mapId);
|
||||
if (childMap != null && childMap.GridMaps[gx][gy].fileExists())
|
||||
grid = childMap.GridMaps[gx][gy];
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(List<uint> phases, float x, float y, float z, ref float ground, bool swim = false)
|
||||
public bool HasGridMap(uint mapId, uint gx, uint gy)
|
||||
{
|
||||
var childMap = m_childTerrainMaps.Find(childTerrainMap => childTerrainMap.GetId() == mapId);
|
||||
return childMap != null && childMap.GridMaps[gx][gy] != null && childMap.GridMaps[gx][gy].fileExists();
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
float ground = 0f;
|
||||
return GetWaterOrGroundLevel(phaseShift, x, y, z, ref ground);
|
||||
}
|
||||
|
||||
public float GetWaterOrGroundLevel(PhaseShift phaseShift, float x, float y, float z, ref float ground, bool swim = false)
|
||||
{
|
||||
if (GetGridMap(x, y) != null)
|
||||
{
|
||||
// we need ground level (including grid height version) for proper return water level in point
|
||||
float ground_z = GetHeight(phases, x, y, z, true, 50.0f);
|
||||
float ground_z = GetHeight(phaseShift, x, y, z, true, 50.0f);
|
||||
ground = ground_z;
|
||||
|
||||
LiquidData liquid_status;
|
||||
|
||||
ZLiquidStatus res = getLiquidStatus(x, y, ground_z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
ZLiquidStatus res = getLiquidStatus(phaseShift, x, y, ground_z, MapConst.MapAllLiquidTypes, out liquid_status);
|
||||
return res != ZLiquidStatus.NoWater ? liquid_status.level : ground_z;
|
||||
}
|
||||
|
||||
return MapConst.VMAPInvalidHeightValue;
|
||||
}
|
||||
|
||||
public float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
public float GetStaticHeight(PhaseShift phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
{
|
||||
// find raw .map surface under Z coordinates
|
||||
float mapHeight = MapConst.VMAPInvalidHeightValue;
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y);
|
||||
GridMap gmap = GetGridMap(terrainMapId, x, y);
|
||||
if (gmap != null)
|
||||
{
|
||||
float gridHeight = gmap.getHeight(x, y);
|
||||
@@ -1679,7 +1749,7 @@ namespace Game.Maps
|
||||
if (checkVMap)
|
||||
{
|
||||
if (Global.VMapMgr.isHeightCalcEnabled())
|
||||
vmapHeight = Global.VMapMgr.getHeight(GetId(), x, y, z + 2.0f, maxSearchDist);
|
||||
vmapHeight = Global.VMapMgr.getHeight(terrainMapId, x, y, z + 2.0f, maxSearchDist);
|
||||
// look from a bit higher pos to find the floor
|
||||
}
|
||||
|
||||
@@ -1736,13 +1806,13 @@ namespace Game.Maps
|
||||
return outdoor;
|
||||
}
|
||||
|
||||
public bool IsOutdoors(float x, float y, float z)
|
||||
public bool IsOutdoors(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
uint mogpFlags;
|
||||
int adtId, rootId, groupId;
|
||||
|
||||
// no wmo found? . outside by default
|
||||
if (!GetAreaInfo(x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
if (!GetAreaInfo(phaseShift, x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
return true;
|
||||
|
||||
AreaTableRecord atEntry = null;
|
||||
@@ -1756,7 +1826,7 @@ namespace Game.Maps
|
||||
return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
|
||||
}
|
||||
|
||||
private bool GetAreaInfo(float x, float y, float z, out uint flags, out int adtId, out int rootId, out int groupId)
|
||||
private bool GetAreaInfo(PhaseShift phaseShift, float x, float y, float z, out uint flags, out int adtId, out int rootId, out int groupId)
|
||||
{
|
||||
flags = 0;
|
||||
adtId = 0;
|
||||
@@ -1764,10 +1834,11 @@ namespace Game.Maps
|
||||
groupId = 0;
|
||||
|
||||
float vmap_z = z;
|
||||
if (Global.VMapMgr.getAreaInfo(GetId(), x, y, ref vmap_z, out flags, out adtId, out rootId, out groupId))
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y);
|
||||
if (Global.VMapMgr.getAreaInfo(terrainMapId, x, y, ref vmap_z, out flags, out adtId, out rootId, out groupId))
|
||||
{
|
||||
// check if there's terrain between player height and object height
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(terrainMapId, x, y);
|
||||
if (gmap != null)
|
||||
{
|
||||
float _mapheight = gmap.getHeight(x, y);
|
||||
@@ -1781,13 +1852,13 @@ namespace Game.Maps
|
||||
return false;
|
||||
}
|
||||
|
||||
public uint GetAreaId(float x, float y, float z)
|
||||
public uint GetAreaId(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
bool throwaway;
|
||||
return GetAreaId(x, y, z, out throwaway);
|
||||
return GetAreaId(phaseShift, x, y, z, out throwaway);
|
||||
}
|
||||
|
||||
public uint GetAreaId(float x, float y, float z, out bool isOutdoors)
|
||||
public uint GetAreaId(PhaseShift phaseShift, float x, float y, float z, out bool isOutdoors)
|
||||
{
|
||||
uint mogpFlags;
|
||||
int adtId, rootId, groupId;
|
||||
@@ -1796,7 +1867,7 @@ namespace Game.Maps
|
||||
bool haveAreaInfo = false;
|
||||
uint areaId = 0;
|
||||
|
||||
if (GetAreaInfo(x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
if (GetAreaInfo(phaseShift, x, y, z, out mogpFlags, out adtId, out rootId, out groupId))
|
||||
{
|
||||
haveAreaInfo = true;
|
||||
wmoEntry = Global.DB2Mgr.GetWMOAreaTable(rootId, adtId, groupId);
|
||||
@@ -1809,7 +1880,7 @@ namespace Game.Maps
|
||||
|
||||
if (areaId == 0)
|
||||
{
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(PhasingHandler.GetTerrainMapId(phaseShift, this, x, y), x, y);
|
||||
if (gmap != null)
|
||||
areaId = gmap.getArea(x, y);
|
||||
|
||||
@@ -1826,9 +1897,9 @@ namespace Game.Maps
|
||||
return areaId;
|
||||
}
|
||||
|
||||
public uint GetZoneId(float x, float y, float z)
|
||||
public uint GetZoneId(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
uint areaId = GetAreaId(x, y, z);
|
||||
uint areaId = GetAreaId(phaseShift, x, y, z);
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(areaId);
|
||||
if (area != null)
|
||||
if (area.ParentAreaID != 0)
|
||||
@@ -1837,38 +1908,38 @@ namespace Game.Maps
|
||||
return areaId;
|
||||
}
|
||||
|
||||
public void GetZoneAndAreaId(out uint zoneid, out uint areaid, float x, float y, float z)
|
||||
public void GetZoneAndAreaId(PhaseShift phaseShift, out uint zoneid, out uint areaid, float x, float y, float z)
|
||||
{
|
||||
areaid = zoneid = GetAreaId(x, y, z);
|
||||
areaid = zoneid = GetAreaId(phaseShift, x, y, z);
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(areaid);
|
||||
if (area != null)
|
||||
if (area.ParentAreaID != 0)
|
||||
zoneid = area.ParentAreaID;
|
||||
}
|
||||
|
||||
private byte GetTerrainType(float x, float y)
|
||||
private byte GetTerrainType(PhaseShift phaseShift, float x, float y)
|
||||
{
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(PhasingHandler.GetTerrainMapId(phaseShift, this, x, y), x, y);
|
||||
if (gmap != null)
|
||||
return gmap.getTerrainType(x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ZLiquidStatus getLiquidStatus(float x, float y, float z, byte ReqLiquidType)
|
||||
public ZLiquidStatus getLiquidStatus(PhaseShift phaseShift, float x, float y, float z, byte ReqLiquidType)
|
||||
{
|
||||
LiquidData throwaway;
|
||||
return getLiquidStatus(x, y, z, ReqLiquidType, out throwaway);
|
||||
return getLiquidStatus(phaseShift, x, y, z, ReqLiquidType, out throwaway);
|
||||
}
|
||||
|
||||
public ZLiquidStatus getLiquidStatus(float x, float y, float z, byte ReqLiquidType, out LiquidData data)
|
||||
public ZLiquidStatus getLiquidStatus(PhaseShift phaseShift, float x, float y, float z, byte ReqLiquidType, out LiquidData data)
|
||||
{
|
||||
data = new LiquidData();
|
||||
var result = ZLiquidStatus.NoWater;
|
||||
float liquid_level = MapConst.InvalidHeight;
|
||||
float ground_level = MapConst.InvalidHeight;
|
||||
uint liquid_type = 0;
|
||||
|
||||
if (Global.VMapMgr.GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, ref liquid_level, ref ground_level, ref liquid_type))
|
||||
uint terrainMapId = PhasingHandler.GetTerrainMapId(phaseShift, this, x, y);
|
||||
if (Global.VMapMgr.GetLiquidLevel(terrainMapId, x, y, z, ReqLiquidType, ref liquid_level, ref ground_level, ref liquid_type))
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "getLiquidStatus(): vmap liquid level: {0} ground: {1} type: {2}",
|
||||
liquid_level, ground_level, liquid_type);
|
||||
@@ -1887,7 +1958,7 @@ namespace Game.Maps
|
||||
|
||||
if (liquid_type != 0 && liquid_type < 21)
|
||||
{
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(GetAreaId(x, y, z));
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(GetAreaId(phaseShift, x, y, z));
|
||||
if (area != null)
|
||||
{
|
||||
uint overrideLiquid = area.LiquidTypeID[liquidFlagType];
|
||||
@@ -1926,7 +1997,7 @@ namespace Game.Maps
|
||||
}
|
||||
}
|
||||
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(terrainMapId, x, y);
|
||||
if (gmap != null)
|
||||
{
|
||||
var map_data = new LiquidData();
|
||||
@@ -1946,27 +2017,27 @@ namespace Game.Maps
|
||||
return result;
|
||||
}
|
||||
|
||||
public float GetWaterLevel(float x, float y)
|
||||
public float GetWaterLevel(PhaseShift phaseShift, float x, float y)
|
||||
{
|
||||
GridMap gmap = GetGridMap(x, y);
|
||||
GridMap gmap = GetGridMap(PhasingHandler.GetTerrainMapId(phaseShift, this, x, y), x, y);
|
||||
if (gmap != null)
|
||||
return gmap.getLiquidLevel(x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, List<uint> phases)
|
||||
public bool isInLineOfSight(PhaseShift phaseShift, float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
{
|
||||
return Global.VMapMgr.isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
|
||||
&& _dynamicTree.isInLineOfSight(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), phases);
|
||||
return Global.VMapMgr.isInLineOfSight(PhasingHandler.GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2)
|
||||
&& _dynamicTree.isInLineOfSight(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), phaseShift);
|
||||
}
|
||||
|
||||
public bool getObjectHitPos(List<uint> phases, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
public bool getObjectHitPos(PhaseShift phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, out float rx, out float ry, out float rz, float modifyDist)
|
||||
{
|
||||
var startPos = new Vector3(x1, y1, z1);
|
||||
var dstPos = new Vector3(x2, y2, z2);
|
||||
|
||||
var resultPos = new Vector3();
|
||||
bool result = _dynamicTree.getObjectHitPos(phases, startPos, dstPos, ref resultPos, modifyDist);
|
||||
bool result = _dynamicTree.getObjectHitPos(startPos, dstPos, ref resultPos, modifyDist, phaseShift);
|
||||
|
||||
rx = resultPos.X;
|
||||
ry = resultPos.Y;
|
||||
@@ -1974,22 +2045,19 @@ namespace Game.Maps
|
||||
return result;
|
||||
}
|
||||
|
||||
public float GetHeight(List<uint> phases, float x, float y, float z, bool vmap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
public float GetHeight(PhaseShift phaseShift, float x, float y, float z, bool vmap = true, float maxSearchDist = MapConst.DefaultHeightSearch)
|
||||
{
|
||||
return Math.Max(GetHeight(x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phases));
|
||||
return Math.Max(GetStaticHeight(phaseShift, x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phaseShift));
|
||||
}
|
||||
|
||||
public bool IsInWater(float x, float y, float pZ)
|
||||
public bool IsInWater(PhaseShift phaseShift, float x, float y, float pZ)
|
||||
{
|
||||
return Convert.ToBoolean(getLiquidStatus(x, y, pZ, MapConst.MapAllLiquidTypes) &
|
||||
(ZLiquidStatus.InWater | ZLiquidStatus.UnderWater));
|
||||
return Convert.ToBoolean(getLiquidStatus(phaseShift, x, y, pZ, MapConst.MapAllLiquidTypes) & (ZLiquidStatus.InWater | ZLiquidStatus.UnderWater));
|
||||
}
|
||||
|
||||
public bool IsUnderWater(float x, float y, float z)
|
||||
public bool IsUnderWater(PhaseShift phaseShift, float x, float y, float z)
|
||||
{
|
||||
return
|
||||
Convert.ToBoolean(getLiquidStatus(x, y, z, MapConst.MapLiquidTypeWater | MapConst.MapLiquidTypeOcean) &
|
||||
ZLiquidStatus.UnderWater);
|
||||
return Convert.ToBoolean(getLiquidStatus(phaseShift, x, y, z, MapConst.MapLiquidTypeWater | MapConst.MapLiquidTypeOcean) & ZLiquidStatus.UnderWater);
|
||||
}
|
||||
|
||||
private bool CheckGridIntegrity(Creature c, bool moved)
|
||||
@@ -2007,30 +2075,32 @@ namespace Game.Maps
|
||||
return i_mapRecord != null ? i_mapRecord.MapName[Global.WorldMgr.GetDefaultDbcLocale()] : "UNNAMEDMAP";
|
||||
}
|
||||
|
||||
public void SendInitSelf(Player pl)
|
||||
public void SendInitSelf(Player player)
|
||||
{
|
||||
var data = new UpdateData(pl.GetMapId());
|
||||
var data = new UpdateData(player.GetMapId());
|
||||
|
||||
// attach to player data current transport data
|
||||
Transport transport = pl.GetTransport();
|
||||
if (transport != null)
|
||||
transport.BuildCreateUpdateBlockForPlayer(data, pl);
|
||||
|
||||
pl.BuildCreateUpdateBlockForPlayer(data, pl);
|
||||
|
||||
// build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
|
||||
|
||||
Transport transport = player.GetTransport();
|
||||
if (transport != null)
|
||||
{
|
||||
foreach (WorldObject obj in transport.GetPassengers())
|
||||
transport.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
player.m_visibleTransports.Add(transport.GetGUID());
|
||||
}
|
||||
|
||||
player.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
|
||||
// build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
|
||||
if (transport != null)
|
||||
{
|
||||
foreach (WorldObject passenger in transport.GetPassengers())
|
||||
{
|
||||
if (pl != obj && pl.HaveAtClient(obj))
|
||||
obj.BuildCreateUpdateBlockForPlayer(data, pl);
|
||||
if (player != passenger && player.HaveAtClient(passenger))
|
||||
passenger.BuildCreateUpdateBlockForPlayer(data, player);
|
||||
}
|
||||
}
|
||||
UpdateObject packet;
|
||||
data.BuildPacket(out packet);
|
||||
pl.SendPacket(packet);
|
||||
player.SendPacket(packet);
|
||||
}
|
||||
|
||||
void SendInitTransports(Player player)
|
||||
@@ -2040,7 +2110,10 @@ namespace Game.Maps
|
||||
foreach (Transport transport in _transports)
|
||||
{
|
||||
if (transport != player.GetTransport() && player.IsInPhase(transport))
|
||||
{
|
||||
transport.BuildCreateUpdateBlockForPlayer(transData, player);
|
||||
player.m_visibleTransports.Add(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateObject packet;
|
||||
@@ -2052,27 +2125,39 @@ namespace Game.Maps
|
||||
{
|
||||
var transData = new UpdateData(player.GetMapId());
|
||||
foreach (Transport transport in _transports)
|
||||
{
|
||||
if (transport != player.GetTransport())
|
||||
{
|
||||
transport.BuildOutOfRangeUpdateBlock(transData);
|
||||
player.m_visibleTransports.Remove(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateObject packet;
|
||||
transData.BuildPacket(out packet);
|
||||
player.SendPacket(packet);
|
||||
}
|
||||
|
||||
public void SendUpdateTransportVisibility(Player player, List<uint> previousPhases)
|
||||
public void SendUpdateTransportVisibility(Player player)
|
||||
{
|
||||
// Hack to send out transports
|
||||
UpdateData transData = new UpdateData(player.GetMapId());
|
||||
foreach (var trans in _transports)
|
||||
foreach (var transport in _transports)
|
||||
{
|
||||
if (trans == player.GetTransport())
|
||||
continue;
|
||||
|
||||
if (player.IsInPhase(trans) && !previousPhases.Intersect(trans.GetPhases()).Any())
|
||||
trans.BuildCreateUpdateBlockForPlayer(transData, player);
|
||||
else if (!player.IsInPhase(trans))
|
||||
trans.BuildOutOfRangeUpdateBlock(transData);
|
||||
var hasTransport = player.m_visibleTransports.Contains(transport.GetGUID());
|
||||
if (player.IsInPhase(transport))
|
||||
{
|
||||
if (!hasTransport)
|
||||
{
|
||||
transport.BuildCreateUpdateBlockForPlayer(transData, player);
|
||||
player.m_visibleTransports.Add(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
transport.BuildOutOfRangeUpdateBlock(transData);
|
||||
player.m_visibleTransports.Remove(transport.GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateObject packet;
|
||||
@@ -2525,7 +2610,7 @@ namespace Game.Maps
|
||||
continue;
|
||||
|
||||
foreach (var phaseId in phases[guid])
|
||||
corpse.SetInPhase(phaseId, false, true);
|
||||
PhasingHandler.AddPhase(corpse, phaseId, false);
|
||||
|
||||
AddCorpse(corpse);
|
||||
} while (result.NextRow());
|
||||
@@ -2604,7 +2689,7 @@ namespace Game.Maps
|
||||
|
||||
bones.SetUInt32Value(CorpseFields.Flags, corpse.GetUInt32Value(CorpseFields.Flags) | (uint)CorpseFlags.Bones);
|
||||
|
||||
bones.CopyPhaseFrom(corpse);
|
||||
PhasingHandler.InheritPhaseShift(bones, corpse);
|
||||
|
||||
AddCorpse(bones);
|
||||
|
||||
@@ -2847,6 +2932,10 @@ namespace Game.Maps
|
||||
return m_parentMap;
|
||||
}
|
||||
|
||||
public void AddChildTerrainMap(Map map) { m_childTerrainMaps.Add(map); }
|
||||
|
||||
public void UnlinkAllChildTerrainMaps() { m_childTerrainMaps.Clear(); }
|
||||
|
||||
public uint GetInstanceId()
|
||||
{
|
||||
return i_InstanceId;
|
||||
@@ -3225,7 +3314,8 @@ namespace Game.Maps
|
||||
return null;
|
||||
|
||||
// Set the summon to the summoner's phase
|
||||
summon.CopyPhaseFrom(summoner);
|
||||
if (summoner)
|
||||
PhasingHandler.InheritPhaseShift(summon, summoner);
|
||||
|
||||
summon.SetUInt32Value(UnitFields.CreatedBySpell, spellId);
|
||||
|
||||
@@ -4219,6 +4309,7 @@ namespace Game.Maps
|
||||
protected List<WorldObject> m_activeNonPlayers = new List<WorldObject>();
|
||||
protected List<Player> m_activePlayers = new List<Player>();
|
||||
Map m_parentMap;
|
||||
List<Map> m_childTerrainMaps = new List<Map>();
|
||||
SortedMultiMap<long, ScriptAction> m_scriptSchedule = new SortedMultiMap<long, ScriptAction>();
|
||||
|
||||
BitArray marked_cells = new BitArray(MapConst.TotalCellsPerMap * MapConst.TotalCellsPerMap);
|
||||
|
||||
+108
-74
@@ -37,10 +37,15 @@ namespace Game.Entities
|
||||
public void Initialize()
|
||||
{
|
||||
//todo needs alot of support for threadsafe.
|
||||
//int num_threads= WorldConfig.GetIntValue(WorldCfg.Numthreads);
|
||||
int num_threads = WorldConfig.GetIntValue(WorldCfg.Numthreads);
|
||||
// Start mtmaps if needed.
|
||||
//if (num_threads > 0)
|
||||
//m_updater = new MapUpdater(WorldConfig.GetIntValue(WorldCfg.Numthreads));
|
||||
if (num_threads > 0)
|
||||
m_updater = new MapUpdater(WorldConfig.GetIntValue(WorldCfg.Numthreads));
|
||||
}
|
||||
|
||||
public void InitializeParentMapData(MultiMap<uint, uint> mapData)
|
||||
{
|
||||
_parentMapData = mapData;
|
||||
}
|
||||
|
||||
public void InitializeVisibilityDistanceInfo()
|
||||
@@ -52,31 +57,46 @@ namespace Game.Entities
|
||||
public Map CreateBaseMap(uint id)
|
||||
{
|
||||
Map map = FindBaseMap(id);
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
lock (this)
|
||||
var entry = CliDB.MapStorage.LookupByKey(id);
|
||||
Contract.Assert(entry != null);
|
||||
if (entry.ParentMapID != -1)
|
||||
{
|
||||
CreateBaseMap((uint)entry.ParentMapID);
|
||||
|
||||
var entry = CliDB.MapStorage.LookupByKey(id);
|
||||
Contract.Assert(entry != null);
|
||||
|
||||
if (entry.Instanceable())
|
||||
map = new MapInstanced(id, i_gridCleanUpDelay);
|
||||
else
|
||||
{
|
||||
map = new Map(id, i_gridCleanUpDelay, 0, Difficulty.None);
|
||||
map.LoadRespawnTimes();
|
||||
map.LoadCorpseData();
|
||||
}
|
||||
|
||||
i_maps[id] = map;
|
||||
// must have been created by parent map
|
||||
map = FindBaseMap(id);
|
||||
return map;
|
||||
}
|
||||
|
||||
lock(_mapsLock)
|
||||
map = CreateBaseMap_i(entry);
|
||||
}
|
||||
Contract.Assert(map != null);
|
||||
return map;
|
||||
}
|
||||
|
||||
Map CreateBaseMap_i(MapRecord mapEntry)
|
||||
{
|
||||
Map map;
|
||||
if (mapEntry.Instanceable())
|
||||
map = new MapInstanced(mapEntry.Id, i_gridCleanUpDelay);
|
||||
else
|
||||
{
|
||||
map = new Map(mapEntry.Id, i_gridCleanUpDelay, 0, Difficulty.None);
|
||||
map.LoadRespawnTimes();
|
||||
map.LoadCorpseData();
|
||||
}
|
||||
|
||||
i_maps[mapEntry.Id] = map;
|
||||
|
||||
foreach (uint childMapId in _parentMapData[mapEntry.Id])
|
||||
map.AddChildTerrainMap(CreateBaseMap_i(CliDB.MapStorage.LookupByKey(childMapId)));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map FindBaseNonInstanceMap(uint mapId)
|
||||
{
|
||||
Map map = FindBaseMap(mapId);
|
||||
@@ -206,20 +226,14 @@ namespace Game.Entities
|
||||
var time = (uint)i_timer.GetCurrent();
|
||||
foreach (var map in i_maps.Values.ToList())
|
||||
{
|
||||
//if (!m_updater)
|
||||
//m_updater.Enqueue(map, (uint)i_timer.GetCurrent());
|
||||
//else
|
||||
map.Update(time);
|
||||
if (m_updater != null)
|
||||
m_updater.Enqueue(map, (uint)i_timer.GetCurrent());
|
||||
else
|
||||
map.Update(time);
|
||||
}
|
||||
|
||||
//List<System.Threading.Tasks.Task> tasks = new List<System.Threading.Tasks.Task>();
|
||||
//foreach (var map in i_maps.Values.ToList())
|
||||
{
|
||||
//tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(() => map.Update(time)));
|
||||
}
|
||||
//System.Threading.Tasks.Task.WaitAll(tasks.ToArray());
|
||||
//if (!m_updater)
|
||||
// m_updater.Wait();
|
||||
if (m_updater != null)
|
||||
m_updater.Wait();
|
||||
|
||||
foreach (var map in i_maps.ToList())
|
||||
map.Value.DelayedUpdate(time);
|
||||
@@ -251,6 +265,10 @@ namespace Game.Entities
|
||||
|
||||
public void UnloadAll()
|
||||
{
|
||||
// first unlink child maps
|
||||
foreach (var pair in i_maps)
|
||||
pair.Value.UnlinkAllChildTerrainMaps();
|
||||
|
||||
foreach (var pair in i_maps.ToList())
|
||||
{
|
||||
pair.Value.UnloadAll();
|
||||
@@ -260,34 +278,40 @@ namespace Game.Entities
|
||||
|
||||
public uint GetNumInstances()
|
||||
{
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps.ToList())
|
||||
lock (_mapsLock)
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret++;
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps.ToList())
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public uint GetNumPlayersInInstances()
|
||||
{
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps)
|
||||
lock (_mapsLock)
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret += (uint)imap.Value.GetPlayers().Count;
|
||||
uint ret = 0;
|
||||
foreach (var pair in i_maps)
|
||||
{
|
||||
Map map = pair.Value;
|
||||
if (!map.Instanceable())
|
||||
continue;
|
||||
var maps = ((MapInstanced)map).GetInstancedMaps();
|
||||
foreach (var imap in maps)
|
||||
if (imap.Value.IsDungeon())
|
||||
ret += (uint)imap.Value.GetPlayers().Count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void InitInstanceIds()
|
||||
@@ -361,54 +385,60 @@ namespace Game.Entities
|
||||
return i_maps.LookupByKey(mapId);
|
||||
}
|
||||
|
||||
uint GetAreaId(uint mapid, float x, float y, float z)
|
||||
uint GetAreaId(PhaseShift phaseShift, uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
return m.GetAreaId(x, y, z);
|
||||
return m.GetAreaId(phaseShift, x, y, z);
|
||||
}
|
||||
|
||||
public uint GetZoneId(uint mapid, float x, float y, float z)
|
||||
public uint GetZoneId(PhaseShift phaseShift, uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
return m.GetZoneId(x, y, z);
|
||||
return m.GetZoneId(phaseShift, x, y, z);
|
||||
}
|
||||
|
||||
public void GetZoneAndAreaId(out uint zoneid, out uint areaid, uint mapid, float x, float y, float z)
|
||||
public void GetZoneAndAreaId(PhaseShift phaseShift, out uint zoneid, out uint areaid, uint mapid, float x, float y, float z)
|
||||
{
|
||||
Map m = CreateBaseMap(mapid);
|
||||
m.GetZoneAndAreaId(out zoneid, out areaid, x, y, z);
|
||||
m.GetZoneAndAreaId(phaseShift, out zoneid, out areaid, x, y, z);
|
||||
}
|
||||
|
||||
public void DoForAllMaps(Action<Map> worker)
|
||||
{
|
||||
foreach (var map in i_maps.Values)
|
||||
lock (_mapsLock)
|
||||
{
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
foreach (var map in i_maps.Values)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances.Values)
|
||||
worker(instance);
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances.Values)
|
||||
worker(instance);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
}
|
||||
|
||||
public void DoForAllMapsWithMapId(uint mapId, Action<Map> worker)
|
||||
{
|
||||
var map = i_maps.LookupByKey(mapId);
|
||||
if (map != null)
|
||||
lock (_mapsLock)
|
||||
{
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
var map = i_maps.LookupByKey(mapId);
|
||||
if (map != null)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances)
|
||||
worker(instance.Value);
|
||||
MapInstanced mapInstanced = map.ToMapInstanced();
|
||||
if (mapInstanced)
|
||||
{
|
||||
var instances = mapInstanced.GetInstancedMaps();
|
||||
foreach (var instance in instances)
|
||||
worker(instance.Value);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
else
|
||||
worker(map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,10 +449,14 @@ namespace Game.Entities
|
||||
|
||||
Dictionary<uint, Map> i_maps = new Dictionary<uint, Map>();
|
||||
IntervalTimer i_timer = new IntervalTimer();
|
||||
object _mapsLock= new object();
|
||||
uint i_gridCleanUpDelay;
|
||||
Dictionary<uint, bool> _instanceIds = new Dictionary<uint, bool>();
|
||||
uint _nextInstanceId;
|
||||
//MapUpdater m_updater;
|
||||
MapUpdater m_updater;
|
||||
uint _scheduledScripts;
|
||||
|
||||
// parent map links
|
||||
MultiMap<uint, uint> _parentMapData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ namespace Game.Maps
|
||||
_transportAnimations[transportEntry] = animNode;
|
||||
}
|
||||
|
||||
public Transport CreateTransport(uint entry, ulong guid = 0, Map map = null, uint phaseid = 0, uint phasegroup = 0)
|
||||
public Transport CreateTransport(uint entry, ulong guid = 0, Map map = null, PhaseUseFlagsValues phaseUseFlags = 0, uint phaseId = 0, uint phaseGroupId = 0)
|
||||
{
|
||||
// instance case, execute GetGameObjectEntry hook
|
||||
if (map != null)
|
||||
@@ -388,12 +388,7 @@ namespace Game.Maps
|
||||
if (!trans.Create(guidLow, entry, mapId, x, y, z, o, 255))
|
||||
return null;
|
||||
|
||||
if (phaseid != 0)
|
||||
trans.SetInPhase(phaseid, false, true);
|
||||
|
||||
if (phasegroup != 0)
|
||||
foreach (var ph in Global.DB2Mgr.GetPhasesForGroup(phasegroup))
|
||||
trans.SetInPhase(ph, false, true);
|
||||
PhasingHandler.InitDbPhaseShift(trans.GetPhaseShift(), phaseUseFlags, phaseId, phaseGroupId);
|
||||
|
||||
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(mapId);
|
||||
if (mapEntry != null)
|
||||
@@ -424,7 +419,7 @@ namespace Game.Maps
|
||||
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT guid, entry, phaseid, phasegroup FROM transports");
|
||||
SQLResult result = DB.World.Query("SELECT guid, entry, phaseUseFlags, phaseid, phasegroup FROM transports");
|
||||
|
||||
uint count = 0;
|
||||
if (!result.IsEmpty())
|
||||
@@ -433,13 +428,51 @@ namespace Game.Maps
|
||||
{
|
||||
ulong guid = result.Read<ulong>(0);
|
||||
uint entry = result.Read<uint>(1);
|
||||
uint phaseid = result.Read<uint>(2);
|
||||
uint phasegroup = result.Read<uint>(3);
|
||||
PhaseUseFlagsValues phaseUseFlags = (PhaseUseFlagsValues)result.Read<byte>(2);
|
||||
uint phaseId = result.Read<uint>(3);
|
||||
uint phaseGroupId = result.Read<uint>(4);
|
||||
|
||||
if (Convert.ToBoolean(phaseUseFlags & ~PhaseUseFlagsValues.All))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with unknown `phaseUseFlags` set, removed unknown value.");
|
||||
phaseUseFlags &= PhaseUseFlagsValues.All;
|
||||
}
|
||||
|
||||
if (phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.AlwaysVisible) && phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.Inverse))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE," +
|
||||
" removing PHASE_USE_FLAGS_INVERSE.");
|
||||
phaseUseFlags &= ~PhaseUseFlagsValues.Inverse;
|
||||
}
|
||||
|
||||
if (phaseGroupId != 0 && phaseId != 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0");
|
||||
phaseGroupId = 0;
|
||||
}
|
||||
|
||||
if (phaseId != 0)
|
||||
{
|
||||
if (!CliDB.PhaseStorage.ContainsKey(phaseId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with `phaseid` {phaseId} does not exist, set to 0");
|
||||
phaseId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (phaseGroupId != 0)
|
||||
{
|
||||
if (Global.DB2Mgr.GetPhasesForGroup(phaseGroupId).Empty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `transports` have transport (GUID: {guid} Entry: {entry}) with `phaseGroup` {phaseGroupId} does not exist, set to 0");
|
||||
phaseGroupId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
TransportTemplate tInfo = GetTransportTemplate(entry);
|
||||
if (tInfo != null)
|
||||
if (!tInfo.inInstance)
|
||||
if (CreateTransport(entry, guid, null, phaseid, phasegroup))
|
||||
if (CreateTransport(entry, guid, null, phaseUseFlags, phaseId, phaseGroupId))
|
||||
++count;
|
||||
|
||||
} while (result.NextRow());
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Game.Movement
|
||||
_getPoint(owner, out x, out y, out z);
|
||||
|
||||
Position mypos = owner.GetPosition();
|
||||
bool isInLOS = Global.VMapMgr.isInLineOfSight(owner.GetMapId(), mypos.posX, mypos.posY, mypos.posZ + 2.0f, x, y, z + 2.0f);
|
||||
bool isInLOS = Global.VMapMgr.isInLineOfSight(PhasingHandler.GetTerrainMapId(owner.GetPhaseShift(), owner.GetMap(), mypos.posX, mypos.posY), mypos.posX, mypos.posY, mypos.posZ + 2.0f, x, y, z + 2.0f);
|
||||
|
||||
if (!isInLOS)
|
||||
{
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace Game.Movement
|
||||
_navMeshQuery = null;
|
||||
Log.outDebug(LogFilter.Maps, "PathGenerator:PathGenerator for {0}", _sourceUnit.GetGUID().ToString());
|
||||
|
||||
uint mapId = _sourceUnit.GetMapId();
|
||||
if (Global.DisableMgr.IsPathfindingEnabled(mapId))
|
||||
uint mapId = PhasingHandler.GetTerrainMapId(_sourceUnit.GetPhaseShift(), _sourceUnit.GetMap(), _sourceUnit.GetPositionX(), _sourceUnit.GetPositionY());
|
||||
if (Global.DisableMgr.IsPathfindingEnabled(_sourceUnit.GetMapId()))
|
||||
{
|
||||
_navMesh = Global.MMapMgr.GetNavMesh(mapId);
|
||||
_navMeshQuery = Global.MMapMgr.GetNavMeshQuery(mapId, _sourceUnit.GetInstanceId());
|
||||
@@ -175,7 +175,7 @@ namespace Game.Movement
|
||||
// Check both start and end points, if they're both in water, then we can *safely* let the creature move
|
||||
for (uint i = 0; i < _pathPoints.Length; ++i)
|
||||
{
|
||||
ZLiquidStatus status = _sourceUnit.GetMap().getLiquidStatus(_pathPoints[i].X, _pathPoints[i].Y, _pathPoints[i].Z, MapConst.MapAllLiquidTypes);
|
||||
ZLiquidStatus status = _sourceUnit.GetMap().getLiquidStatus(_sourceUnit.GetPhaseShift(), _pathPoints[i].X, _pathPoints[i].Y, _pathPoints[i].Z, MapConst.MapAllLiquidTypes);
|
||||
// One of the points is not in the water, cancel movement.
|
||||
if (status == ZLiquidStatus.NoWater)
|
||||
{
|
||||
@@ -201,7 +201,7 @@ namespace Game.Movement
|
||||
Creature owner = _sourceUnit.ToCreature();
|
||||
|
||||
Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos;
|
||||
if (_sourceUnit.GetMap().IsUnderWater(p.X, p.Y, p.Z))
|
||||
if (_sourceUnit.GetMap().IsUnderWater(_sourceUnit.GetPhaseShift(), p.X, p.Y, p.Z))
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "++ BuildPolyPath . underWater case\n");
|
||||
if (owner.CanSwim())
|
||||
@@ -834,7 +834,7 @@ namespace Game.Movement
|
||||
NavTerrain GetNavTerrain(float x, float y, float z)
|
||||
{
|
||||
LiquidData data;
|
||||
ZLiquidStatus liquidStatus = _sourceUnit.GetMap().getLiquidStatus(x, y, z, MapConst.MapAllLiquidTypes, out data);
|
||||
ZLiquidStatus liquidStatus = _sourceUnit.GetMap().getLiquidStatus(_sourceUnit.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out data);
|
||||
if (liquidStatus == ZLiquidStatus.NoWater)
|
||||
return NavTerrain.Ground;
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Game.Movement
|
||||
// Limit height change
|
||||
float distanceZ = (float)(RandomHelper.NextDouble() * travelDistZ / 2.0f);
|
||||
destZ = respZ + distanceZ;
|
||||
float levelZ = map.GetWaterOrGroundLevel(creature.GetPhases(), destX, destY, destZ - 2.5f);
|
||||
float levelZ = map.GetWaterOrGroundLevel(creature.GetPhaseShift(), destX, destY, destZ - 2.5f);
|
||||
|
||||
// Problem here, we must fly above the ground and water, not under. Let's try on next tick
|
||||
if (levelZ >= destZ)
|
||||
@@ -130,17 +130,17 @@ namespace Game.Movement
|
||||
|
||||
// The fastest way to get an accurate result 90% of the time.
|
||||
// Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
|
||||
destZ = map.GetHeight(creature.GetPhases(), destX, destY, respZ + travelDistZ - 2.0f, false);
|
||||
destZ = map.GetHeight(creature.GetPhaseShift(), destX, destY, respZ + travelDistZ - 2.0f, false);
|
||||
|
||||
if (Math.Abs(destZ - respZ) > travelDistZ) // Map check
|
||||
{
|
||||
// Vmap Horizontal or above
|
||||
destZ = map.GetHeight(creature.GetPhases(), destX, destY, respZ - 2.0f, true);
|
||||
destZ = map.GetHeight(creature.GetPhaseShift(), destX, destY, respZ - 2.0f, true);
|
||||
|
||||
if (Math.Abs(destZ - respZ) > travelDistZ)
|
||||
{
|
||||
// Vmap Higher
|
||||
destZ = map.GetHeight(creature.GetPhases(), destX, destY, respZ + travelDistZ - 2.0f, true);
|
||||
destZ = map.GetHeight(creature.GetPhaseShift(), destX, destY, respZ + travelDistZ - 2.0f, true);
|
||||
|
||||
// let's forget this bad coords where a z cannot be find and retry at next tick
|
||||
if (Math.Abs(destZ - respZ) > travelDistZ)
|
||||
|
||||
@@ -436,7 +436,7 @@ namespace Game.Movement
|
||||
if (_owner.IsFlying())
|
||||
point.Z = z;
|
||||
else
|
||||
point.Z = _owner.GetMap().GetHeight(_owner.GetPhases(), point.X, point.Y, z);
|
||||
point.Z = _owner.GetMap().GetHeight(_owner.GetPhaseShift(), point.X, point.Y, z);
|
||||
|
||||
init.args.path[i] = point;
|
||||
}
|
||||
@@ -514,7 +514,7 @@ namespace Game.Movement
|
||||
public void MoveFall(uint id = 0)
|
||||
{
|
||||
// use larger distance for vmap height search than in most other cases
|
||||
float tz = _owner.GetMap().GetHeight(_owner.GetPhases(), _owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ(), true, MapConst.MaxFallDistance);
|
||||
float tz = _owner.GetMap().GetHeight(_owner.GetPhaseShift(), _owner.GetPositionX(), _owner.GetPositionY(), _owner.GetPositionZ(), true, MapConst.MaxFallDistance);
|
||||
if (tz <= MapConst.InvalidHeight)
|
||||
return;
|
||||
|
||||
|
||||
@@ -743,43 +743,38 @@ namespace Game.Network.Packets
|
||||
public override void Write() { }
|
||||
}
|
||||
|
||||
public class PhaseShift : ServerPacket
|
||||
|
||||
class PhaseShiftChange : ServerPacket
|
||||
{
|
||||
public PhaseShift() : base(ServerOpcodes.PhaseShiftChange, ConnectionType.Instance) { }
|
||||
public PhaseShiftChange() : base(ServerOpcodes.PhaseShiftChange) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WritePackedGuid(ClientGUID);
|
||||
_worldPacket.WriteUInt32(!PhaseShifts.Empty() ? 0 : 8); // PhaseShiftFlags
|
||||
_worldPacket.WriteUInt32(PhaseShifts.Count);
|
||||
_worldPacket.WritePackedGuid(PersonalGUID);
|
||||
foreach (uint phase in PhaseShifts)
|
||||
{
|
||||
_worldPacket.WriteUInt16(1); // PhaseFlags
|
||||
_worldPacket.WriteUInt16(phase); // PhaseID
|
||||
}
|
||||
_worldPacket.WritePackedGuid(Client);
|
||||
Phaseshift.Write(_worldPacket);
|
||||
_worldPacket.WriteUInt32(VisibleMapIDs.Count * 2); // size in bytes
|
||||
foreach (ushort visibleMapId in VisibleMapIDs)
|
||||
_worldPacket.WriteUInt16(visibleMapId); // Active terrain swap map id
|
||||
|
||||
_worldPacket.WriteUInt32(VisibleMapIDs.Count * 2);
|
||||
foreach (uint map in VisibleMapIDs)
|
||||
_worldPacket.WriteUInt16(map); // Active terrain swap map id
|
||||
_worldPacket.WriteUInt32(PreloadMapIDs.Count * 2); // size in bytes
|
||||
foreach (ushort preloadMapId in PreloadMapIDs)
|
||||
_worldPacket.WriteUInt16(preloadMapId); // Inactive terrain swap map id
|
||||
|
||||
_worldPacket.WriteUInt32(PreloadMapIDs.Count * 2);
|
||||
foreach (uint map in PreloadMapIDs)
|
||||
_worldPacket.WriteUInt16(map); // Inactive terrain swap map id
|
||||
|
||||
_worldPacket.WriteUInt32(UiWorldMapAreaIDSwaps.Count * 2);
|
||||
foreach (uint map in UiWorldMapAreaIDSwaps)
|
||||
_worldPacket.WriteUInt16(map); // UI map id, WorldMapArea.dbc, controls map display
|
||||
_worldPacket.WriteUInt32(UiWorldMapAreaIDSwaps.Count * 2); // size in bytes
|
||||
foreach (ushort uiWorldMapAreaIDSwap in UiWorldMapAreaIDSwaps)
|
||||
_worldPacket.WriteUInt16(uiWorldMapAreaIDSwap); // UI map id, WorldMapArea.db2, controls map display
|
||||
}
|
||||
|
||||
public ObjectGuid ClientGUID;
|
||||
public ObjectGuid PersonalGUID;
|
||||
public List<uint> PhaseShifts = new List<uint>();
|
||||
public List<uint> PreloadMapIDs = new List<uint>();
|
||||
public List<uint> UiWorldMapAreaIDSwaps = new List<uint>();
|
||||
public List<uint> VisibleMapIDs = new List<uint>();
|
||||
public ObjectGuid Client;
|
||||
public PhaseShiftData Phaseshift = new PhaseShiftData();
|
||||
public List<ushort> PreloadMapIDs = new List<ushort>();
|
||||
public List<ushort> UiWorldMapAreaIDSwaps = new List<ushort>();
|
||||
public List<ushort> VisibleMapIDs = new List<ushort>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class ZoneUnderAttack : ServerPacket
|
||||
{
|
||||
public ZoneUnderAttack() : base(ServerOpcodes.ZoneUnderAttack, ConnectionType.Instance) { }
|
||||
@@ -1299,4 +1294,39 @@ namespace Game.Network.Packets
|
||||
|
||||
public ObjectGuid SourceGuid;
|
||||
}
|
||||
|
||||
//Structs
|
||||
struct PhaseShiftDataPhase
|
||||
{
|
||||
public PhaseShiftDataPhase(uint phaseFlags, uint id)
|
||||
{
|
||||
PhaseFlags = (ushort)phaseFlags;
|
||||
Id = (ushort)id;
|
||||
}
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt16(PhaseFlags);
|
||||
data.WriteUInt16(Id);
|
||||
}
|
||||
|
||||
public ushort PhaseFlags;
|
||||
public ushort Id;
|
||||
}
|
||||
|
||||
class PhaseShiftData
|
||||
{
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt32(PhaseShiftFlags);
|
||||
data.WriteUInt32(Phases.Count);
|
||||
data.WritePackedGuid(PersonalGUID);
|
||||
foreach (PhaseShiftDataPhase phaseShiftDataPhase in Phases)
|
||||
phaseShiftDataPhase.Write(data);
|
||||
}
|
||||
|
||||
public uint PhaseShiftFlags;
|
||||
public List<PhaseShiftDataPhase> Phases = new List<PhaseShiftDataPhase>();
|
||||
public ObjectGuid PersonalGUID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,16 +313,7 @@ namespace Game.Network.Packets
|
||||
}
|
||||
|
||||
// Phases
|
||||
var phases = player.GetPhases();
|
||||
MemberStats.Phases.PhaseShiftFlags = 0x08 | (!phases.Empty() ? 0x10 : 0);
|
||||
MemberStats.Phases.PersonalGUID = ObjectGuid.Empty;
|
||||
foreach (uint phaseId in phases)
|
||||
{
|
||||
PartyMemberPhase phase;
|
||||
phase.Id = (ushort)phaseId;
|
||||
phase.Flags = 1;
|
||||
MemberStats.Phases.List.Add(phase);
|
||||
}
|
||||
PhasingHandler.FillPartyMemberPhase(MemberStats.Phases, player.GetPhaseShift());
|
||||
|
||||
// Pet
|
||||
if (player.GetPet())
|
||||
@@ -892,8 +883,14 @@ namespace Game.Network.Packets
|
||||
}
|
||||
|
||||
//Structs
|
||||
struct PartyMemberPhase
|
||||
public struct PartyMemberPhase
|
||||
{
|
||||
public PartyMemberPhase(uint flags, uint id)
|
||||
{
|
||||
Flags = (ushort)flags;
|
||||
Id = (ushort)id;
|
||||
}
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt16(Flags);
|
||||
@@ -904,7 +901,7 @@ namespace Game.Network.Packets
|
||||
public ushort Id;
|
||||
}
|
||||
|
||||
class PartyMemberPhaseStates
|
||||
public class PartyMemberPhaseStates
|
||||
{
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2018 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Game.Conditions;
|
||||
using Game.Entities;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public class PhaseShift
|
||||
{
|
||||
public bool AddPhase(uint phaseId, PhaseFlags flags, List<Condition> areaConditions, int references = 1)
|
||||
{
|
||||
var phase = new PhaseRef(phaseId, flags, null);
|
||||
ModifyPhasesReferences(phase, references);
|
||||
if (areaConditions != null)
|
||||
phase.AreaConditions = areaConditions;
|
||||
|
||||
Phases.Add(phase);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RemovePhase(uint phaseId)
|
||||
{
|
||||
var phaseRef = new PhaseRef(phaseId, PhaseFlags.None, null);
|
||||
if (Phases.Contains(phaseRef))
|
||||
{
|
||||
ModifyPhasesReferences(phaseRef, -1);
|
||||
if (phaseRef.References == 0)
|
||||
{
|
||||
Phases.Remove(phaseRef);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool AddVisibleMapId(uint visibleMapId, TerrainSwapInfo visibleMapInfo, int references = 1)
|
||||
{
|
||||
VisibleMapIds.Add(visibleMapId, new VisibleMapIdRef(references, visibleMapInfo));
|
||||
return true; //Tryadd? maybe Concurrent
|
||||
}
|
||||
|
||||
public bool RemoveVisibleMapId(uint visibleMapId)
|
||||
{
|
||||
if (VisibleMapIds.ContainsKey(visibleMapId))
|
||||
{
|
||||
var mapIdRef = VisibleMapIds[visibleMapId];
|
||||
if ((--mapIdRef.References) == 0)
|
||||
{
|
||||
VisibleMapIds.Remove(visibleMapId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool AddUiWorldMapAreaIdSwap(uint uiWorldMapAreaId, int references = 1)
|
||||
{
|
||||
UiWorldMapAreaIdSwaps.Add(uiWorldMapAreaId, new UiWorldMapAreaIdSwapRef(references));
|
||||
return true; //Tryadd? maybe Concurrent
|
||||
}
|
||||
|
||||
public bool RemoveUiWorldMapAreaIdSwap(uint uiWorldMapAreaId)
|
||||
{
|
||||
if (UiWorldMapAreaIdSwaps.ContainsKey(uiWorldMapAreaId))
|
||||
{
|
||||
var value = UiWorldMapAreaIdSwaps[uiWorldMapAreaId];
|
||||
if ((--value.References) == 0)
|
||||
{
|
||||
UiWorldMapAreaIdSwaps.Remove(uiWorldMapAreaId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ClearPhases();
|
||||
PersonalGuid.Clear();
|
||||
VisibleMapIds.Clear();
|
||||
UiWorldMapAreaIdSwaps.Clear();
|
||||
}
|
||||
|
||||
public void ClearPhases()
|
||||
{
|
||||
Flags &= PhaseShiftFlags.AlwaysVisible | PhaseShiftFlags.Inverse;
|
||||
Phases.Clear();
|
||||
NonCosmeticReferences = 0;
|
||||
CosmeticReferences = 0;
|
||||
DefaultReferences = 0;
|
||||
UpdateUnphasedFlag();
|
||||
}
|
||||
|
||||
public bool CanSee(PhaseShift other)
|
||||
{
|
||||
if (Flags.HasFlag(PhaseShiftFlags.Unphased) && other.Flags.HasFlag(PhaseShiftFlags.Unphased))
|
||||
return true;
|
||||
if (Flags.HasFlag(PhaseShiftFlags.AlwaysVisible) || other.Flags.HasFlag(PhaseShiftFlags.AlwaysVisible))
|
||||
return true;
|
||||
if (Flags.HasFlag(PhaseShiftFlags.Inverse) && other.Flags.HasFlag(PhaseShiftFlags.Inverse))
|
||||
return true;
|
||||
|
||||
PhaseFlags excludePhasesWithFlag = PhaseFlags.None;
|
||||
if (Flags.HasFlag(PhaseShiftFlags.NoCosmetic) && other.Flags.HasFlag(PhaseShiftFlags.NoCosmetic))
|
||||
excludePhasesWithFlag = PhaseFlags.Cosmetic;
|
||||
|
||||
if (!Flags.HasFlag(PhaseShiftFlags.Inverse) && !other.Flags.HasFlag(PhaseShiftFlags.Inverse))
|
||||
{
|
||||
ObjectGuid ownerGuid = PersonalGuid;
|
||||
ObjectGuid otherPersonalGuid = other.PersonalGuid;
|
||||
return Phases.Intersect(other.Phases, (myPhase, otherPhase) =>
|
||||
{
|
||||
return !myPhase.Flags.HasAnyFlag(excludePhasesWithFlag) && (!myPhase.Flags.HasFlag(PhaseFlags.Personal) || ownerGuid == otherPersonalGuid);
|
||||
}).Any();
|
||||
}
|
||||
|
||||
var checkInversePhaseShift = new Func<PhaseShift, PhaseShift, bool>((phaseShift, excludedPhaseShift) =>
|
||||
{
|
||||
if (phaseShift.Flags.HasFlag(PhaseShiftFlags.Unphased) && !excludedPhaseShift.Flags.HasFlag(PhaseShiftFlags.InverseUnphased))
|
||||
return true;
|
||||
|
||||
foreach (var itr in phaseShift.Phases)
|
||||
{
|
||||
if (itr.Flags.HasAnyFlag(excludePhasesWithFlag))
|
||||
continue;
|
||||
|
||||
var index = excludedPhaseShift.Phases.IndexOf(itr);
|
||||
if (index == -1 || excludedPhaseShift.Phases[index].Flags.HasAnyFlag(excludePhasesWithFlag))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (other.Flags.HasFlag(PhaseShiftFlags.Inverse))
|
||||
return checkInversePhaseShift(this, other);
|
||||
|
||||
return checkInversePhaseShift(other, this);
|
||||
}
|
||||
|
||||
public void ModifyPhasesReferences(PhaseRef phaseRef, int references)
|
||||
{
|
||||
phaseRef.References += references;
|
||||
|
||||
if (!IsDbPhaseShift)
|
||||
{
|
||||
if (phaseRef.Flags.HasAnyFlag(PhaseFlags.Cosmetic))
|
||||
CosmeticReferences += references;
|
||||
else if (phaseRef.Id != 169)
|
||||
NonCosmeticReferences += references;
|
||||
else
|
||||
DefaultReferences += references;
|
||||
|
||||
if (CosmeticReferences != 0)
|
||||
Flags |= PhaseShiftFlags.NoCosmetic;
|
||||
else
|
||||
Flags &= ~PhaseShiftFlags.NoCosmetic;
|
||||
|
||||
UpdateUnphasedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateUnphasedFlag()
|
||||
{
|
||||
PhaseShiftFlags unphasedFlag = !Flags.HasAnyFlag(PhaseShiftFlags.Inverse) ? PhaseShiftFlags.Unphased : PhaseShiftFlags.InverseUnphased;
|
||||
Flags &= ~(!Flags.HasFlag(PhaseShiftFlags.Inverse) ? PhaseShiftFlags.InverseUnphased : PhaseShiftFlags.Unphased);
|
||||
if (NonCosmeticReferences != 0 && DefaultReferences == 0)
|
||||
Flags &= ~unphasedFlag;
|
||||
else
|
||||
Flags |= unphasedFlag;
|
||||
}
|
||||
|
||||
public bool HasPhase(uint phaseId) { return Phases.Contains(new PhaseRef(phaseId, PhaseFlags.None, null)); }
|
||||
public List<PhaseRef> GetPhases() { return Phases; }
|
||||
|
||||
public bool HasVisibleMapId(uint visibleMapId) { return VisibleMapIds.ContainsKey(visibleMapId); }
|
||||
public Dictionary<uint, VisibleMapIdRef> GetVisibleMapIds() { return VisibleMapIds; }
|
||||
|
||||
public bool HasUiWorldMapAreaIdSwap(uint uiWorldMapAreaId) { return UiWorldMapAreaIdSwaps.ContainsKey(uiWorldMapAreaId); }
|
||||
public Dictionary<uint, UiWorldMapAreaIdSwapRef> GetUiWorldMapAreaIdSwaps() { return UiWorldMapAreaIdSwaps; }
|
||||
|
||||
public PhaseShiftFlags Flags = PhaseShiftFlags.Unphased;
|
||||
public ObjectGuid PersonalGuid;
|
||||
public List<PhaseRef> Phases = new List<PhaseRef>();
|
||||
public Dictionary<uint, VisibleMapIdRef> VisibleMapIds = new Dictionary<uint, VisibleMapIdRef>();
|
||||
public Dictionary<uint, UiWorldMapAreaIdSwapRef> UiWorldMapAreaIdSwaps = new Dictionary<uint, UiWorldMapAreaIdSwapRef>();
|
||||
|
||||
int NonCosmeticReferences;
|
||||
int CosmeticReferences;
|
||||
int DefaultReferences;
|
||||
public bool IsDbPhaseShift;
|
||||
}
|
||||
|
||||
public struct PhaseRef
|
||||
{
|
||||
public PhaseRef(uint id, PhaseFlags flags, List<Condition> conditions)
|
||||
{
|
||||
Id = id;
|
||||
Flags = flags;
|
||||
References = 0;
|
||||
AreaConditions = conditions;
|
||||
}
|
||||
|
||||
public uint Id;
|
||||
public PhaseFlags Flags;
|
||||
public int References;
|
||||
public List<Condition> AreaConditions;
|
||||
|
||||
public static bool operator <(PhaseRef left, PhaseRef right)
|
||||
{
|
||||
return left.Id < right.Id;
|
||||
}
|
||||
|
||||
public static bool operator >(PhaseRef left, PhaseRef right)
|
||||
{
|
||||
return left.Id > right.Id;
|
||||
}
|
||||
|
||||
public static bool operator ==(PhaseRef left, PhaseRef right) { return left.Id == right.Id; }
|
||||
public static bool operator !=(PhaseRef left, PhaseRef right) { return !(left == right); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return base.Equals(obj);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public struct VisibleMapIdRef
|
||||
{
|
||||
public VisibleMapIdRef(int references, TerrainSwapInfo visibleMapInfo)
|
||||
{
|
||||
References = references;
|
||||
VisibleMapInfo = visibleMapInfo;
|
||||
}
|
||||
|
||||
public int References;
|
||||
public TerrainSwapInfo VisibleMapInfo;
|
||||
}
|
||||
|
||||
public struct UiWorldMapAreaIdSwapRef
|
||||
{
|
||||
public UiWorldMapAreaIdSwapRef(int references)
|
||||
{
|
||||
References = references;
|
||||
}
|
||||
|
||||
public int References;
|
||||
}
|
||||
|
||||
public enum PhaseShiftFlags
|
||||
{
|
||||
None = 0x00,
|
||||
AlwaysVisible = 0x01, // Ignores all phasing, can see everything and be seen by everything
|
||||
Inverse = 0x02, // By default having at least one shared phase for two objects means they can see each other
|
||||
// this flag makes objects see each other if they have at least one non-shared phase
|
||||
InverseUnphased = 0x04,
|
||||
Unphased = 0x08,
|
||||
NoCosmetic = 0x10 // This flag ignores shared cosmetic phases (two players that both have shared cosmetic phase but no other phase cannot see each other)
|
||||
}
|
||||
|
||||
public enum PhaseFlags : ushort
|
||||
{
|
||||
None = 0x0,
|
||||
Cosmetic = 0x1,
|
||||
Personal = 0x2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,573 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Framework.Constants;
|
||||
using Game.Conditions;
|
||||
using Game.Spells;
|
||||
using System.Linq;
|
||||
using Game.Network.Packets;
|
||||
using Game.Chat;
|
||||
using Game.Maps;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public class PhasingHandler
|
||||
{
|
||||
public static PhaseShift EmptyPhaseShift = new PhaseShift();
|
||||
|
||||
public static PhaseFlags GetPhaseFlags(uint phaseId)
|
||||
{
|
||||
PhaseRecord phase = CliDB.PhaseStorage.LookupByKey(phaseId);
|
||||
if (phase != null)
|
||||
{
|
||||
if (phase.Flags.HasAnyFlag(PhaseEntryFlags.Cosmetic))
|
||||
return PhaseFlags.Cosmetic;
|
||||
|
||||
if (phase.Flags.HasAnyFlag(PhaseEntryFlags.Personal))
|
||||
return PhaseFlags.Personal;
|
||||
}
|
||||
|
||||
return PhaseFlags.None;
|
||||
}
|
||||
|
||||
public static void ForAllControlled(Unit unit, Action<Unit> func)
|
||||
{
|
||||
foreach (Unit controlled in unit.m_Controlled)
|
||||
if (controlled.GetTypeId() != TypeId.Player)
|
||||
func(controlled);
|
||||
|
||||
for (byte i = 0; i < SharedConst.MaxSummonSlot; ++i)
|
||||
{
|
||||
if (!unit.m_SummonSlot[i].IsEmpty())
|
||||
{
|
||||
Creature summon = unit.GetMap().GetCreature(unit.m_SummonSlot[i]);
|
||||
if (summon)
|
||||
func(summon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddPhase(WorldObject obj, uint phaseId, bool updateVisibility)
|
||||
{
|
||||
bool changed = obj.GetPhaseShift().AddPhase(phaseId, GetPhaseFlags(phaseId), null);
|
||||
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
unit.OnPhaseChange();
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
AddPhase(controlled, phaseId, updateVisibility);
|
||||
});
|
||||
unit.RemoveNotOwnSingleTargetAuras(true);
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, updateVisibility, changed);
|
||||
}
|
||||
|
||||
public static void RemovePhase(WorldObject obj, uint phaseId, bool updateVisibility)
|
||||
{
|
||||
bool changed = obj.GetPhaseShift().RemovePhase(phaseId);
|
||||
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
unit.OnPhaseChange();
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
RemovePhase(controlled, phaseId, updateVisibility);
|
||||
});
|
||||
unit.RemoveNotOwnSingleTargetAuras(true);
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, updateVisibility, changed);
|
||||
}
|
||||
|
||||
public static void AddPhaseGroup(WorldObject obj, uint phaseGroupId, bool updateVisibility)
|
||||
{
|
||||
var phasesInGroup = Global.DB2Mgr.GetPhasesForGroup(phaseGroupId);
|
||||
if (phasesInGroup.Empty())
|
||||
return;
|
||||
|
||||
bool changed = false;
|
||||
foreach (uint phaseId in phasesInGroup)
|
||||
changed = obj.GetPhaseShift().AddPhase(phaseId, GetPhaseFlags(phaseId), null) || changed;
|
||||
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
unit.OnPhaseChange();
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
AddPhaseGroup(controlled, phaseGroupId, updateVisibility);
|
||||
});
|
||||
unit.RemoveNotOwnSingleTargetAuras(true);
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, updateVisibility, changed);
|
||||
}
|
||||
|
||||
public static void RemovePhaseGroup(WorldObject obj, uint phaseGroupId, bool updateVisibility)
|
||||
{
|
||||
var phasesInGroup = Global.DB2Mgr.GetPhasesForGroup(phaseGroupId);
|
||||
if (phasesInGroup.Empty())
|
||||
return;
|
||||
|
||||
bool changed = false;
|
||||
foreach (uint phaseId in phasesInGroup)
|
||||
changed = obj.GetPhaseShift().RemovePhase(phaseId) || changed;
|
||||
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
unit.OnPhaseChange();
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
RemovePhaseGroup(controlled, phaseGroupId, updateVisibility);
|
||||
});
|
||||
unit.RemoveNotOwnSingleTargetAuras(true);
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, updateVisibility, changed);
|
||||
}
|
||||
|
||||
public static void AddVisibleMapId(WorldObject obj, uint visibleMapId)
|
||||
{
|
||||
TerrainSwapInfo terrainSwapInfo = Global.ObjectMgr.GetTerrainSwapInfo(visibleMapId);
|
||||
bool changed = obj.GetPhaseShift().AddVisibleMapId(visibleMapId, terrainSwapInfo);
|
||||
|
||||
foreach (uint uiWorldMapAreaIDSwap in terrainSwapInfo.UiWorldMapAreaIDSwaps)
|
||||
changed = obj.GetPhaseShift().AddUiWorldMapAreaIdSwap(uiWorldMapAreaIDSwap) || changed;
|
||||
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
AddVisibleMapId(controlled, visibleMapId);
|
||||
});
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, false, changed);
|
||||
}
|
||||
|
||||
public static void RemoveVisibleMapId(WorldObject obj, uint visibleMapId)
|
||||
{
|
||||
TerrainSwapInfo terrainSwapInfo = Global.ObjectMgr.GetTerrainSwapInfo(visibleMapId);
|
||||
bool changed = obj.GetPhaseShift().RemoveVisibleMapId(visibleMapId);
|
||||
|
||||
foreach (uint uiWorldMapAreaIDSwap in terrainSwapInfo.UiWorldMapAreaIDSwaps)
|
||||
changed = obj.GetPhaseShift().RemoveUiWorldMapAreaIdSwap(uiWorldMapAreaIDSwap) || changed;
|
||||
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
RemoveVisibleMapId(controlled, visibleMapId);
|
||||
});
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, false, changed);
|
||||
}
|
||||
|
||||
public static void ResetPhaseShift(WorldObject obj)
|
||||
{
|
||||
obj.GetPhaseShift().Clear();
|
||||
obj.GetSuppressedPhaseShift().Clear();
|
||||
}
|
||||
|
||||
public static void InheritPhaseShift(WorldObject target, WorldObject source)
|
||||
{
|
||||
target.SetPhaseShift(source.GetPhaseShift());
|
||||
target.SetSuppressedPhaseShift(source.GetSuppressedPhaseShift());
|
||||
}
|
||||
|
||||
public static void OnMapChange(WorldObject obj)
|
||||
{
|
||||
PhaseShift phaseShift = obj.GetPhaseShift();
|
||||
PhaseShift suppressedPhaseShift = obj.GetSuppressedPhaseShift();
|
||||
ConditionSourceInfo srcInfo = new ConditionSourceInfo(obj);
|
||||
|
||||
obj.GetPhaseShift().VisibleMapIds.Clear();
|
||||
obj.GetPhaseShift().UiWorldMapAreaIdSwaps.Clear();
|
||||
obj.GetSuppressedPhaseShift().VisibleMapIds.Clear();
|
||||
|
||||
var visibleMapIds = Global.ObjectMgr.GetTerrainSwapsForMap(obj.GetMapId());
|
||||
if (!visibleMapIds.Empty())
|
||||
{
|
||||
foreach (TerrainSwapInfo visibleMapInfo in visibleMapIds)
|
||||
{
|
||||
if (Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.TerrainSwap, visibleMapInfo.Id, srcInfo))
|
||||
{
|
||||
phaseShift.AddVisibleMapId(visibleMapInfo.Id, visibleMapInfo);
|
||||
foreach (uint uiWorldMapAreaIdSwap in visibleMapInfo.UiWorldMapAreaIDSwaps)
|
||||
phaseShift.AddUiWorldMapAreaIdSwap(uiWorldMapAreaIdSwap);
|
||||
}
|
||||
else
|
||||
suppressedPhaseShift.AddVisibleMapId(visibleMapInfo.Id, visibleMapInfo);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, false, true);
|
||||
}
|
||||
|
||||
public static void OnAreaChange(WorldObject obj)
|
||||
{
|
||||
PhaseShift phaseShift = obj.GetPhaseShift();
|
||||
PhaseShift suppressedPhaseShift = obj.GetSuppressedPhaseShift();
|
||||
var oldPhases = phaseShift.GetPhases(); // for comparison
|
||||
ConditionSourceInfo srcInfo = new ConditionSourceInfo(obj);
|
||||
|
||||
obj.GetPhaseShift().ClearPhases();
|
||||
obj.GetSuppressedPhaseShift().ClearPhases();
|
||||
|
||||
uint areaId = obj.GetAreaId();
|
||||
AreaTableRecord areaEntry = CliDB.AreaTableStorage.LookupByKey(areaId);
|
||||
while (areaEntry != null)
|
||||
{
|
||||
var newAreaPhases = Global.ObjectMgr.GetPhasesForArea(areaEntry.Id);
|
||||
if (!newAreaPhases.Empty())
|
||||
{
|
||||
foreach (PhaseAreaInfo phaseArea in newAreaPhases)
|
||||
{
|
||||
if (phaseArea.SubAreaExclusions.Contains(areaId))
|
||||
continue;
|
||||
|
||||
uint phaseId = phaseArea.PhaseInfo.Id;
|
||||
if (Global.ConditionMgr.IsObjectMeetToConditions(srcInfo, phaseArea.Conditions))
|
||||
phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), phaseArea.Conditions);
|
||||
else
|
||||
suppressedPhaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), phaseArea.Conditions);
|
||||
}
|
||||
}
|
||||
|
||||
areaEntry = CliDB.AreaTableStorage.LookupByKey(areaEntry.ParentAreaID);
|
||||
}
|
||||
|
||||
bool changed = phaseShift.GetPhases() != oldPhases;
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
foreach (AuraEffect aurEff in unit.GetAuraEffectsByType(AuraType.Phase))
|
||||
{
|
||||
uint phaseId = (uint)aurEff.GetMiscValueB();
|
||||
changed = phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), null) || changed;
|
||||
}
|
||||
|
||||
foreach (AuraEffect aurEff in unit.GetAuraEffectsByType(AuraType.PhaseGroup))
|
||||
{
|
||||
var phasesInGroup = Global.DB2Mgr.GetPhasesForGroup((uint)aurEff.GetMiscValueB());
|
||||
foreach (uint phaseId in phasesInGroup)
|
||||
changed = phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), null) || changed;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
unit.OnPhaseChange();
|
||||
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
InheritPhaseShift(controlled, unit);
|
||||
});
|
||||
|
||||
if (changed)
|
||||
unit.RemoveNotOwnSingleTargetAuras(true);
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, true, changed);
|
||||
}
|
||||
|
||||
public static void OnConditionChange(WorldObject obj)
|
||||
{
|
||||
PhaseShift phaseShift = obj.GetPhaseShift();
|
||||
PhaseShift suppressedPhaseShift = obj.GetSuppressedPhaseShift();
|
||||
PhaseShift newSuppressions = new PhaseShift();
|
||||
ConditionSourceInfo srcInfo = new ConditionSourceInfo(obj);
|
||||
bool changed = false;
|
||||
|
||||
foreach (var phaseRef in phaseShift.Phases.ToArray())
|
||||
{
|
||||
if (!phaseRef.AreaConditions.Empty() && !Global.ConditionMgr.IsObjectMeetToConditions(srcInfo, phaseRef.AreaConditions))
|
||||
{
|
||||
newSuppressions.AddPhase(phaseRef.Id, phaseRef.Flags, phaseRef.AreaConditions, phaseRef.References);
|
||||
phaseShift.Phases.Remove(phaseRef);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var phaseRef in suppressedPhaseShift.Phases.ToArray())
|
||||
{
|
||||
if (Global.ConditionMgr.IsObjectMeetToConditions(srcInfo, phaseRef.AreaConditions))
|
||||
{
|
||||
changed = phaseShift.AddPhase(phaseRef.Id, phaseRef.Flags, phaseRef.AreaConditions, phaseRef.References) || changed;
|
||||
suppressedPhaseShift.Phases.Remove(phaseRef);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pair in phaseShift.VisibleMapIds.ToList())
|
||||
{
|
||||
if (!Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.TerrainSwap, pair.Key, srcInfo))
|
||||
{
|
||||
newSuppressions.AddVisibleMapId(pair.Key, pair.Value.VisibleMapInfo, pair.Value.References);
|
||||
foreach (uint uiWorldMapAreaIdSwap in pair.Value.VisibleMapInfo.UiWorldMapAreaIDSwaps)
|
||||
changed = phaseShift.RemoveUiWorldMapAreaIdSwap(uiWorldMapAreaIdSwap) || changed;
|
||||
|
||||
phaseShift.VisibleMapIds.Remove(pair.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var pair in suppressedPhaseShift.VisibleMapIds.ToList())
|
||||
{
|
||||
if (Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.TerrainSwap, pair.Key, srcInfo))
|
||||
{
|
||||
changed = phaseShift.AddVisibleMapId(pair.Key, pair.Value.VisibleMapInfo, pair.Value.References) || changed;
|
||||
foreach (uint uiWorldMapAreaIdSwap in pair.Value.VisibleMapInfo.UiWorldMapAreaIDSwaps)
|
||||
changed = phaseShift.AddUiWorldMapAreaIdSwap(uiWorldMapAreaIdSwap) || changed;
|
||||
|
||||
suppressedPhaseShift.VisibleMapIds.Remove(pair.Key);
|
||||
}
|
||||
}
|
||||
|
||||
Unit unit = obj.ToUnit();
|
||||
if (unit)
|
||||
{
|
||||
foreach (AuraEffect aurEff in unit.GetAuraEffectsByType(AuraType.Phase))
|
||||
{
|
||||
uint phaseId = (uint)aurEff.GetMiscValueB();
|
||||
var eraseResult = newSuppressions.RemovePhase(phaseId);
|
||||
// if condition was met previously there is nothing to erase
|
||||
if (newSuppressions.RemovePhase(phaseId))
|
||||
phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), null);//todo needs checked
|
||||
}
|
||||
|
||||
foreach (AuraEffect aurEff in unit.GetAuraEffectsByType(AuraType.PhaseGroup))
|
||||
{
|
||||
var phasesInGroup = Global.DB2Mgr.GetPhasesForGroup((uint)aurEff.GetMiscValueB());
|
||||
if (!phasesInGroup.Empty())
|
||||
{
|
||||
foreach (uint phaseId in phasesInGroup)
|
||||
{
|
||||
var eraseResult = newSuppressions.RemovePhase(phaseId);
|
||||
// if condition was met previously there is nothing to erase
|
||||
if (eraseResult)
|
||||
phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
changed = changed || !newSuppressions.Phases.Empty() || !newSuppressions.VisibleMapIds.Empty();
|
||||
foreach (var phaseRef in newSuppressions.Phases)
|
||||
suppressedPhaseShift.AddPhase(phaseRef.Id, phaseRef.Flags, phaseRef.AreaConditions, phaseRef.References);
|
||||
|
||||
foreach (var pair in newSuppressions.VisibleMapIds)
|
||||
suppressedPhaseShift.AddVisibleMapId(pair.Key, pair.Value.VisibleMapInfo, pair.Value.References);
|
||||
|
||||
if (unit)
|
||||
{
|
||||
if (changed)
|
||||
unit.OnPhaseChange();
|
||||
|
||||
ForAllControlled(unit, controlled =>
|
||||
{
|
||||
InheritPhaseShift(controlled, unit);
|
||||
});
|
||||
|
||||
if (changed)
|
||||
unit.RemoveNotOwnSingleTargetAuras(true);
|
||||
}
|
||||
|
||||
UpdateVisibilityIfNeeded(obj, true, changed);
|
||||
}
|
||||
|
||||
public static void SendToPlayer(Player player, PhaseShift phaseShift)
|
||||
{
|
||||
PhaseShiftChange phaseShiftChange = new PhaseShiftChange();
|
||||
phaseShiftChange.Client = player.GetGUID();
|
||||
phaseShiftChange.Phaseshift.PhaseShiftFlags = (uint)phaseShift.Flags;
|
||||
phaseShiftChange.Phaseshift.PersonalGUID = phaseShift.PersonalGuid;
|
||||
|
||||
foreach (var phaseRef in phaseShift.Phases)
|
||||
phaseShiftChange.Phaseshift.Phases.Add(new PhaseShiftDataPhase((uint)phaseRef.Flags, phaseRef.Id));
|
||||
|
||||
foreach (var visibleMapId in phaseShift.VisibleMapIds)
|
||||
phaseShiftChange.VisibleMapIDs.Add((ushort)visibleMapId.Key);
|
||||
|
||||
foreach (var uiWorldMapAreaIdSwap in phaseShift.UiWorldMapAreaIdSwaps)
|
||||
phaseShiftChange.UiWorldMapAreaIDSwaps.Add((ushort)uiWorldMapAreaIdSwap.Key);
|
||||
|
||||
player.SendPacket(phaseShiftChange);
|
||||
}
|
||||
|
||||
public static void SendToPlayer(Player player)
|
||||
{
|
||||
SendToPlayer(player, player.GetPhaseShift());
|
||||
}
|
||||
|
||||
public static void FillPartyMemberPhase(PartyMemberPhaseStates partyMemberPhases, PhaseShift phaseShift)
|
||||
{
|
||||
partyMemberPhases.PhaseShiftFlags = (int)phaseShift.Flags;
|
||||
partyMemberPhases.PersonalGUID = phaseShift.PersonalGuid;
|
||||
|
||||
foreach (var phase in phaseShift.Phases)
|
||||
partyMemberPhases.List.Add(new PartyMemberPhase((uint)phase.Flags, phase.Id));
|
||||
}
|
||||
|
||||
public static void InitDbPhaseShift(PhaseShift phaseShift, PhaseUseFlagsValues phaseUseFlags, uint phaseId, uint phaseGroupId)
|
||||
{
|
||||
phaseShift.ClearPhases();
|
||||
phaseShift.IsDbPhaseShift = true;
|
||||
|
||||
PhaseShiftFlags flags = PhaseShiftFlags.None;
|
||||
if (phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.AlwaysVisible))
|
||||
flags = flags | PhaseShiftFlags.AlwaysVisible | PhaseShiftFlags.Unphased;
|
||||
if (phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.Inverse))
|
||||
flags |= PhaseShiftFlags.Inverse;
|
||||
|
||||
if (phaseId != 0)
|
||||
phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), null);
|
||||
else
|
||||
{
|
||||
var phasesInGroup = Global.DB2Mgr.GetPhasesForGroup(phaseGroupId);
|
||||
foreach (uint phaseInGroup in phasesInGroup)
|
||||
phaseShift.AddPhase(phaseInGroup, GetPhaseFlags(phaseInGroup), null);
|
||||
}
|
||||
|
||||
if (phaseShift.Phases.Empty() || phaseShift.HasPhase(169))
|
||||
{
|
||||
if (flags.HasFlag(PhaseShiftFlags.Inverse))
|
||||
flags |= PhaseShiftFlags.InverseUnphased;
|
||||
else
|
||||
flags |= PhaseShiftFlags.Unphased;
|
||||
}
|
||||
|
||||
phaseShift.Flags = flags;
|
||||
}
|
||||
|
||||
public static void InitDbVisibleMapId(PhaseShift phaseShift, int visibleMapId)
|
||||
{
|
||||
phaseShift.VisibleMapIds.Clear();
|
||||
if (visibleMapId != -1)
|
||||
phaseShift.AddVisibleMapId((uint)visibleMapId, Global.ObjectMgr.GetTerrainSwapInfo((uint)visibleMapId));
|
||||
}
|
||||
|
||||
public static bool InDbPhaseShift(WorldObject obj, PhaseUseFlagsValues phaseUseFlags, ushort phaseId, uint phaseGroupId)
|
||||
{
|
||||
PhaseShift phaseShift = new PhaseShift();
|
||||
InitDbPhaseShift(phaseShift, phaseUseFlags, phaseId, phaseGroupId);
|
||||
return obj.GetPhaseShift().CanSee(phaseShift);
|
||||
}
|
||||
|
||||
public static uint GetTerrainMapId(PhaseShift phaseShift, Map map, float x, float y)
|
||||
{
|
||||
if (phaseShift.VisibleMapIds.Empty())
|
||||
return map.GetId();
|
||||
|
||||
if (phaseShift.VisibleMapIds.Count == 1)
|
||||
return phaseShift.VisibleMapIds.First().Key;
|
||||
|
||||
GridCoord gridCoord = GridDefines.ComputeGridCoord(x, y);
|
||||
uint gx = (uint)((MapConst.MaxGrids - 1) - gridCoord.x_coord);
|
||||
uint gy = (uint)((MapConst.MaxGrids - 1) - gridCoord.y_coord);
|
||||
|
||||
uint gxbegin = Math.Max(gx - 1, 0);
|
||||
uint gxend = Math.Min(gx + 1, MapConst.MaxGrids);
|
||||
uint gybegin = Math.Max(gy - 1, 0);
|
||||
uint gyend = Math.Min(gy + 1, MapConst.MaxGrids);
|
||||
|
||||
foreach (var itr in phaseShift.VisibleMapIds)
|
||||
for (uint gxi = gxbegin; gxi < gxend; ++gxi)
|
||||
for (uint gyi = gybegin; gyi < gyend; ++gyi)
|
||||
if (map.HasGridMap(itr.Key, gxi, gyi))
|
||||
return itr.Key;
|
||||
|
||||
return map.GetId();
|
||||
}
|
||||
|
||||
public static void SetAlwaysVisible(PhaseShift phaseShift, bool apply)
|
||||
{
|
||||
if (apply)
|
||||
phaseShift.Flags |= PhaseShiftFlags.AlwaysVisible;
|
||||
else
|
||||
phaseShift.Flags &= ~PhaseShiftFlags.AlwaysVisible;
|
||||
}
|
||||
|
||||
public static void SetInversed(PhaseShift phaseShift, bool apply)
|
||||
{
|
||||
if (apply)
|
||||
phaseShift.Flags |= PhaseShiftFlags.Inverse;
|
||||
else
|
||||
phaseShift.Flags &= ~PhaseShiftFlags.Inverse;
|
||||
|
||||
phaseShift.UpdateUnphasedFlag();
|
||||
}
|
||||
|
||||
public static void PrintToChat(CommandHandler chat, PhaseShift phaseShift)
|
||||
{
|
||||
chat.SendSysMessage(CypherStrings.PhaseshiftStatus, phaseShift.Flags, phaseShift.PersonalGuid.ToString());
|
||||
if (!phaseShift.Phases.Empty())
|
||||
{
|
||||
StringBuilder phases = new StringBuilder();
|
||||
string cosmetic = Global.ObjectMgr.GetCypherString(CypherStrings.PhaseFlagCosmetic, chat.GetSessionDbcLocale());
|
||||
string personal = Global.ObjectMgr.GetCypherString(CypherStrings.PhaseFlagPersonal, chat.GetSessionDbcLocale());
|
||||
foreach (PhaseRef phase in phaseShift.Phases)
|
||||
{
|
||||
phases.Append(phase.Id);
|
||||
if (phase.Flags.HasFlag(PhaseFlags.Cosmetic))
|
||||
phases.Append(' ' + '(' + cosmetic + ')');
|
||||
if (phase.Flags.HasFlag(PhaseFlags.Personal))
|
||||
phases.Append(' ' + '(' + personal + ')');
|
||||
phases.Append(", ");
|
||||
}
|
||||
|
||||
chat.SendSysMessage(CypherStrings.PhaseshiftPhases, phases.ToString());
|
||||
}
|
||||
|
||||
if (!phaseShift.VisibleMapIds.Empty())
|
||||
{
|
||||
StringBuilder visibleMapIds = new StringBuilder();
|
||||
foreach (var visibleMapId in phaseShift.VisibleMapIds)
|
||||
visibleMapIds.Append(visibleMapId.Key + ',' + ' ');
|
||||
|
||||
chat.SendSysMessage(CypherStrings.PhaseshiftVisibleMapIds, visibleMapIds.ToString());
|
||||
}
|
||||
|
||||
if (!phaseShift.UiWorldMapAreaIdSwaps.Empty())
|
||||
{
|
||||
StringBuilder uiWorldMapAreaIdSwaps = new StringBuilder();
|
||||
foreach (var uiWorldMapAreaIdSwap in phaseShift.UiWorldMapAreaIdSwaps)
|
||||
uiWorldMapAreaIdSwaps.Append(uiWorldMapAreaIdSwap.Key + ',' + ' ');
|
||||
|
||||
chat.SendSysMessage(CypherStrings.PhaseshiftUiWorldMapAreaSwaps, uiWorldMapAreaIdSwaps.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatPhases(PhaseShift phaseShift)
|
||||
{
|
||||
StringBuilder phases = new StringBuilder();
|
||||
foreach (var phase in phaseShift.Phases)
|
||||
phases.Append(phase.Id + ',');
|
||||
|
||||
return phases.ToString();
|
||||
}
|
||||
|
||||
static void UpdateVisibilityIfNeeded(WorldObject obj, bool updateVisibility, bool changed)
|
||||
{
|
||||
if (changed && obj.IsInWorld)
|
||||
{
|
||||
Player player = obj.ToPlayer();
|
||||
if (player)
|
||||
SendToPlayer(player);
|
||||
|
||||
if (updateVisibility)
|
||||
{
|
||||
if (player)
|
||||
player.GetMap().SendUpdateTransportVisibility(player);
|
||||
|
||||
obj.UpdateObjectVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,6 +357,18 @@ namespace Game
|
||||
//Load weighted graph on taxi nodes path
|
||||
Global.TaxiPathGraph.Initialize();
|
||||
|
||||
MultiMap<uint, uint> mapData = new MultiMap<uint, uint>();
|
||||
foreach (MapRecord mapEntry in CliDB.MapStorage.Values)
|
||||
{
|
||||
if (mapEntry.ParentMapID != -1)
|
||||
mapData.Add((uint)mapEntry.ParentMapID, mapEntry.Id);
|
||||
}
|
||||
|
||||
Global.MapMgr.InitializeParentMapData(mapData);
|
||||
|
||||
Global.VMapMgr.Initialize(mapData);
|
||||
Global.MMapMgr.Initialize(mapData);
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading SpellInfo Storage...");
|
||||
Global.SpellMgr.LoadSpellInfoStore();
|
||||
|
||||
@@ -742,17 +754,7 @@ namespace Game
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading World States..."); // must be loaded before Battleground, outdoor PvP and conditions
|
||||
LoadWorldStates();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Terrain Phase definitions...");
|
||||
Global.ObjectMgr.LoadTerrainPhaseInfo();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Terrain Swap Default definitions...");
|
||||
Global.ObjectMgr.LoadTerrainSwapDefaults();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Terrain World Map definitions...");
|
||||
Global.ObjectMgr.LoadTerrainWorldMaps();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Phase Area definitions...");
|
||||
Global.ObjectMgr.LoadAreaPhases();
|
||||
Global.ObjectMgr.LoadPhases();
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Conditions...");
|
||||
Global.ConditionMgr.LoadConditions();
|
||||
|
||||
@@ -1283,28 +1283,17 @@ namespace Game.Spells
|
||||
|
||||
Unit target = aurApp.GetTarget();
|
||||
|
||||
var oldPhases = target.GetPhases();
|
||||
target.SetInPhase((uint)GetMiscValueB(), false, apply);
|
||||
|
||||
// call functions which may have additional effects after chainging state of unit
|
||||
// phase auras normally not expected at BG but anyway better check
|
||||
if (apply)
|
||||
{
|
||||
PhasingHandler.AddPhase(target, (uint)GetMiscValueB(), true);
|
||||
|
||||
// call functions which may have additional effects after chainging state of unit
|
||||
// phase auras normally not expected at BG but anyway better check
|
||||
// drop flag at invisibiliy in bg
|
||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.ImmuneOrLostSelection);
|
||||
}
|
||||
|
||||
Player player = target.ToPlayer();
|
||||
if (player)
|
||||
{
|
||||
if (player.IsInWorld)
|
||||
player.GetMap().SendUpdateTransportVisibility(player, oldPhases);
|
||||
player.SendUpdatePhasing();
|
||||
}
|
||||
|
||||
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
|
||||
if (target.IsVisible())
|
||||
target.UpdateObjectVisibility();
|
||||
else
|
||||
PhasingHandler.RemovePhase(target, (uint)GetMiscValueB(), true);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.PhaseGroup)]
|
||||
@@ -1314,29 +1303,18 @@ namespace Game.Spells
|
||||
return;
|
||||
|
||||
Unit target = aurApp.GetTarget();
|
||||
var oldPhases = target.GetPhases();
|
||||
var phases = Global.DB2Mgr.GetPhasesForGroup((uint)GetMiscValueB());
|
||||
foreach (var phase in phases)
|
||||
target.SetInPhase(phase, false, apply);
|
||||
// call functions which may have additional effects after chainging state of unit
|
||||
// phase auras normally not expected at BG but anyway better check
|
||||
|
||||
if (apply)
|
||||
{
|
||||
PhasingHandler.AddPhaseGroup(target, (uint)GetMiscValueB(), true);
|
||||
|
||||
// call functions which may have additional effects after chainging state of unit
|
||||
// phase auras normally not expected at BG but anyway better check
|
||||
// drop flag at invisibiliy in bg
|
||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.ImmuneOrLostSelection);
|
||||
}
|
||||
|
||||
Player player = target.ToPlayer();
|
||||
if (player)
|
||||
{
|
||||
if (player.IsInWorld)
|
||||
player.GetMap().SendUpdateTransportVisibility(player, oldPhases);
|
||||
player.SendUpdatePhasing();
|
||||
}
|
||||
|
||||
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
|
||||
if (target.IsVisible())
|
||||
target.UpdateObjectVisibility();
|
||||
else
|
||||
PhasingHandler.RemovePhaseGroup(target, (uint)GetMiscValueB(), true);
|
||||
}
|
||||
|
||||
/**********************/
|
||||
|
||||
@@ -794,15 +794,19 @@ namespace Game.Spells
|
||||
break;
|
||||
case Targets.DestCasterFishing:
|
||||
{
|
||||
float min_dis = m_spellInfo.GetMinRange(true);
|
||||
float max_dis = m_spellInfo.GetMaxRange(true);
|
||||
float dis = (float)RandomHelper.NextDouble() * (max_dis - min_dis) + min_dis;
|
||||
float minDist = m_spellInfo.GetMinRange(true);
|
||||
float maxDist = m_spellInfo.GetMaxRange(true);
|
||||
float dis = (float)RandomHelper.NextDouble() * (maxDist - minDist) + minDist;
|
||||
float x, y, z;
|
||||
float angle = (float)RandomHelper.NextDouble() * (MathFunctions.PI * 35.0f / 180.0f) - (float)(Math.PI * 17.5f / 180.0f);
|
||||
m_caster.GetClosePoint(out x, out y, out z, SharedConst.DefaultWorldObjectSize, dis, angle);
|
||||
|
||||
float ground = z;
|
||||
float liquidLevel = m_caster.GetMap().GetWaterOrGroundLevel(m_caster.GetPhases(), x, y, z, ref ground);
|
||||
float ground = m_caster.GetMap().GetHeight(m_caster.GetPhaseShift(), x, y, z, true, 50.0f);
|
||||
float liquidLevel = MapConst.VMAPInvalidHeightValue;
|
||||
LiquidData liquidData;
|
||||
if (m_caster.GetMap().getLiquidStatus(m_caster.GetPhaseShift(), x, y, z, MapConst.MapAllLiquidTypes, out liquidData) != 0)
|
||||
liquidLevel = liquidData.level;
|
||||
|
||||
if (liquidLevel <= ground) // When there is no liquid Map.GetWaterOrGroundLevel returns ground level
|
||||
{
|
||||
SendCastResult(SpellCastResult.NotHere);
|
||||
@@ -4458,11 +4462,11 @@ namespace Game.Spells
|
||||
if (m_caster.IsTypeId(TypeId.Player) && Global.VMapMgr.isLineOfSightCalcEnabled())
|
||||
{
|
||||
if (m_spellInfo.HasAttribute(SpellAttr0.OutdoorsOnly) &&
|
||||
!m_caster.GetMap().IsOutdoors(m_caster.posX, m_caster.posY, m_caster.posZ))
|
||||
!m_caster.GetMap().IsOutdoors(m_caster.GetPhaseShift(), m_caster.posX, m_caster.posY, m_caster.posZ))
|
||||
return SpellCastResult.OnlyOutdoors;
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr0.IndoorsOnly) &&
|
||||
m_caster.GetMap().IsOutdoors(m_caster.posX, m_caster.posY, m_caster.posZ))
|
||||
m_caster.GetMap().IsOutdoors(m_caster.GetPhaseShift(), m_caster.posX, m_caster.posY, m_caster.posZ))
|
||||
return SpellCastResult.OnlyIndoors;
|
||||
}
|
||||
|
||||
|
||||
@@ -2857,7 +2857,7 @@ namespace Game.Spells
|
||||
if (!go)
|
||||
return;
|
||||
|
||||
go.CopyPhaseFrom(m_caster);
|
||||
PhasingHandler.InheritPhaseShift(go, m_caster);
|
||||
|
||||
int duration = m_spellInfo.CalcDuration(m_caster);
|
||||
|
||||
@@ -2883,7 +2883,7 @@ namespace Game.Spells
|
||||
GameObject linkedTrap = go.GetLinkedTrap();
|
||||
if (linkedTrap)
|
||||
{
|
||||
linkedTrap.CopyPhaseFrom(m_caster);
|
||||
PhasingHandler.InheritPhaseShift(linkedTrap, m_caster);
|
||||
linkedTrap.SetRespawnTime(duration > 0 ? duration / Time.InMilliseconds : 0);
|
||||
linkedTrap.SetSpellId(m_spellInfo.Id);
|
||||
|
||||
@@ -3518,7 +3518,7 @@ namespace Game.Spells
|
||||
if (!go)
|
||||
return;
|
||||
|
||||
go.CopyPhaseFrom(m_caster);
|
||||
PhasingHandler.InheritPhaseShift(go, m_caster);
|
||||
|
||||
go.SetUInt32Value(GameObjectFields.Faction, m_caster.getFaction());
|
||||
go.SetUInt32Value(GameObjectFields.Level, m_caster.getLevel() + 1);
|
||||
@@ -3858,7 +3858,7 @@ namespace Game.Spells
|
||||
if (!go)
|
||||
return;
|
||||
|
||||
go.CopyPhaseFrom(m_caster);
|
||||
PhasingHandler.InheritPhaseShift(go, m_caster);
|
||||
|
||||
int duration = m_spellInfo.CalcDuration(m_caster);
|
||||
go.SetRespawnTime(duration > 0 ? duration / Time.InMilliseconds : 0);
|
||||
@@ -4545,7 +4545,7 @@ namespace Game.Spells
|
||||
if (!go)
|
||||
return;
|
||||
|
||||
go.CopyPhaseFrom(m_caster);
|
||||
PhasingHandler.InheritPhaseShift(go, m_caster);
|
||||
|
||||
int duration = m_spellInfo.CalcDuration(m_caster);
|
||||
|
||||
@@ -4603,7 +4603,7 @@ namespace Game.Spells
|
||||
GameObject linkedTrap = go.GetLinkedTrap();
|
||||
if (linkedTrap != null)
|
||||
{
|
||||
linkedTrap.CopyPhaseFrom(m_caster);
|
||||
PhasingHandler.InheritPhaseShift(linkedTrap, m_caster);
|
||||
linkedTrap.SetRespawnTime(duration > 0 ? duration / Time.InMilliseconds : 0);
|
||||
linkedTrap.SetSpellId(m_spellInfo.Id);
|
||||
linkedTrap.SetOwnerGUID(m_caster.GetGUID());
|
||||
@@ -5656,7 +5656,7 @@ namespace Game.Spells
|
||||
if (!unitTarget || !unitTarget.IsTypeId(TypeId.Player))
|
||||
return;
|
||||
|
||||
unitTarget.UpdateAreaAndZonePhase();
|
||||
PhasingHandler.OnConditionChange(unitTarget);
|
||||
}
|
||||
|
||||
[SpellEffectHandler(SpellEffectName.UpdateZoneAurasPhases)]
|
||||
|
||||
@@ -102,23 +102,19 @@ namespace Scripts.Northrend.AzjolNerub.Ahnkahet.Amanitar
|
||||
for (byte i = 0; i < 30; ++i)
|
||||
{
|
||||
Position pos = me.GetRandomNearPosition(30.0f);
|
||||
pos.posZ = me.GetMap().GetHeight(pos.GetPositionX(), pos.GetPositionY(), MapConst.MaxHeight) + 2.0f;
|
||||
me.UpdateGroundPositionZ(pos.GetPositionX(), pos.GetPositionY(), ref pos.posZ);
|
||||
|
||||
Creature trigger = me.SummonCreature(CreatureIds.Trigger, pos);
|
||||
if (trigger)
|
||||
{
|
||||
Creature temp1 = trigger.FindNearestCreature(CreatureIds.HealthyMushroom, 4.0f, true);
|
||||
Creature temp2 = trigger.FindNearestCreature(CreatureIds.PoisonousMushroom, 4.0f, true);
|
||||
if (temp1 || temp2)
|
||||
{
|
||||
trigger.DisappearAndDie();
|
||||
}
|
||||
else
|
||||
if (!temp1 && !temp2)
|
||||
{
|
||||
u = 1 - u;
|
||||
trigger.DisappearAndDie();
|
||||
me.SummonCreature(u > 0 ? CreatureIds.PoisonousMushroom : CreatureIds.HealthyMushroom, pos, TempSummonType.TimedOrCorpseDespawn, 60 * Time.InMilliseconds);
|
||||
}
|
||||
trigger.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ using Game.Scripting;
|
||||
using Game.Spells;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Game;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.Ahnkahet.HeraldVolazj
|
||||
{
|
||||
@@ -133,7 +134,7 @@ namespace Scripts.Northrend.AzjolNerub.Ahnkahet.HeraldVolazj
|
||||
// clone
|
||||
player.CastSpell(summon, SpellIds.ClonePlayer, true);
|
||||
// phase the summon
|
||||
summon.SetInPhase((uint)spellInfo.GetEffect(0).MiscValueB, true, true);
|
||||
PhasingHandler.AddPhase(summon, (uint)spellInfo.GetEffect(0).MiscValueB, true);
|
||||
}
|
||||
}
|
||||
++insanityHandled;
|
||||
@@ -158,9 +159,9 @@ namespace Scripts.Northrend.AzjolNerub.Ahnkahet.HeraldVolazj
|
||||
instance.DoStopCriteriaTimer(CriteriaTimedTypes.Event, Misc.AchievQuickDemiseStartEvent);
|
||||
|
||||
// Visible for all players in insanity
|
||||
me.SetInPhase(169, true, true);
|
||||
for (uint i = 173; i <= 177; ++i)
|
||||
me.SetInPhase(i, true, true);
|
||||
PhasingHandler.AddPhase(me, i, false);
|
||||
PhasingHandler.AddPhase(me, 169, true);
|
||||
|
||||
ResetPlayersPhase();
|
||||
|
||||
@@ -199,7 +200,7 @@ namespace Scripts.Northrend.AzjolNerub.Ahnkahet.HeraldVolazj
|
||||
return;
|
||||
else
|
||||
{
|
||||
nextPhase = visage.GetPhases().First();
|
||||
nextPhase = visage.GetPhaseShift().GetPhases().First().Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ namespace Scripts.Northrend.Ulduar.FlameLeviathan
|
||||
{
|
||||
float x, y, z;
|
||||
me.GetPosition(out x, out y, out z);
|
||||
z = me.GetMap().GetHeight(me.GetPhases(), x, y, z);
|
||||
z = me.GetMap().GetHeight(me.GetPhaseShift(), x, y, z);
|
||||
me.GetMotionMaster().MovePoint(0, x, y, z);
|
||||
me.SetPosition(x, y, z, 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
ALTER TABLE `creature`
|
||||
ADD `phaseUseFlags` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `spawnMask`,
|
||||
ADD `terrainSwapMap` int(11) NOT NULL DEFAULT '-1' AFTER `PhaseGroup`;
|
||||
|
||||
ALTER TABLE `gameobject`
|
||||
ADD `phaseUseFlags` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `spawnMask`,
|
||||
ADD `terrainSwapMap` int(11) NOT NULL DEFAULT '-1' AFTER `PhaseGroup`;
|
||||
|
||||
DROP TABLE `terrain_phase_info`;
|
||||
|
||||
ALTER TABLE `transports` ADD `phaseUseFlags` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `name`;
|
||||
|
||||
DELETE FROM `trinity_string` WHERE `entry` IN (101,178,179,180,181,182,183,184,185);
|
||||
INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES
|
||||
(101,'Map: %u (%s) Zone: %u (%s) Area: %u (%s)\nX: %f Y: %f Z: %f Orientation: %f'),
|
||||
(178,'grid[%u,%u]cell[%u,%u] InstanceID: %u\n ZoneX: %f ZoneY: %f\nGroundZ: %f FloorZ: %f Have height data (Map: %u VMap: %u MMap: %u)'),
|
||||
(179,'PhaseShift:\n* Flags %u, PersonalGuid: %s'),
|
||||
(180,'* Phases: %s'),
|
||||
(181,'* VisibleMapIds: %s'),
|
||||
(182,'* UiWorldMapAreaSwaps: %s'),
|
||||
(183,'Cosmetic'),
|
||||
(184,'Personal');
|
||||
Reference in New Issue
Block a user