Core/Entities: Phasing rewrite

This commit is contained in:
hondacrx
2018-03-28 11:09:30 -04:00
parent caad52f636
commit fa35d60f60
72 changed files with 2254 additions and 1146 deletions
+17
View File
@@ -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.
+8 -8
View File
@@ -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
+1 -1
View File
@@ -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];
+10 -5
View File
@@ -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;
+8 -14
View File
@@ -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;
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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)
+14 -10
View File
@@ -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.");
+16 -29
View File
@@ -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;
+24 -6
View File
@@ -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;
}
+6 -19
View File
@@ -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();
+4 -4
View File
@@ -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();
+4 -4
View File
@@ -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;
}
+8 -8
View File
@@ -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())
+164 -122
View File
@@ -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;
}
+93 -43
View File
@@ -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);
+1 -1
View File
@@ -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; }
}
}
+2 -2
View File
@@ -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:
{
+23 -32
View File
@@ -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)
{
-2
View File
@@ -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)
+1 -1
View File
@@ -23,7 +23,7 @@ namespace Game.DataStorage
public sealed class PhaseRecord
{
public uint Id;
public ushort Flags;
public PhaseEntryFlags Flags;
}
public sealed class PhaseXPhaseGroupRecord
+1 -1
View File
@@ -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))
{
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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);
}
}
+7 -8
View File
@@ -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;
}
+3 -10
View File
@@ -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;
}
+28 -256
View File
@@ -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; }
+1 -1
View File
@@ -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());
+1 -1
View File
@@ -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;
+2 -4
View File
@@ -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);
+1 -1
View File
@@ -1817,7 +1817,7 @@ namespace Game.Entities
}
UpdateForQuestWorldObjects();
SendUpdatePhasing();
PhasingHandler.OnConditionChange(this);
}
public QuestGiverStatus GetQuestDialogStatus(WorldObject questgiver)
+16 -14
View File
@@ -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)
+6 -17
View File
@@ -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);
+4 -4
View File
@@ -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)
+1 -1
View File
@@ -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)
+4 -4
View File
@@ -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();
}
}
+5 -34
View File
@@ -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))
+1 -1
View File
@@ -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;
}
+259 -106
View File
@@ -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>();
}
-11
View File
@@ -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)
{
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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);
}
}
}
+7 -2
View File
@@ -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
}
+1 -1
View File
@@ -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)
+89 -26
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
}
+44 -11
View File
@@ -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)
+2 -2
View File
@@ -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;
+57 -27
View File
@@ -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;
}
}
+9 -12
View File
@@ -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)
{
+299
View File
@@ -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
}
}
+573
View File
@@ -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();
}
}
}
}
}
+13 -11
View File
@@ -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();
+13 -35
View File
@@ -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);
}
/**********************/
+11 -7
View File
@@ -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;
}
+7 -7
View File
@@ -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');