Core/Misc: Some refactoring

Port From (https://github.com/TrinityCore/TrinityCore/commit/94a79bac7a06aa0f931e9d651928de7eea0a8b5c)
This commit is contained in:
hondacrx
2022-01-06 20:07:26 -05:00
parent e51b775636
commit d2ba807c20
19 changed files with 585 additions and 477 deletions
+6 -2
View File
@@ -205,16 +205,20 @@ namespace Framework.Constants
{
Creature = 0,
GameObject = 1,
AreaTrigger = 2,
Max
NumSpawnTypesWithData,
NumSpawnTypes
}
public enum SpawnObjectTypeMask
{
Creature = (1 << SpawnObjectType.Creature),
GameObject = (1 << SpawnObjectType.GameObject),
AreaTrigger = (1 << SpawnObjectType.AreaTrigger),
All = (1 << SpawnObjectType.Max) - 1
WithData = (1 << SpawnObjectType.NumSpawnTypesWithData) - 1,
All = (1 << SpawnObjectType.NumSpawnTypes) - 1
}
[Flags]
-19
View File
@@ -866,25 +866,6 @@ namespace Framework.Constants
DisplayMythic = 0x80 // Controls icon displayed on minimap when inside the instance
}
public enum SpawnMask
{
Continent = (1 << Difficulty.None), // Any Maps Without Spawn Modes
DungeonNormal = (1 << Difficulty.Normal),
DungeonHeroic = (1 << Difficulty.Heroic),
DungeonAll = (DungeonNormal | DungeonHeroic),
Raid10Normal = (1 << Difficulty.Raid10N),
Raid25Normal = (1 << Difficulty.Raid25N),
RaidNormalAll = (Raid10Normal | Raid25Normal),
Raid10Heroic = (1 << Difficulty.Raid10HC),
Raid25Heroic = (1 << Difficulty.Raid25HC),
RaidHeroicAll = (Raid10Heroic | Raid25Heroic),
RaidAll = (RaidNormalAll | RaidHeroicAll)
}
public enum MapFlags
{
CanToggleDifficulty = 0x0100,
@@ -209,7 +209,7 @@ namespace Game.Chat
if (data != null)
{
data.rotation.toEulerAnglesZYX(out float yaw, out float pitch, out float roll);
handler.SendSysMessage(CypherStrings.SpawninfoSpawnidLocation, data.spawnId, data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY(), data.spawnPoint.GetPositionZ());
handler.SendSysMessage(CypherStrings.SpawninfoSpawnidLocation, data.SpawnId, data.SpawnPoint.GetPositionX(), data.SpawnPoint.GetPositionY(), data.SpawnPoint.GetPositionZ());
handler.SendSysMessage(CypherStrings.SpawninfoRotation, yaw, pitch, roll);
}
+3 -3
View File
@@ -645,9 +645,9 @@ namespace Game.Chat.Commands
return false;
}
if (!GridDefines.IsValidMapCoord(goData.spawnPoint) || Global.ObjectMgr.IsTransportMap(goData.spawnPoint.GetMapId()))
if (!GridDefines.IsValidMapCoord(goData.MapId, goData.SpawnPoint) || Global.ObjectMgr.IsTransportMap(goData.MapId))
{
handler.SendSysMessage(CypherStrings.InvalidTargetCoord, goData.spawnPoint.GetPositionX(), goData.spawnPoint.GetPositionY(), goData.spawnPoint.GetMapId());
handler.SendSysMessage(CypherStrings.InvalidTargetCoord, goData.SpawnPoint.GetPositionX(), goData.SpawnPoint.GetPositionY(), goData.MapId);
return false;
}
@@ -657,7 +657,7 @@ namespace Game.Chat.Commands
else
player.SaveRecallPosition(); // save only in non-flight case
player.TeleportTo(goData.spawnPoint);
player.TeleportTo(new WorldLocation(goData.MapId, goData.SpawnPoint));
return true;
}
+23 -17
View File
@@ -580,31 +580,37 @@ namespace Game.Chat.Commands
uint zoneId = player.GetZoneId();
string zoneName = GetZoneName(zoneId, locale);
for (SpawnObjectType type = 0; type < SpawnObjectType.Max; type++)
for (SpawnObjectType type = 0; type < SpawnObjectType.NumSpawnTypes; type++)
{
if (range != 0)
handler.SendSysMessage(CypherStrings.ListRespawnsRange, type, range);
else
handler.SendSysMessage(CypherStrings.ListRespawnsZone, type, zoneName, zoneId);
handler.SendSysMessage(CypherStrings.ListRespawnsListheader);
List<RespawnInfo> respawns = new();
map.GetRespawnInfo(respawns, (SpawnObjectTypeMask)(1 << (int)type));
foreach (RespawnInfo ri in respawns)
{
SpawnData data = Global.ObjectMgr.GetSpawnData(ri.type, ri.spawnId);
SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(ri.type, ri.spawnId);
if (data == null)
continue;
uint respawnZoneId = map.GetZoneId(PhasingHandler.EmptyPhaseShift, data.spawnPoint);
if (range != 0)
uint respawnZoneId = 0;
SpawnData edata = data.ToSpawnData();
if (edata != null)
{
if (!player.IsInDist(data.spawnPoint, range))
continue;
}
else
{
if (zoneId != respawnZoneId)
continue;
respawnZoneId = map.GetZoneId(PhasingHandler.EmptyPhaseShift, edata.SpawnPoint);
if (range != 0)
{
if (!player.IsInDist(edata.SpawnPoint, range))
continue;
}
else
{
if (zoneId != respawnZoneId)
continue;
}
}
uint gridY = ri.gridId / MapConst.MaxGrids;
@@ -652,28 +658,28 @@ namespace Game.Chat.Commands
foreach (var pair in Global.ObjectMgr.GetAllCreatureData())
{
SpawnData data = pair.Value;
if (data.spawnPoint.GetMapId() != mapId)
if (data.MapId != mapId)
continue;
CreatureTemplate cTemp = Global.ObjectMgr.GetCreatureTemplate(data.Id);
if (cTemp == null)
continue;
if (showAll || data.spawnPoint.IsInDist2d(player, 5000.0f))
handler.SendSysMessage($"Type: {data.type} | SpawnId: {data.spawnId} | Entry: {data.Id} ({cTemp.Name}) | X: {data.spawnPoint.GetPositionX():3} | Y: {data.spawnPoint.GetPositionY():3} | Z: {data.spawnPoint.GetPositionZ():3}");
if (showAll || data.SpawnPoint.IsInDist2d(player, 5000.0f))
handler.SendSysMessage($"Type: {data.type} | SpawnId: {data.SpawnId} | Entry: {data.Id} ({cTemp.Name}) | X: {data.SpawnPoint.GetPositionX():3} | Y: {data.SpawnPoint.GetPositionY():3} | Z: {data.SpawnPoint.GetPositionZ():3}");
}
foreach (var pair in Global.ObjectMgr.GetAllGameObjectData())
{
SpawnData data = pair.Value;
if (data.spawnPoint.GetMapId() != mapId)
if (data.MapId != mapId)
continue;
GameObjectTemplate goTemp = Global.ObjectMgr.GetGameObjectTemplate(data.Id);
if (goTemp == null)
continue;
if (showAll || data.spawnPoint.IsInDist2d(player, 5000.0f))
handler.SendSysMessage($"Type: {data.type} | SpawnId: {data.spawnId} | Entry: {data.Id} ({goTemp.name}) | X: {data.spawnPoint.GetPositionX():3} | Y: {data.spawnPoint.GetPositionY():3} | Z: {data.spawnPoint.GetPositionZ():3}");
if (showAll || data.SpawnPoint.IsInDist2d(player, 5000.0f))
handler.SendSysMessage($"Type: {data.type} | SpawnId: {data.SpawnId} | Entry: {data.Id} ({goTemp.name}) | X: {data.SpawnPoint.GetPositionX():3} | Y: {data.SpawnPoint.GetPositionY():3} | Z: {data.SpawnPoint.GetPositionZ():3}");
}
return true;
}
+5 -5
View File
@@ -172,7 +172,7 @@ namespace Game.Chat
CreatureData data = Global.ObjectMgr.GetCreatureData(target.GetSpawnId());
if (data != null)
handler.SendSysMessage(CypherStrings.NpcinfoPhases, data.phaseId, data.phaseGroup);
handler.SendSysMessage(CypherStrings.NpcinfoPhases, data.PhaseId, data.PhaseGroup);
PhasingHandler.PrintToChat(handler, target.GetPhaseShift());
@@ -233,14 +233,14 @@ namespace Game.Chat
return false;
}
if (player.GetMapId() != data.spawnPoint.GetMapId())
if (player.GetMapId() != data.MapId)
{
handler.SendSysMessage(CypherStrings.CommandCreatureatsamemap, lowguid);
return false;
}
Global.ObjectMgr.RemoveCreatureFromGrid(lowguid, data);
data.spawnPoint.Relocate(player);
data.SpawnPoint.Relocate(player);
Global.ObjectMgr.AddCreatureToGrid(lowguid, data);
// update position in DB
@@ -659,9 +659,9 @@ namespace Game.Chat
{
ulong guid = map.GenerateLowGuid(HighGuid.Creature);
CreatureData data = Global.ObjectMgr.NewOrExistCreatureData(guid);
data.spawnId = guid;
data.SpawnId = guid;
data.Id = id;
data.spawnPoint.Relocate(chr.GetTransOffsetX(), chr.GetTransOffsetY(), chr.GetTransOffsetZ(), chr.GetTransOffsetO());
data.SpawnPoint.Relocate(chr.GetTransOffsetX(), chr.GetTransOffsetY(), chr.GetTransOffsetZ(), chr.GetTransOffsetO());
data.spawnGroupData = new();
Creature creaturePassenger = trans.CreateNPCPassenger(guid, data);
@@ -319,10 +319,11 @@ namespace Game.DataStorage
AreaTriggerSpawn spawn = new();
spawn.SpawnId = spawnId;
spawn.Id = areaTriggerId;
spawn.Location = new WorldLocation(location);
spawn.MapId = location.GetMapId();
spawn.TriggerId = areaTriggerId;
spawn.SpawnPoint = new Position(location);
spawn.PhaseUseFlags = templates.Read<byte>(8);
spawn.PhaseUseFlags = (PhaseUseFlagsValues)templates.Read<byte>(8);
spawn.PhaseId = templates.Read<uint>(9);
spawn.PhaseGroup = templates.Read<uint>(10);
@@ -334,13 +335,14 @@ namespace Game.DataStorage
}
spawn.ScriptId = Global.ObjectMgr.GetScriptId(templates.Read<string>(18));
spawn.spawnGroupData = Global.ObjectMgr.GetLegacySpawnGroup();
// Add the trigger to a map::cell map, which is later used by GridLoader to query
CellCoord cellCoord = GridDefines.ComputeCellCoord(spawn.Location.GetPositionX(), spawn.Location.GetPositionY());
if (!_areaTriggerSpawnsByLocation.ContainsKey((spawn.Location.GetMapId(), cellCoord.GetId())))
_areaTriggerSpawnsByLocation[(spawn.Location.GetMapId(), cellCoord.GetId())] = new SortedSet<ulong>();
CellCoord cellCoord = GridDefines.ComputeCellCoord(spawn.SpawnPoint.GetPositionX(), spawn.SpawnPoint.GetPositionY());
if (!_areaTriggerSpawnsByLocation.ContainsKey((spawn.MapId, cellCoord.GetId())))
_areaTriggerSpawnsByLocation[(spawn.MapId, cellCoord.GetId())] = new SortedSet<ulong>();
_areaTriggerSpawnsByLocation[(spawn.Location.GetMapId(), cellCoord.GetId())].Add(spawnId);
_areaTriggerSpawnsByLocation[(spawn.MapId, cellCoord.GetId())].Add(spawnId);
// add the position to the map
_areaTriggerSpawnsBySpawnId[spawnId] = spawn;
@@ -53,6 +53,9 @@ namespace Game.Entities
if (!IsInWorld)
{
GetMap().GetObjectsStore().Add(GetGUID(), this);
if (_spawnId != 0)
GetMap().GetAreaTriggerBySpawnIdStore().Add(_spawnId, this);
base.AddToWorld();
}
}
@@ -74,6 +77,9 @@ namespace Game.Entities
_ai.OnRemove();
base.RemoveFromWorld();
if (_spawnId != 0)
GetMap().GetAreaTriggerBySpawnIdStore().Remove(_spawnId, this);
GetMap().GetObjectsStore().Remove(GetGUID());
}
}
@@ -236,7 +242,7 @@ namespace Game.Entities
if (position == null)
return false;
AreaTriggerTemplate areaTriggerTemplate = Global.AreaTriggerDataStorage.GetAreaTriggerTemplate(position.Id);
AreaTriggerTemplate areaTriggerTemplate = Global.AreaTriggerDataStorage.GetAreaTriggerTemplate(position.TriggerId);
if (areaTriggerTemplate == null)
return false;
@@ -246,7 +252,7 @@ namespace Game.Entities
bool CreateServer(Map map, AreaTriggerTemplate areaTriggerTemplate, AreaTriggerSpawn position)
{
SetMap(map);
Relocate(position.Location);
Relocate(position.SpawnPoint);
if (!IsPositionValid())
{
Log.outError(LogFilter.AreaTrigger, $"AreaTriggerServer (id {areaTriggerTemplate.Id}) not created. Invalid coordinates (X: {GetPositionX()} Y: {GetPositionY()})");
@@ -17,6 +17,7 @@
using Framework.Constants;
using Framework.Dynamic;
using Game.Maps;
using Game.Networking;
using System;
using System.Collections.Generic;
@@ -319,18 +320,12 @@ namespace Game.Entities
public uint ScriptId;
}
public class AreaTriggerSpawn
public class AreaTriggerSpawn : SpawnData
{
public ulong SpawnId;
public AreaTriggerId Id;
public WorldLocation Location;
public uint PhaseId;
public uint PhaseGroup;
public byte PhaseUseFlags;
public AreaTriggerId TriggerId;
public AreaTriggerShapeInfo Shape = new();
public uint ScriptId;
public AreaTriggerSpawn() : base(SpawnObjectType.AreaTrigger) { }
}
public struct AreaTriggerAction
+23 -17
View File
@@ -793,7 +793,7 @@ namespace Game.Entities
if (data != null)
{
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), data.PhaseUseFlags, data.PhaseId, data.PhaseGroup);
PhasingHandler.InitDbVisibleMapId(GetPhaseShift(), data.terrainSwapMap);
}
@@ -1246,18 +1246,24 @@ namespace Game.Entities
dynamicflags = 0;
}
if (data.spawnId == 0)
data.spawnId = m_spawnId;
Cypher.Assert(data.spawnId == m_spawnId);
if (data.SpawnId == 0)
data.SpawnId = m_spawnId;
Cypher.Assert(data.SpawnId == m_spawnId);
data.Id = GetEntry();
data.displayid = displayId;
data.equipmentId = (sbyte)GetCurrentEquipmentId();
if (GetTransport() == null)
data.spawnPoint.WorldRelocate(this);
{
data.MapId = GetMapId();
data.SpawnPoint.Relocate(this);
}
else
data.spawnPoint.WorldRelocate(mapid, GetTransOffsetX(), GetTransOffsetY(), GetTransOffsetZ(), GetTransOffsetO());
{
data.MapId = mapid;
data.SpawnPoint.Relocate(GetTransOffsetX(), GetTransOffsetY(), GetTransOffsetZ(), GetTransOffsetO());
}
data.spawntimesecs = (int)m_respawnDelay;
// prevent add data integrity problems
@@ -1277,8 +1283,8 @@ namespace Game.Entities
if (data.spawnGroupData == null)
data.spawnGroupData = Global.ObjectMgr.GetDefaultSpawnGroup();
data.phaseId = GetDBPhase() > 0 ? (uint)GetDBPhase() : data.phaseId;
data.phaseGroup = GetDBPhase() < 0 ? (uint)-GetDBPhase() : data.phaseGroup;
data.PhaseId = GetDBPhase() > 0 ? (uint)GetDBPhase() : data.PhaseId;
data.PhaseGroup = GetDBPhase() < 0 ? (uint)-GetDBPhase() : data.PhaseGroup;
// update in DB
SQLTransaction trans = new();
@@ -1294,8 +1300,8 @@ namespace Game.Entities
stmt.AddValue(index++, GetEntry());
stmt.AddValue(index++, mapid);
stmt.AddValue(index++, data.spawnDifficulties.Empty() ? "" : string.Join(',', data.spawnDifficulties));
stmt.AddValue(index++, data.phaseId);
stmt.AddValue(index++, data.phaseGroup);
stmt.AddValue(index++, data.PhaseId);
stmt.AddValue(index++, data.PhaseGroup);
stmt.AddValue(index++, displayId);
stmt.AddValue(index++, GetCurrentEquipmentId());
stmt.AddValue(index++, GetPositionX());
@@ -1610,7 +1616,7 @@ namespace Game.Entities
SQLTransaction trans = new();
Global.MapMgr.DoForAllMapsWithMapId(data.spawnPoint.GetMapId(), map =>
Global.MapMgr.DoForAllMapsWithMapId(data.MapId, map =>
{
// despawn all active creatures, and remove their respawns
List<Creature> toUnload = new();
@@ -2448,7 +2454,7 @@ namespace Game.Entities
{
if (m_creatureData != null)
{
m_creatureData.spawnPoint.GetPosition(out x, out y, out z, out ori);
m_creatureData.SpawnPoint.GetPosition(out x, out y, out z, out ori);
dist = m_creatureData.spawndist;
}
else
@@ -2459,7 +2465,7 @@ namespace Game.Entities
}
}
bool IsSpawnedOnTransport() { return m_creatureData != null && m_creatureData.spawnPoint.GetMapId() != GetMapId(); }
bool IsSpawnedOnTransport() { return m_creatureData != null && m_creatureData.MapId != GetMapId(); }
void InitializeMovementFlags()
{
@@ -3157,7 +3163,7 @@ namespace Game.Entities
m_respawnradius = data.spawndist;
m_respawnDelay = (uint)data.spawntimesecs;
if (!Create(map.GenerateLowGuid(HighGuid.Creature), map, data.Id, data.spawnPoint, data, 0, !m_respawnCompatibilityMode))
if (!Create(map.GenerateLowGuid(HighGuid.Creature), map, data.Id, data.SpawnPoint, data, 0, !m_respawnCompatibilityMode))
return false;
//We should set first home position, because then AI calls home movement
@@ -3198,9 +3204,9 @@ namespace Game.Entities
m_deathState = DeathState.Dead;
if (CanFly())
{
float tz = map.GetHeight(GetPhaseShift(), data.spawnPoint, true, MapConst.MaxFallDistance);
if (data.spawnPoint.GetPositionZ() - tz > 0.1f && GridDefines.IsValidMapCoord(tz))
Relocate(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY(), tz);
float tz = map.GetHeight(GetPhaseShift(), data.SpawnPoint, true, MapConst.MaxFallDistance);
if (data.SpawnPoint.GetPositionZ() - tz > 0.1f && GridDefines.IsValidMapCoord(tz))
Relocate(data.SpawnPoint.GetPositionX(), data.SpawnPoint.GetPositionY(), tz);
}
}
+13 -12
View File
@@ -1034,12 +1034,13 @@ namespace Game.Entities
// update in loaded data (changing data only in this place)
GameObjectData data = Global.ObjectMgr.NewOrExistGameObjectData(m_spawnId);
if (data.spawnId == 0)
data.spawnId = m_spawnId;
Cypher.Assert(data.spawnId == m_spawnId);
if (data.SpawnId == 0)
data.SpawnId = m_spawnId;
Cypher.Assert(data.SpawnId == m_spawnId);
data.Id = GetEntry();
data.spawnPoint.WorldRelocate(this);
data.MapId = GetMapId();
data.SpawnPoint.Relocate(this);
data.rotation = m_localRotation;
data.spawntimesecs = (int)(m_spawnedByDefault ? m_respawnDelayTime : -m_respawnDelayTime);
data.animprogress = GetGoAnimProgress();
@@ -1049,8 +1050,8 @@ namespace Game.Entities
if (data.spawnGroupData == null)
data.spawnGroupData = Global.ObjectMgr.GetDefaultSpawnGroup();
data.phaseId = GetDBPhase() > 0 ? (uint)GetDBPhase() : data.phaseId;
data.phaseGroup = GetDBPhase() < 0 ? (uint)-GetDBPhase() : data.phaseGroup;
data.PhaseId = GetDBPhase() > 0 ? (uint)GetDBPhase() : data.PhaseId;
data.PhaseGroup = GetDBPhase() < 0 ? (uint)-GetDBPhase() : data.PhaseGroup;
// Update in DB
byte index = 0;
@@ -1063,8 +1064,8 @@ namespace Game.Entities
stmt.AddValue(index++, GetEntry());
stmt.AddValue(index++, mapid);
stmt.AddValue(index++, data.spawnDifficulties.Empty() ? "" : string.Join(",", data.spawnDifficulties));
stmt.AddValue(index++, data.phaseId);
stmt.AddValue(index++, data.phaseGroup);
stmt.AddValue(index++, data.PhaseId);
stmt.AddValue(index++, data.PhaseGroup);
stmt.AddValue(index++, GetPositionX());
stmt.AddValue(index++, GetPositionY());
stmt.AddValue(index++, GetPositionZ());
@@ -1096,10 +1097,10 @@ namespace Game.Entities
m_spawnId = spawnId;
m_respawnCompatibilityMode = ((data.spawnGroupData.flags & SpawnGroupFlags.CompatibilityMode) != 0);
if (!Create(entry, map, data.spawnPoint, data.rotation, animprogress, go_state, artKit, !m_respawnCompatibilityMode, spawnId))
if (!Create(entry, map, data.SpawnPoint, data.rotation, animprogress, go_state, artKit, !m_respawnCompatibilityMode, spawnId))
return false;
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), data.PhaseUseFlags, data.PhaseId, data.PhaseGroup);
PhasingHandler.InitDbVisibleMapId(GetPhaseShift(), data.terrainSwapMap);
if (data.spawntimesecs >= 0)
@@ -1154,7 +1155,7 @@ namespace Game.Entities
SQLTransaction trans = new();
Global.MapMgr.DoForAllMapsWithMapId(data.spawnPoint.GetMapId(), map =>
Global.MapMgr.DoForAllMapsWithMapId(data.MapId, map =>
{
// despawn all active objects, and remove their respawns
List<GameObject> toUnload = new();
@@ -2805,7 +2806,7 @@ namespace Game.Entities
public void GetRespawnPosition(out float x, out float y, out float z, out float ori)
{
if (m_goData != null)
m_goData.spawnPoint.GetPosition(out x, out y, out z, out ori);
m_goData.SpawnPoint.GetPosition(out x, out y, out z, out ori);
else
GetPosition(out x, out y, out z, out ori);
}
+4 -4
View File
@@ -326,7 +326,7 @@ namespace Game.Entities
return null;
float x, y, z, o;
data.spawnPoint.GetPosition(out x, out y, out z, out o);
data.SpawnPoint.GetPosition(out x, out y, out z, out o);
creature.SetTransport(this);
creature.m_movementInfo.transport.guid = GetGUID();
@@ -347,7 +347,7 @@ namespace Game.Entities
return null;
}
PhasingHandler.InitDbPhaseShift(creature.GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
PhasingHandler.InitDbPhaseShift(creature.GetPhaseShift(), data.PhaseUseFlags, data.PhaseId, data.PhaseGroup);
PhasingHandler.InitDbVisibleMapId(creature.GetPhaseShift(), data.terrainSwapMap);
if (!map.AddToMap(creature))
@@ -369,7 +369,7 @@ namespace Game.Entities
return null;
float x, y, z, o;
data.spawnPoint.GetPosition(out x, out y, out z, out o);
data.SpawnPoint.GetPosition(out x, out y, out z, out o);
go.SetTransport(this);
go.m_movementInfo.transport.guid = GetGUID();
@@ -385,7 +385,7 @@ namespace Game.Entities
return null;
}
PhasingHandler.InitDbPhaseShift(go.GetPhaseShift(), data.phaseUseFlags, data.phaseId, data.phaseGroup);
PhasingHandler.InitDbPhaseShift(go.GetPhaseShift(), data.PhaseUseFlags, data.PhaseId, data.PhaseGroup);
PhasingHandler.InitDbVisibleMapId(go.GetPhaseShift(), data.terrainSwapMap);
if (!map.AddToMap(go))
+8 -8
View File
@@ -1124,7 +1124,7 @@ namespace Game
// get the creature data from the low guid to get the entry, to be able to find out the whole guid
CreatureData data = Global.ObjectMgr.GetCreatureData(guid);
if (data != null)
creaturesByMap.Add(data.spawnPoint.GetMapId(), guid);
creaturesByMap.Add(data.MapId, guid);
}
foreach (var key in creaturesByMap.Keys)
@@ -1191,10 +1191,10 @@ namespace Game
Global.ObjectMgr.AddCreatureToGrid(guid, data);
// Spawn if necessary (loaded grids only)
Map map = Global.MapMgr.CreateBaseMap(data.spawnPoint.GetMapId());
Map map = Global.MapMgr.CreateBaseMap(data.MapId);
map.RemoveRespawnTime(SpawnObjectType.Creature, guid);
// We use spawn coords to spawn
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.spawnPoint))
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.SpawnPoint))
Creature.CreateCreatureFromDB(guid, map);
}
}
@@ -1215,10 +1215,10 @@ namespace Game
Global.ObjectMgr.AddGameObjectToGrid(guid, data);
// Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed
Map map = Global.MapMgr.CreateBaseMap(data.spawnPoint.GetMapId());
Map map = Global.MapMgr.CreateBaseMap(data.MapId);
map.RemoveRespawnTime(SpawnObjectType.GameObject, guid);
// We use current coords to unspawn, not spawn coords since creature can have changed grid
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.spawnPoint))
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.SpawnPoint))
{
GameObject pGameobject = GameObject.CreateGameObjectFromDB(guid, map, false);
// @todo find out when it is add to map
@@ -1266,7 +1266,7 @@ namespace Game
{
Global.ObjectMgr.RemoveCreatureFromGrid(guid, data);
Global.MapMgr.DoForAllMapsWithMapId(data.spawnPoint.GetMapId(), map =>
Global.MapMgr.DoForAllMapsWithMapId(data.MapId, map =>
{
map.RemoveRespawnTime(SpawnObjectType.Creature, guid);
var creatureBounds = map.GetCreatureBySpawnIdStore().LookupByKey(guid);
@@ -1294,7 +1294,7 @@ namespace Game
{
Global.ObjectMgr.RemoveGameObjectFromGrid(guid, data);
Global.MapMgr.DoForAllMapsWithMapId(data.spawnPoint.GetMapId(), map =>
Global.MapMgr.DoForAllMapsWithMapId(data.MapId, map =>
{
map.RemoveRespawnTime(SpawnObjectType.GameObject, guid);
var gameobjectBounds = map.GetGameObjectBySpawnIdStore().LookupByKey(guid);
@@ -1325,7 +1325,7 @@ namespace Game
continue;
// Update if spawned
Global.MapMgr.DoForAllMapsWithMapId(data.spawnPoint.GetMapId(), map =>
Global.MapMgr.DoForAllMapsWithMapId(data.MapId, map =>
{
var creatureBounds = map.GetCreatureBySpawnIdStore().LookupByKey(tuple.Item1);
foreach (var creature in creatureBounds)
+148 -125
View File
@@ -2892,8 +2892,8 @@ namespace Game
break;
}
MapRecord map = CliDB.MapStorage.LookupByKey(master.spawnPoint.GetMapId());
if (map == null || !map.Instanceable() || (master.spawnPoint.GetMapId() != slave.spawnPoint.GetMapId()))
MapRecord map = CliDB.MapStorage.LookupByKey(master.MapId);
if (map == null || !map.Instanceable() || (master.MapId != slave.MapId))
{
Log.outError(LogFilter.Sql, "Creature '{0}' linking to '{1}' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -2908,8 +2908,8 @@ namespace Game
break;
}
guid = ObjectGuid.Create(HighGuid.Creature, slave.spawnPoint.GetMapId(), slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.Creature, master.spawnPoint.GetMapId(), master.Id, linkedGuidLow);
guid = ObjectGuid.Create(HighGuid.Creature, slave.MapId, slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.Creature, master.MapId, master.Id, linkedGuidLow);
break;
}
case CreatureLinkedRespawnType.CreatureToGO:
@@ -2930,8 +2930,8 @@ namespace Game
break;
}
MapRecord map = CliDB.MapStorage.LookupByKey(master.spawnPoint.GetMapId());
if (map == null || !map.Instanceable() || (master.spawnPoint.GetMapId() != slave.spawnPoint.GetMapId()))
MapRecord map = CliDB.MapStorage.LookupByKey(master.MapId);
if (map == null || !map.Instanceable() || (master.MapId != slave.MapId))
{
Log.outError(LogFilter.Sql, "Creature '{0}' linking to '{1}' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -2946,8 +2946,8 @@ namespace Game
break;
}
guid = ObjectGuid.Create(HighGuid.Creature, slave.spawnPoint.GetMapId(), slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.GameObject, master.spawnPoint.GetMapId(), master.Id, linkedGuidLow);
guid = ObjectGuid.Create(HighGuid.Creature, slave.MapId, slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.GameObject, master.MapId, master.Id, linkedGuidLow);
break;
}
case CreatureLinkedRespawnType.GOToGO:
@@ -2968,8 +2968,8 @@ namespace Game
break;
}
MapRecord map = CliDB.MapStorage.LookupByKey(master.spawnPoint.GetMapId());
if (map == null || !map.Instanceable() || (master.spawnPoint.GetMapId() != slave.spawnPoint.GetMapId()))
MapRecord map = CliDB.MapStorage.LookupByKey(master.MapId);
if (map == null || !map.Instanceable() || (master.MapId != slave.MapId))
{
Log.outError(LogFilter.Sql, "Creature '{0}' linking to '{1}' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -2984,8 +2984,8 @@ namespace Game
break;
}
guid = ObjectGuid.Create(HighGuid.GameObject, slave.spawnPoint.GetMapId(), slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.GameObject, master.spawnPoint.GetMapId(), master.Id, linkedGuidLow);
guid = ObjectGuid.Create(HighGuid.GameObject, slave.MapId, slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.GameObject, master.MapId, master.Id, linkedGuidLow);
break;
}
case CreatureLinkedRespawnType.GOToCreature:
@@ -3006,8 +3006,8 @@ namespace Game
break;
}
MapRecord map = CliDB.MapStorage.LookupByKey(master.spawnPoint.GetMapId());
if (map == null || !map.Instanceable() || (master.spawnPoint.GetMapId() != slave.spawnPoint.GetMapId()))
MapRecord map = CliDB.MapStorage.LookupByKey(master.MapId);
if (map == null || !map.Instanceable() || (master.MapId != slave.MapId))
{
Log.outError(LogFilter.Sql, "Creature '{0}' linking to '{1}' on an unpermitted map.", guidLow, linkedGuidLow);
error = true;
@@ -3022,8 +3022,8 @@ namespace Game
break;
}
guid = ObjectGuid.Create(HighGuid.GameObject, slave.spawnPoint.GetMapId(), slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.Creature, master.spawnPoint.GetMapId(), master.Id, linkedGuidLow);
guid = ObjectGuid.Create(HighGuid.GameObject, slave.MapId, slave.Id, guidLow);
linkedGuid = ObjectGuid.Create(HighGuid.Creature, master.MapId, master.Id, linkedGuidLow);
break;
}
@@ -3408,9 +3408,10 @@ namespace Game
}
CreatureData data = new();
data.spawnId = guid;
data.SpawnId = guid;
data.Id = entry;
data.spawnPoint = new WorldLocation(result.Read<ushort>(2), result.Read<float>(3), result.Read<float>(4), result.Read<float>(5), result.Read<float>(6));
data.MapId = result.Read<ushort>(2);
data.SpawnPoint = new Position(result.Read<float>(3), result.Read<float>(4), result.Read<float>(5), result.Read<float>(6));
data.displayid = result.Read<uint>(7);
data.equipmentId = result.Read<sbyte>(8);
data.spawntimesecs = result.Read<int>(9);
@@ -3419,7 +3420,7 @@ namespace Game
data.curhealth = result.Read<uint>(12);
data.curmana = result.Read<uint>(13);
data.movementType = result.Read<byte>(14);
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(15), "creature", guid, data.spawnPoint.GetMapId(), spawnMasks.LookupByKey(data.spawnPoint.GetMapId()));
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(15), "creature", guid, data.MapId, spawnMasks.LookupByKey(data.MapId));
short gameEvent = result.Read<short>(16);
uint PoolId = result.Read<uint>(17);
data.npcflag = result.Read<ulong>(18);
@@ -3427,17 +3428,17 @@ namespace Game
data.unit_flags2 = result.Read<uint>(20);
data.unit_flags3 = result.Read<uint>(21);
data.dynamicflags = result.Read<uint>(22);
data.phaseUseFlags = (PhaseUseFlagsValues)result.Read<byte>(23);
data.phaseId = result.Read<uint>(24);
data.phaseGroup = result.Read<uint>(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));
data.spawnGroupData = _spawnGroupDataStorage[IsTransportMap(data.spawnPoint.GetMapId()) ? 1 : 0u]; // transport spawns default to compatibility group
data.spawnGroupData = _spawnGroupDataStorage[IsTransportMap(data.MapId) ? 1 : 0u]; // transport spawns default to compatibility group
var mapEntry = CliDB.MapStorage.LookupByKey(data.spawnPoint.GetMapId());
var mapEntry = CliDB.MapStorage.LookupByKey(data.MapId);
if (mapEntry == null)
{
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0}) that spawned at not existed map (Id: {1}), skipped.", guid, data.spawnPoint.GetMapId());
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0}) that spawned at not existed map (Id: {1}), skipped.", guid, data.MapId);
continue;
}
@@ -3498,40 +3499,40 @@ namespace Game
}
}
if (Convert.ToBoolean(data.phaseUseFlags & ~PhaseUseFlagsValues.All))
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;
data.PhaseUseFlags &= PhaseUseFlagsValues.All;
}
if (data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.AlwaysVisible) && data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.Inverse))
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;
data.PhaseUseFlags &= ~PhaseUseFlagsValues.Inverse;
}
if (data.phaseGroup != 0 && data.phaseId != 0)
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);
data.phaseGroup = 0;
data.PhaseGroup = 0;
}
if (data.phaseId != 0)
if (data.PhaseId != 0)
{
if (!CliDB.PhaseStorage.ContainsKey(data.phaseId))
if (!CliDB.PhaseStorage.ContainsKey(data.PhaseId))
{
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) with `phaseid` {2} does not exist, set to 0", guid, data.Id, data.phaseId);
data.phaseId = 0;
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) with `phaseid` {2} does not exist, set to 0", guid, data.Id, data.PhaseId);
data.PhaseId = 0;
}
}
if (data.phaseGroup != 0)
if (data.PhaseGroup != 0)
{
if (Global.DB2Mgr.GetPhasesForGroup(data.phaseGroup).Empty())
if (Global.DB2Mgr.GetPhasesForGroup(data.PhaseGroup).Empty())
{
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) with `phasegroup` {2} does not exist, set to 0", guid, data.Id, data.phaseGroup);
data.phaseGroup = 0;
Log.outError(LogFilter.Sql, "Table `creature` have creature (GUID: {0} Entry: {1}) with `phasegroup` {2} does not exist, set to 0", guid, data.Id, data.PhaseGroup);
data.PhaseGroup = 0;
}
}
@@ -3543,7 +3544,7 @@ namespace Game
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.spawnPoint.GetMapId())
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;
@@ -3553,7 +3554,7 @@ namespace Game
if (WorldConfig.GetBoolValue(WorldCfg.CalculateCreatureZoneAreaData))
{
PhasingHandler.InitDbVisibleMapId(phaseShift, data.terrainSwapMap);
Global.MapMgr.GetZoneAndAreaId(phaseShift, out uint zoneId, out uint areaId, data.spawnPoint);
Global.MapMgr.GetZoneAndAreaId(phaseShift, out uint zoneId, out uint areaId, data.MapId, data.SpawnPoint);
PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.UPD_CREATURE_ZONE_AREA_DATA);
stmt.AddValue(0, zoneId);
@@ -3578,8 +3579,8 @@ namespace Game
{
foreach (Difficulty difficulty in data.spawnDifficulties)
{
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY());
var cellguids = CreateCellObjectGuids(data.spawnPoint.GetMapId(), difficulty, cellCoord.GetId());
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.SpawnPoint.GetPositionX(), data.SpawnPoint.GetPositionY());
var cellguids = CreateCellObjectGuids(data.MapId, difficulty, cellCoord.GetId());
cellguids.creatures.Add(guid);
}
}
@@ -3587,8 +3588,8 @@ namespace Game
{
foreach (Difficulty difficulty in data.spawnDifficulties)
{
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY());
CellObjectGuids cellguids = GetCellObjectGuids(data.spawnPoint.GetMapId(), difficulty, cellCoord.GetId());
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.SpawnPoint.GetPositionX(), data.SpawnPoint.GetPositionY());
CellObjectGuids cellguids = GetCellObjectGuids(data.MapId, difficulty, cellCoord.GetId());
if (cellguids == null)
return;
@@ -3611,9 +3612,10 @@ namespace Game
ulong spawnId = GenerateCreatureSpawnId();
CreatureData data = NewOrExistCreatureData(spawnId);
data.spawnId = spawnId;
data.SpawnId = spawnId;
data.Id = entry;
data.spawnPoint.WorldRelocate(mapId, pos);
data.MapId = mapId;
data.SpawnPoint.Relocate(pos);
data.displayid = 0;
data.equipmentId = 0;
@@ -3633,7 +3635,7 @@ namespace Game
AddCreatureToGrid(spawnId, data);
// We use spawn coords to spawn
if (!map.Instanceable() && !map.IsRemovalGrid(data.spawnPoint))
if (!map.Instanceable() && !map.IsRemovalGrid(data.SpawnPoint))
{
Creature creature = Creature.CreateCreatureFromDB(spawnId, map, true, true);
if (!creature)
@@ -3674,13 +3676,13 @@ namespace Game
return creatureTemplateStorage;
}
public Dictionary<ulong, CreatureData> GetAllCreatureData() { return creatureDataStorage; }
public CreatureData GetCreatureData(ulong guid)
public CreatureData GetCreatureData(ulong spawnId)
{
return creatureDataStorage.LookupByKey(guid);
return creatureDataStorage.LookupByKey(spawnId);
}
public ObjectGuid GetLinkedRespawnGuid(ObjectGuid guid)
public ObjectGuid GetLinkedRespawnGuid(ObjectGuid spawnId)
{
var retGuid = linkedRespawnStorage.LookupByKey(guid);
var retGuid = linkedRespawnStorage.LookupByKey(spawnId);
if (retGuid.IsEmpty())
return ObjectGuid.Empty;
return retGuid;
@@ -3691,7 +3693,7 @@ namespace Game
return false;
CreatureData master = GetCreatureData(guidLow);
ObjectGuid guid = ObjectGuid.Create(HighGuid.Creature, master.spawnPoint.GetMapId(), master.Id, guidLow);
ObjectGuid guid = ObjectGuid.Create(HighGuid.Creature, master.MapId, master.Id, guidLow);
PreparedStatement stmt;
if (linkedGuidLow == 0) // we're removing the linking
@@ -3711,8 +3713,8 @@ namespace Game
return false;
}
MapRecord map = CliDB.MapStorage.LookupByKey(master.spawnPoint.GetMapId());
if (map == null || !map.Instanceable() || (master.spawnPoint.GetMapId() != slave.spawnPoint.GetMapId()))
MapRecord map = CliDB.MapStorage.LookupByKey(master.MapId);
if (map == null || !map.Instanceable() || (master.MapId != slave.MapId))
{
Log.outError(LogFilter.Sql, "Creature '{0}' linking to '{1}' on an unpermitted map.", guidLow, linkedGuidLow);
return false;
@@ -3725,7 +3727,7 @@ namespace Game
return false;
}
ObjectGuid linkedGuid = ObjectGuid.Create(HighGuid.Creature, slave.spawnPoint.GetMapId(), slave.Id, linkedGuidLow);
ObjectGuid linkedGuid = ObjectGuid.Create(HighGuid.Creature, slave.MapId, slave.Id, linkedGuidLow);
linkedRespawnStorage[guid] = linkedGuid;
stmt = DB.World.GetPreparedStatement(WorldStatements.REP_LINKED_RESPAWN);
@@ -3735,22 +3737,22 @@ namespace Game
DB.World.Execute(stmt);
return true;
}
public CreatureData NewOrExistCreatureData(ulong guid)
public CreatureData NewOrExistCreatureData(ulong spawnId)
{
if (!creatureDataStorage.ContainsKey(guid))
creatureDataStorage[guid] = new CreatureData();
return creatureDataStorage[guid];
if (!creatureDataStorage.ContainsKey(spawnId))
creatureDataStorage[spawnId] = new CreatureData();
return creatureDataStorage[spawnId];
}
public void DeleteCreatureData(ulong guid)
public void DeleteCreatureData(ulong spawnId)
{
CreatureData data = GetCreatureData(guid);
CreatureData data = GetCreatureData(spawnId);
if (data != null)
{
RemoveCreatureFromGrid(guid, data);
RemoveCreatureFromGrid(spawnId, data);
OnDeleteSpawnData(data);
}
creatureDataStorage.Remove(guid);
creatureDataStorage.Remove(spawnId);
}
public CreatureBaseStats GetCreatureBaseStats(uint level, uint unitClass)
{
@@ -4168,20 +4170,21 @@ namespace Game
}
GameObjectData data = new();
data.spawnId = guid;
data.SpawnId = guid;
data.Id = entry;
data.spawnPoint = new WorldLocation(result.Read<ushort>(2), result.Read<float>(3), result.Read<float>(4), result.Read<float>(5), result.Read<float>(6));
data.MapId = result.Read<ushort>(2);
data.SpawnPoint = new Position(result.Read<float>(3), result.Read<float>(4), result.Read<float>(5), result.Read<float>(6));
data.rotation.X = result.Read<float>(7);
data.rotation.Y = result.Read<float>(8);
data.rotation.Z = result.Read<float>(9);
data.rotation.W = result.Read<float>(10);
data.spawntimesecs = result.Read<int>(11);
data.spawnGroupData = _spawnGroupDataStorage[IsTransportMap(data.spawnPoint.GetMapId()) ? 1 : 0u]; // transport spawns default to compatibility group
data.spawnGroupData = IsTransportMap(data.MapId) ? GetLegacySpawnGroup() : GetDefaultSpawnGroup(); // transport spawns default to compatibility group
var mapEntry = CliDB.MapStorage.LookupByKey(data.spawnPoint.GetMapId());
var mapEntry = CliDB.MapStorage.LookupByKey(data.MapId);
if (mapEntry == null)
{
Log.outError(LogFilter.Sql, "Table `gameobject` has gameobject (GUID: {0} Entry: {1}) spawned on a non-existed map (Id: {2}), skip", guid, data.Id, data.spawnPoint.GetMapId());
Log.outError(LogFilter.Sql, "Table `gameobject` has gameobject (GUID: {0} Entry: {1}) spawned on a non-existed map (Id: {2}), skip", guid, data.Id, data.MapId);
continue;
}
@@ -4204,7 +4207,7 @@ namespace Game
}
data.goState = (GameObjectState)gostate;
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(14), "gameobject", guid, data.spawnPoint.GetMapId(), spawnMasks.LookupByKey(data.spawnPoint.GetMapId()));
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(14), "gameobject", guid, data.MapId, spawnMasks.LookupByKey(data.MapId));
if (data.spawnDifficulties.Empty())
{
Log.outError(LogFilter.Sql, $"Table `creature` has creature (GUID: {guid}) that is not spawned in any difficulty, skipped.");
@@ -4213,44 +4216,44 @@ namespace Game
short gameEvent = result.Read<sbyte>(15);
uint PoolId = result.Read<uint>(16);
data.phaseUseFlags = (PhaseUseFlagsValues)result.Read<byte>(17);
data.phaseId = result.Read<uint>(18);
data.phaseGroup = result.Read<uint>(19);
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))
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;
data.PhaseUseFlags &= PhaseUseFlagsValues.All;
}
if (data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.AlwaysVisible) && data.phaseUseFlags.HasAnyFlag(PhaseUseFlagsValues.Inverse))
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;
data.PhaseUseFlags &= ~PhaseUseFlagsValues.Inverse;
}
if (data.phaseGroup != 0 && data.phaseId != 0)
if (data.PhaseGroup != 0 && data.PhaseId != 0)
{
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.Id);
data.phaseGroup = 0;
data.PhaseGroup = 0;
}
if (data.phaseId != 0)
if (data.PhaseId != 0)
{
if (!CliDB.PhaseStorage.ContainsKey(data.phaseId))
if (!CliDB.PhaseStorage.ContainsKey(data.PhaseId))
{
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) with `phaseid` {2} does not exist, set to 0", guid, data.Id, data.phaseId);
data.phaseId = 0;
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) with `phaseid` {2} does not exist, set to 0", guid, data.Id, data.PhaseId);
data.PhaseId = 0;
}
}
if (data.phaseGroup != 0)
if (data.PhaseGroup != 0)
{
if (Global.DB2Mgr.GetPhasesForGroup(data.phaseGroup).Empty())
if (Global.DB2Mgr.GetPhasesForGroup(data.PhaseGroup).Empty())
{
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) with `phaseGroup` {2} does not exist, set to 0", guid, data.Id, data.phaseGroup);
data.phaseGroup = 0;
Log.outError(LogFilter.Sql, "Table `gameobject` have gameobject (GUID: {0} Entry: {1}) with `phaseGroup` {2} does not exist, set to 0", guid, data.Id, data.PhaseGroup);
data.PhaseGroup = 0;
}
}
@@ -4263,7 +4266,7 @@ namespace Game
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.spawnPoint.GetMapId())
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;
@@ -4296,7 +4299,7 @@ namespace Game
continue;
}
if (!GridDefines.IsValidMapCoord(data.spawnPoint))
if (!GridDefines.IsValidMapCoord(data.MapId, data.SpawnPoint))
{
Log.outError(LogFilter.Sql, "Table `gameobject` has gameobject (GUID: {0} Entry: {1}) with invalid coordinates, skip", guid, data.Id);
continue;
@@ -4305,13 +4308,13 @@ namespace Game
if (!(Math.Abs(Quaternion.Dot(data.rotation, data.rotation) - 1) < 1e-5))
{
Log.outError(LogFilter.Sql, $"Table `gameobject` has gameobject (GUID: {guid} Entry: {data.Id}) with invalid rotation quaternion (non-unit), defaulting to orientation on Z axis only");
data.rotation = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(data.spawnPoint.GetOrientation(), 0f, 0f));
data.rotation = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(data.SpawnPoint.GetOrientation(), 0f, 0f));
}
if (WorldConfig.GetBoolValue(WorldCfg.CalculateGameobjectZoneAreaData))
{
PhasingHandler.InitDbVisibleMapId(phaseShift, data.terrainSwapMap);
Global.MapMgr.GetZoneAndAreaId(phaseShift, out uint zoneId, out uint areaId, data.spawnPoint);
Global.MapMgr.GetZoneAndAreaId(phaseShift, out uint zoneId, out uint areaId, data.MapId, data.SpawnPoint);
PreparedStatement stmt = DB.World.GetPreparedStatement(WorldStatements.UPD_GAMEOBJECT_ZONE_AREA_DATA);
stmt.AddValue(0, zoneId);
@@ -4499,8 +4502,8 @@ namespace Game
{
foreach (Difficulty difficulty in data.spawnDifficulties)
{
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY());
var cellguids = CreateCellObjectGuids(data.spawnPoint.GetMapId(), difficulty, cellCoord.GetId());
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.SpawnPoint.GetPositionX(), data.SpawnPoint.GetPositionY());
var cellguids = CreateCellObjectGuids(data.MapId, difficulty, cellCoord.GetId());
cellguids.gameobjects.Add(guid);
}
}
@@ -4508,8 +4511,8 @@ namespace Game
{
foreach (Difficulty difficulty in data.spawnDifficulties)
{
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY());
CellObjectGuids cellguids = GetCellObjectGuids(data.spawnPoint.GetMapId(), difficulty, cellCoord.GetId());
CellCoord cellCoord = GridDefines.ComputeCellCoord(data.SpawnPoint.GetPositionX(), data.SpawnPoint.GetPositionY());
CellObjectGuids cellguids = GetCellObjectGuids(data.MapId, difficulty, cellCoord.GetId());
if (cellguids == null)
return;
@@ -4528,9 +4531,10 @@ namespace Game
ulong spawnId = GenerateGameObjectSpawnId();
GameObjectData data = NewOrExistGameObjectData(spawnId);
data.spawnId = spawnId;
data.SpawnId = spawnId;
data.Id = entry;
data.spawnPoint.WorldRelocate(mapId, pos);
data.MapId = mapId;
data.SpawnPoint.Relocate(pos);
data.rotation = rot;
data.spawntimesecs = (int)spawntimedelay;
data.animprogress = 100;
@@ -4544,7 +4548,7 @@ namespace Game
// Spawn if necessary (loaded grids only)
// We use spawn coords to spawn
if (!map.Instanceable() && map.IsGridLoaded(data.spawnPoint))
if (!map.Instanceable() && map.IsGridLoaded(data.SpawnPoint))
{
GameObject go = GameObject.CreateGameObjectFromDB(spawnId, map);
if (!go)
@@ -4554,7 +4558,7 @@ namespace Game
}
}
Log.outDebug(LogFilter.Maps, $"AddGameObjectData: dbguid:{spawnId} entry:{entry} map:{mapId} pos:{data.spawnPoint}");
Log.outDebug(LogFilter.Maps, $"AddGameObjectData: dbguid:{spawnId} entry:{entry} map:{mapId} pos:{data.SpawnPoint}");
return spawnId;
}
@@ -4569,27 +4573,27 @@ namespace Game
}
MultiMap<uint, uint> GetGameObjectQuestItemMap() { return _gameObjectQuestItemStorage; }
public Dictionary<ulong, GameObjectData> GetAllGameObjectData() { return gameObjectDataStorage; }
public GameObjectData GetGameObjectData(ulong guid)
public GameObjectData GetGameObjectData(ulong spawnId)
{
return gameObjectDataStorage.LookupByKey(guid);
return gameObjectDataStorage.LookupByKey(spawnId);
}
public void DeleteGameObjectData(ulong guid)
public void DeleteGameObjectData(ulong spawnId)
{
GameObjectData data = GetGameObjectData(guid);
GameObjectData data = GetGameObjectData(spawnId);
if (data != null)
{
RemoveGameObjectFromGrid(guid, data);
RemoveGameObjectFromGrid(spawnId, data);
OnDeleteSpawnData(data);
}
gameObjectDataStorage.Remove(guid);
gameObjectDataStorage.Remove(spawnId);
}
public GameObjectData NewOrExistGameObjectData(ulong guid)
public GameObjectData NewOrExistGameObjectData(ulong spawnId)
{
if (!gameObjectDataStorage.ContainsKey(guid))
gameObjectDataStorage[guid] = new GameObjectData();
if (!gameObjectDataStorage.ContainsKey(spawnId))
gameObjectDataStorage[spawnId] = new GameObjectData();
return gameObjectDataStorage[guid];
return gameObjectDataStorage[spawnId];
}
public GameObjectTemplate GetGameObjectTemplate(uint entry)
{
@@ -5509,14 +5513,14 @@ namespace Game
{
uint groupId = result.Read<uint>(0);
SpawnObjectType spawnType = (SpawnObjectType)result.Read<byte>(1);
if (spawnType >= SpawnObjectType.Max)
if (!SpawnData.TypeIsValid(spawnType))
{
Log.outError(LogFilter.Sql, $"Spawn data with invalid type {spawnType} listed for spawn group {groupId}. Skipped.");
continue;
}
ulong spawnId = result.Read<ulong>(2);
SpawnData data = GetSpawnData(spawnType, spawnId);
SpawnMetadata data = GetSpawnMetadata(spawnType, spawnId);
if (data == null)
{
Log.outError(LogFilter.Sql, $"Spawn data with ID ({spawnType},{spawnId}) not found, but is listed as a member of spawn group {groupId}!");
@@ -5536,10 +5540,10 @@ namespace Game
else
{
if (groupTemplate.mapId == 0xFFFFFFFF)
groupTemplate.mapId = data.spawnPoint.GetMapId();
else if (groupTemplate.mapId != data.spawnPoint.GetMapId() && !groupTemplate.flags.HasAnyFlag(SpawnGroupFlags.System))
groupTemplate.mapId = data.MapId;
else if (groupTemplate.mapId != data.MapId && !groupTemplate.flags.HasAnyFlag(SpawnGroupFlags.System))
{
Log.outError(LogFilter.Sql, $"Spawn group {groupId} has map ID {groupTemplate.mapId}, but spawn ({spawnType},{spawnId}) has map id {data.spawnPoint.GetMapId()} - spawn NOT added to group!");
Log.outError(LogFilter.Sql, $"Spawn group {groupId} has map ID {groupTemplate.mapId}, but spawn ({spawnType},{spawnId}) has map id {data.MapId} - spawn NOT added to group!");
continue;
}
data.spawnGroupData = groupTemplate;
@@ -5609,7 +5613,7 @@ namespace Game
void OnDeleteSpawnData(SpawnData data)
{
var templateIt = _spawnGroupDataStorage.LookupByKey(data.spawnGroupData.groupId);
Cypher.Assert(templateIt != null, $"Creature data for ({data.type},{data.spawnId}) is being deleted and has invalid spawn group index {data.spawnGroupData.groupId}!");
Cypher.Assert(templateIt != null, $"Creature data for ({data.type},{data.SpawnId}) is being deleted and has invalid spawn group index {data.spawnGroupData.groupId}!");
if (templateIt.flags.HasAnyFlag(SpawnGroupFlags.System)) // system groups don't store their members in the map
return;
@@ -5623,7 +5627,7 @@ namespace Game
return;
}
Cypher.Assert(false, $"Spawn data ({data.type},{data.spawnId}) being removed is member of spawn group {data.spawnGroupData.groupId}, but not actually listed in the lookup table for that group!");
Cypher.Assert(false, $"Spawn data ({data.type},{data.SpawnId}) being removed is member of spawn group {data.spawnGroupData.groupId}, but not actually listed in the lookup table for that group!");
}
public Dictionary<uint, InstanceTemplate> GetInstanceTemplates() { return instanceTemplateStorage; }
@@ -5691,19 +5695,38 @@ namespace Game
}
public bool IsTransportMap(uint mapId) { return _transportMaps.Contains((ushort)mapId); }
public SpawnGroupTemplateData GetSpawnGroupData(uint groupId) { return _spawnGroupDataStorage.LookupByKey(groupId); }
public SpawnGroupTemplateData GetSpawnGroupData(SpawnObjectType type, ulong spawnId)
{
SpawnMetadata data = GetSpawnMetadata(type, spawnId);
return data != null ? data.spawnGroupData : null;
}
public SpawnGroupTemplateData GetDefaultSpawnGroup() { return _spawnGroupDataStorage.ElementAt(0).Value; }
public SpawnGroupTemplateData GetLegacySpawnGroup() { return _spawnGroupDataStorage.ElementAt(1).Value; }
public List<SpawnData> GetSpawnDataForGroup(uint groupId) { return _spawnGroupMapStorage.LookupByKey(groupId); }
public SpawnData GetSpawnData(SpawnObjectType type, ulong guid)
public List<SpawnMetadata> GetSpawnMetadataForGroup(uint groupId) { return _spawnGroupMapStorage.LookupByKey(groupId); }
public SpawnMetadata GetSpawnMetadata(SpawnObjectType type, ulong spawnId)
{
if (type == SpawnObjectType.Creature)
return GetCreatureData(guid);
else if (type == SpawnObjectType.GameObject)
return GetGameObjectData(guid);
if (SpawnData.TypeHasData(type))
return GetSpawnData(type, spawnId);
else
Cypher.Assert(false, $"Invalid spawn object type {type}");
return null;
}
public SpawnData GetSpawnData(SpawnObjectType type, ulong spawnId)
{
if (!SpawnData.TypeHasData(type))
return null;
return null;
switch (type)
{
case SpawnObjectType.Creature:
return GetCreatureData(spawnId);
case SpawnObjectType.GameObject:
return GetGameObjectData(spawnId);
case SpawnObjectType.AreaTrigger:
return Global.AreaTriggerDataStorage.GetAreaTriggerSpawn(spawnId);
default:
Cypher.Assert(false, $"Invalid spawn object type {type}");
return null;
}
}
public List<InstanceSpawnGroupInfo> GetSpawnGroupsForInstance(uint instanceId) { return _instanceSpawnGroupStorage.LookupByKey(instanceId); }
@@ -10593,7 +10616,7 @@ namespace Game
public MultiMap<uint, GraveYardData> GraveYardStorage = new();
List<ushort> _transportMaps = new();
Dictionary<uint, SpawnGroupTemplateData> _spawnGroupDataStorage = new();
MultiMap<uint, SpawnData> _spawnGroupMapStorage = new();
MultiMap<uint, SpawnMetadata> _spawnGroupMapStorage = new();
MultiMap<ushort, InstanceSpawnGroupInfo> _instanceSpawnGroupStorage = new();
//Spells /Skills / Phases
+7 -2
View File
@@ -42,7 +42,7 @@ namespace Game.Maps
{
return IsValidMapCoord(x, y, z) && float.IsFinite(o);
}
public static bool IsValidMapCoord(uint mapid, float x, float y)
{
return Global.MapMgr.IsValidMAP(mapid, false) && IsValidMapCoord(x, y);
@@ -58,9 +58,14 @@ namespace Game.Maps
return Global.MapMgr.IsValidMAP(mapid, false) && IsValidMapCoord(x, y, z, o);
}
public static bool IsValidMapCoord(uint mapid, Position pos)
{
return IsValidMapCoord(mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
}
public static bool IsValidMapCoord(WorldLocation loc)
{
return IsValidMapCoord(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation());
return IsValidMapCoord(loc.GetMapId(), loc);
}
public static void NormalizeMapCoord(ref float c)
+264 -182
View File
@@ -2411,6 +2411,159 @@ namespace Game.Maps
return true;
}
public void Respawn(SpawnObjectType type, ulong spawnId, SQLTransaction dbTrans = null)
{
RespawnInfo info = GetRespawnInfo(type, spawnId);
if (info != null)
Respawn(info, dbTrans);
}
public void Respawn(RespawnInfo info, SQLTransaction dbTrans = null)
{
info.respawnTime = GameTime.GetGameTime();
SaveRespawnInfoDB(info, dbTrans);
}
public void RemoveRespawnTime(SpawnObjectType type, ulong spawnId, SQLTransaction dbTrans = null)
{
RespawnInfo info = GetRespawnInfo(type, spawnId);
if (info != null)
DeleteRespawnInfo(info, dbTrans);
}
int DespawnAll(SpawnObjectType type, ulong spawnId)
{
List<WorldObject> toUnload = new();
switch (type)
{
case SpawnObjectType.Creature:
foreach (var creature in GetCreatureBySpawnIdStore().LookupByKey(spawnId))
toUnload.Add(creature);
break;
case SpawnObjectType.GameObject:
foreach (var obj in GetGameObjectBySpawnIdStore().LookupByKey(spawnId))
toUnload.Add(obj);
break;
default:
break;
}
foreach (WorldObject o in toUnload)
AddObjectToRemoveList(o);
return toUnload.Count;
}
bool AddRespawnInfo(RespawnInfo info)
{
if (info.spawnId == 0)
{
Log.outError(LogFilter.Maps, $"Attempt to insert respawn info for zero spawn id (type {info.type})");
return false;
}
var bySpawnIdMap = GetRespawnMapForType(info.type);
if (bySpawnIdMap == null)
return false;
// check if we already have the maximum possible number of respawns scheduled
if (SpawnData.TypeHasData(info.type))
{
var existing = bySpawnIdMap.LookupByKey(info.spawnId);
if (existing != null) // spawnid already has a respawn scheduled
{
if (info.respawnTime <= existing.respawnTime) // delete existing in this case
DeleteRespawnInfo(existing);
else
return false;
}
Cypher.Assert(!bySpawnIdMap.ContainsKey(info.spawnId), $"Insertion of respawn info with id ({info.type},{info.spawnId}) into spawn id map failed - state desync.");
}
else
Cypher.Assert(false, $"Invalid respawn info for spawn id ({info.type},{info.spawnId}) being inserted");
RespawnInfo ri = new(info);
_respawnTimes.Add(ri);
bySpawnIdMap.Add(ri.spawnId, ri);
return true;
}
static void PushRespawnInfoFrom(List<RespawnInfo> data, Dictionary<ulong, RespawnInfo> map)
{
foreach (var pair in map)
data.Add(pair.Value);
}
public void GetRespawnInfo(List<RespawnInfo> respawnData, SpawnObjectTypeMask types)
{
if ((types & SpawnObjectTypeMask.Creature) != 0)
PushRespawnInfoFrom(respawnData, _creatureRespawnTimesBySpawnId);
if ((types & SpawnObjectTypeMask.GameObject) != 0)
PushRespawnInfoFrom(respawnData, _gameObjectRespawnTimesBySpawnId);
}
public RespawnInfo GetRespawnInfo(SpawnObjectType type, ulong spawnId)
{
var map = GetRespawnMapForType(type);
if (map == null)
return null;
var respawnInfo = map.LookupByKey(spawnId);
if (respawnInfo == null)
return null;
return respawnInfo;
}
Dictionary<ulong, RespawnInfo> GetRespawnMapForType(SpawnObjectType type)
{
switch (type)
{
case SpawnObjectType.Creature:
return _creatureRespawnTimesBySpawnId;
case SpawnObjectType.GameObject:
return _gameObjectRespawnTimesBySpawnId;
case SpawnObjectType.AreaTrigger:
return null;
default:
Cypher.Assert(false);
return null;
}
}
void UnloadAllRespawnInfos() // delete everything from memory
{
_respawnTimes.Clear();
_creatureRespawnTimesBySpawnId.Clear();
_gameObjectRespawnTimesBySpawnId.Clear();
}
void DeleteRespawnInfo(RespawnInfo info, SQLTransaction dbTrans = null)
{
// Delete from all relevant containers to ensure consistency
Cypher.Assert(info != null);
// spawnid store
var spawnMap = GetRespawnMapForType(info.type);
if (spawnMap == null)
return;
var respawnInfo = spawnMap.LookupByKey(info.spawnId);
Cypher.Assert(respawnInfo != info, $"Respawn stores inconsistent for map {GetId()}, spawnid {info.spawnId} (type {info.type})");
spawnMap.Remove(info.spawnId);
// respawn heap
_respawnTimes.Remove(info);
// database
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_RESPAWN);
stmt.AddValue(0, (ushort)info.type);
stmt.AddValue(1, info.spawnId);
stmt.AddValue(2, GetId());
stmt.AddValue(3, GetInstanceId());
DB.Characters.ExecuteOrAppend(dbTrans, stmt);
}
void DoRespawn(SpawnObjectType type, ulong spawnId, uint gridId)
{
if (!IsGridLoaded(gridId)) // if grid isn't loaded, this will be processed in grid load handler
@@ -2438,120 +2591,6 @@ namespace Game.Maps
}
}
public void Respawn(SpawnObjectType type, ulong spawnId, SQLTransaction dbTrans = null)
{
RespawnInfo info = GetRespawnInfo(type, spawnId);
if (info != null)
Respawn(info, dbTrans);
}
public void Respawn(RespawnInfo info, SQLTransaction dbTrans = null)
{
if (!CheckRespawn(info))
{
if (info.respawnTime != 0)
{
//_respawnTimes.decrease(info);
SaveRespawnInfoDB(info, dbTrans);
}
else
DeleteRespawnInfo(info, dbTrans);
return;
}
// remove the actual respawn record first - since this deletes it, we save what we need
SpawnObjectType type = info.type;
uint gridId = info.gridId;
ulong spawnId = info.spawnId;
DeleteRespawnInfo(info, dbTrans);
DoRespawn(type, spawnId, gridId);
}
bool AddRespawnInfo(RespawnInfo info)
{
Cypher.Assert(info.spawnId != 0, $"Attempt to schedule respawn with zero spawnid (type {info.type})");
var bySpawnIdMap = GetRespawnMapForType(info.type);
var existing = bySpawnIdMap.LookupByKey(info.spawnId);
if (existing != null) // spawnid already has a respawn scheduled
{
if (info.respawnTime < existing.respawnTime) // delete existing in this case
DeleteRespawnInfo(existing);
else
return false;
}
// if we get to this point, we should insert the respawninfo (there either was no prior entry, or it was deleted already)
RespawnInfo ri = new(info);
_respawnTimes.Add(ri);
bool success = bySpawnIdMap.TryAdd(ri.spawnId, ri);
Cypher.Assert(success, $"Insertion of respawn info with id ({ri.type},{ri.spawnId}) into spawn id map failed - state desync.");
return true;
}
static void PushRespawnInfoFrom(List<RespawnInfo> data, Dictionary<ulong, RespawnInfo> map)
{
foreach (var pair in map)
data.Add(pair.Value);
}
public void GetRespawnInfo(List<RespawnInfo> respawnData, SpawnObjectTypeMask types)
{
if (types.HasAnyFlag(SpawnObjectTypeMask.Creature))
PushRespawnInfoFrom(respawnData, _creatureRespawnTimesBySpawnId);
if (types.HasAnyFlag(SpawnObjectTypeMask.GameObject))
PushRespawnInfoFrom(respawnData, _gameObjectRespawnTimesBySpawnId);
}
RespawnInfo GetRespawnInfo(SpawnObjectType type, ulong spawnId)
{
var map = GetRespawnMapForType(type);
var respawnInfo = map.LookupByKey(spawnId);
if (respawnInfo == null)
return null;
return respawnInfo;
}
Dictionary<ulong, RespawnInfo> GetRespawnMapForType(SpawnObjectType type) { return (type == SpawnObjectType.GameObject) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; }
void UnloadAllRespawnInfos() // delete everything from memory
{
_respawnTimes.Clear();
_creatureRespawnTimesBySpawnId.Clear();
_gameObjectRespawnTimesBySpawnId.Clear();
}
void DeleteRespawnInfo(RespawnInfo info, SQLTransaction dbTrans = null)
{
// Delete from all relevant containers to ensure consistency
Cypher.Assert(info != null);
// spawnid store
bool removed = GetRespawnMapForType(info.type).Remove(info.spawnId);
Cypher.Assert(removed, $"Respawn stores inconsistent for map {GetId()}, spawnid {info.spawnId} (type {info.type})");
// respawn heap
_respawnTimes.Remove(info);
// database
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_RESPAWN);
stmt.AddValue(0, (ushort)info.type);
stmt.AddValue(1, info.spawnId);
stmt.AddValue(2, GetId());
stmt.AddValue(3, GetInstanceId());
DB.Characters.ExecuteOrAppend(dbTrans, stmt);
}
public void RemoveRespawnTime(SpawnObjectType type, ulong spawnId, SQLTransaction dbTrans = null)
{
RespawnInfo info = GetRespawnInfo(type, spawnId);
if (info != null)
DeleteRespawnInfo(info, dbTrans);
}
void ProcessRespawns()
{
long now = GameTime.GetGameTime();
@@ -2603,8 +2642,11 @@ namespace Game.Maps
return;
}
SpawnData data = Global.ObjectMgr.GetSpawnData(type, spawnId);
if (data == null || data.spawnGroupData == null || !!data.spawnGroupData.flags.HasAnyFlag(SpawnGroupFlags.DynamicSpawnRate))
SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(type, spawnId);
if (data == null)
return;
if (!data.spawnGroupData.flags.HasFlag(SpawnGroupFlags.DynamicSpawnRate))
return;
if (!_zonePlayerCountMap.ContainsKey(obj.GetZoneId()))
@@ -2625,6 +2667,25 @@ namespace Game.Maps
respawnDelay = (uint)Math.Max(Math.Ceiling(respawnDelay * adjustFactor), timeMinimum);
}
public bool ShouldBeSpawnedOnGridLoad<T>(ulong spawnId) { return ShouldBeSpawnedOnGridLoad(SpawnData.TypeFor<T>(), spawnId); }
bool ShouldBeSpawnedOnGridLoad(SpawnObjectType type, ulong spawnId)
{
Cypher.Assert(SpawnData.TypeHasData(type));
// check if the object is on its respawn timer
if (GetRespawnTime(type, spawnId) != 0)
return false;
SpawnMetadata spawnData = Global.ObjectMgr.GetSpawnMetadata(type, spawnId);
// check if the object is part of a spawn group
SpawnGroupTemplateData spawnGroup = spawnData.spawnGroupData;
if (!spawnGroup.flags.HasFlag(SpawnGroupFlags.System))
if (!IsSpawnGroupActive(spawnGroup.groupId))
return false;
return true;
}
SpawnGroupTemplateData GetSpawnGroupData(uint groupId)
{
SpawnGroupTemplateData data = Global.ObjectMgr.GetSpawnGroupData(groupId);
@@ -2644,39 +2705,52 @@ namespace Game.Maps
}
SetSpawnGroupActive(groupId, true); // start processing respawns for the group
foreach (var data in Global.ObjectMgr.GetSpawnDataForGroup(groupId))
List<SpawnData> toSpawn = new();
foreach (var data in Global.ObjectMgr.GetSpawnMetadataForGroup(groupId))
{
Cypher.Assert(groupData.mapId == data.spawnPoint.GetMapId());
// Check if there's already an instance spawned
if (!force)
{
WorldObject obj = GetWorldObjectBySpawnId(data.type, data.spawnId);
if (obj != null)
if ((data.type != SpawnObjectType.Creature) || obj.ToCreature().IsAlive())
continue;
}
Cypher.Assert(groupData.mapId == data.MapId);
long respawnTime = GetRespawnTime(data.type, data.spawnId);
if (respawnTime != 0)
{
if (!force && !ignoreRespawn && respawnTime > GameTime.GetGameTime())
continue;
// we need to remove the respawn time, otherwise we'd end up double spawning
RemoveRespawnTime(data.type, data.spawnId);
}
// don't spawn if the grid isn't loaded (will be handled in grid loader)
if (!IsGridLoaded(data.spawnPoint))
var respawnMap = GetRespawnMapForType(data.type);
if (respawnMap == null)
continue;
// Everything OK, now do the actual (re)spawn
if (force || ignoreRespawn)
RemoveRespawnTime(data.type, data.SpawnId);
bool hasRespawnTimer = respawnMap.ContainsKey(data.SpawnId);
if (SpawnData.TypeHasData(data.type))
{
// has a respawn timer
if (hasRespawnTimer)
continue;
// has a spawn already active
if (!force)
{
WorldObject obj = GetWorldObjectBySpawnId(data.type, data.SpawnId);
if (obj != null)
if ((data.type != SpawnObjectType.Creature) || obj.ToCreature().IsAlive())
continue;
}
toSpawn.Add(data.ToSpawnData());
}
}
foreach (SpawnData data in toSpawn)
{
// don't spawn if the grid isn't loaded (will be handled in grid loader)
if (!IsGridLoaded(data.SpawnPoint))
continue;
// now do the actual (re)spawn
switch (data.type)
{
case SpawnObjectType.Creature:
{
Creature creature = new();
if (!creature.LoadFromDB(data.spawnId, this, true, force))
if (!creature.LoadFromDB(data.SpawnId, this, true, force))
creature.Dispose();
else if (spawnedObjects != null)
spawnedObjects.Add(creature);
@@ -2685,14 +2759,23 @@ namespace Game.Maps
case SpawnObjectType.GameObject:
{
GameObject gameobject = new();
if (!gameobject.LoadFromDB(data.spawnId, this, true))
if (!gameobject.LoadFromDB(data.SpawnId, this, true))
gameobject.Dispose();
else if (spawnedObjects != null)
spawnedObjects.Add(gameobject);
break;
}
case SpawnObjectType.AreaTrigger:
{
AreaTrigger areaTrigger = new AreaTrigger();
if (!areaTrigger.LoadFromDB(data.SpawnId, this, true, false))
areaTrigger.Dispose();
else if (spawnedObjects != null)
spawnedObjects.Add(areaTrigger);
break;
}
default:
Cypher.Assert(false, $"Invalid spawn type {data.type} with spawnId {data.spawnId}");
Cypher.Assert(false, $"Invalid spawn type {data.type} with spawnId {data.SpawnId}");
return false;
}
}
@@ -2704,6 +2787,7 @@ namespace Game.Maps
{
return SpawnGroupDespawn(groupId, deleteRespawnTimes, out _);
}
public bool SpawnGroupDespawn(uint groupId, bool deleteRespawnTimes, out int count)
{
count = 0;
@@ -2714,39 +2798,14 @@ namespace Game.Maps
return false;
}
List<WorldObject> toUnload = new(); // unload after iterating, otherwise iterator invalidation
foreach (var data in Global.ObjectMgr.GetSpawnDataForGroup(groupId))
foreach (var data in Global.ObjectMgr.GetSpawnMetadataForGroup(groupId))
{
Cypher.Assert(groupData.mapId == data.MapId);
if (deleteRespawnTimes)
RemoveRespawnTime(data.type, data.spawnId);
switch (data.type)
{
case SpawnObjectType.Creature:
{
var bounds = GetCreatureBySpawnIdStore().LookupByKey(data.spawnId);
foreach (var creature in bounds)
toUnload.Add(creature);
break;
}
case SpawnObjectType.GameObject:
{
var bounds = GetGameObjectBySpawnIdStore().LookupByKey(data.spawnId);
foreach (var go in bounds)
toUnload.Add(go);
break;
}
default:
Cypher.Assert(false, $"Invalid spawn type {data.type} in spawn data with spawnId {data.spawnId}.");
return false;
}
RemoveRespawnTime(data.type, data.SpawnId);
count += DespawnAll(data.type, data.SpawnId);
}
count = toUnload.Count;
// now do the actual despawning
foreach (WorldObject obj in toUnload)
obj.AddObjectToRemoveList();
SetSpawnGroupActive(groupId, false); // stop processing respawns for the group, too
return true;
}
@@ -3030,19 +3089,23 @@ namespace Game.Maps
public void SaveRespawnTime(SpawnObjectType type, ulong spawnId, uint entry, long respawnTime, uint gridId = 0, SQLTransaction dbTrans = null, bool startup = false)
{
if (spawnId == 0)
SpawnMetadata data = Global.ObjectMgr.GetSpawnMetadata(type, spawnId);
if (data == null)
{
Log.outError(LogFilter.Maps, $"Map {GetId()} attempt to save respawn time for nonexistant spawnid ({type},{spawnId}).");
return;
}
if (respawnTime == 0)
{
// Delete only
RemoveRespawnTime(type, spawnId, dbTrans);
RemoveRespawnTime(data.type, data.SpawnId, dbTrans);
return;
}
RespawnInfo ri = new();
ri.type = type;
ri.spawnId = spawnId;
ri.type = data.type;
ri.spawnId = data.SpawnId;
ri.entry = entry;
ri.respawnTime = respawnTime;
ri.gridId = gridId;
@@ -3083,11 +3146,11 @@ namespace Game.Maps
var spawnId = result.Read<ulong>(1);
var respawnTime = result.Read<long>(2);
if (type < SpawnObjectType.Max)
if (SpawnData.TypeHasData(type))
{
SpawnData data = Global.ObjectMgr.GetSpawnData(type, spawnId);
if (data != null)
SaveRespawnTime(type, spawnId, data.Id, respawnTime, GridDefines.ComputeGridCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY()).GetId(), null, true);
SaveRespawnTime(type, spawnId, data.Id, respawnTime, GridDefines.ComputeGridCoord(data.SpawnPoint.GetPositionX(), data.SpawnPoint.GetPositionY()).GetId(), null, true);
else
Log.outError(LogFilter.Maps, $"Loading saved respawn time of {respawnTime} for spawnid ({type},{spawnId}) - spawn does not exist, ignoring");
}
@@ -3702,6 +3765,8 @@ namespace Game.Maps
public MultiMap<ulong, GameObject> GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore; }
public MultiMap<ulong, AreaTrigger> GetAreaTriggerBySpawnIdStore() { return _areaTriggerBySpawnIdStore; }
public List<Corpse> GetCorpsesInCell(uint cellId)
{
return _corpsesByCell.LookupByKey(cellId);
@@ -3748,12 +3813,17 @@ namespace Game.Maps
public long GetRespawnTime(SpawnObjectType type, ulong spawnId)
{
var respawnDic = GetRespawnMapForType(type);
var respawnInfo = respawnDic.LookupByKey(spawnId);
return (respawnInfo == null) ? 0 : respawnInfo.respawnTime;
var map = GetRespawnMapForType(type);
if (map != null)
{
var respawnInfo = map.LookupByKey(spawnId);
return (respawnInfo == null) ? 0 : respawnInfo.respawnTime;
}
return 0;
}
public long GetCreatureRespawnTime(ulong spawnId) { return GetRespawnTime(SpawnObjectType.Creature, spawnId); }
public long GetGORespawnTime(ulong spawnId) { return GetRespawnTime(SpawnObjectType.GameObject, spawnId); }
void SetTimer(uint t)
@@ -3851,7 +3921,7 @@ namespace Game.Maps
return go ? go.ToTransport() : null;
}
Creature GetCreatureBySpawnId(ulong spawnId)
public Creature GetCreatureBySpawnId(ulong spawnId)
{
var bounds = GetCreatureBySpawnIdStore().LookupByKey(spawnId);
if (bounds.Empty())
@@ -3862,7 +3932,7 @@ namespace Game.Maps
return foundCreature != null ? foundCreature : bounds[0];
}
GameObject GetGameObjectBySpawnId(ulong spawnId)
public GameObject GetGameObjectBySpawnId(ulong spawnId)
{
var bounds = GetGameObjectBySpawnIdStore().LookupByKey(spawnId);
if (bounds.Empty())
@@ -3873,6 +3943,15 @@ namespace Game.Maps
return foundGameObject != null ? foundGameObject : bounds[0];
}
public AreaTrigger GetAreaTriggerBySpawnId(ulong spawnId)
{
var bounds = GetAreaTriggerBySpawnIdStore().LookupByKey(spawnId);
if (bounds.Empty())
return null;
return bounds.FirstOrDefault();
}
public WorldObject GetWorldObjectBySpawnId(SpawnObjectType type, ulong spawnId)
{
switch (type)
@@ -3881,6 +3960,8 @@ namespace Game.Maps
return GetCreatureBySpawnId(spawnId);
case SpawnObjectType.GameObject:
return GetGameObjectBySpawnId(spawnId);
case SpawnObjectType.AreaTrigger:
return GetAreaTriggerBySpawnId(spawnId);
default:
return null;
}
@@ -4986,6 +5067,7 @@ namespace Game.Maps
Dictionary<ObjectGuid, WorldObject> _objectsStore = new();
MultiMap<ulong, Creature> _creatureBySpawnIdStore = new();
MultiMap<ulong, GameObject> _gameobjectBySpawnIdStore = new();
MultiMap<ulong, AreaTrigger> _areaTriggerBySpawnIdStore = new();
MultiMap<uint, Corpse> _corpsesByCell = new();
Dictionary<ObjectGuid, Corpse> _corpsesByPlayer = new();
List<Corpse> _corpseBones = new();
+9 -43
View File
@@ -90,52 +90,18 @@ namespace Game.Maps
{
foreach (var guid in guid_set)
{
// Don't spawn at all if there's a respawn timer
if (!map.ShouldBeSpawnedOnGridLoad<T>(guid))
continue;
T obj = new();
// Don't spawn at all if there's a respawn time
if ((obj.IsTypeId(TypeId.Unit) && map.GetCreatureRespawnTime(guid) == 0) || (obj.IsTypeId(TypeId.GameObject) && map.GetGORespawnTime(guid) == 0) || obj.IsTypeId(TypeId.AreaTrigger))
if (!obj.LoadFromDB(guid, map, false, false))
{
//TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid);
if (obj.IsTypeId(TypeId.Unit))
{
CreatureData cdata = Global.ObjectMgr.GetCreatureData(guid);
Cypher.Assert(cdata != null, $"Tried to load creature with spawnId {guid}, but no such creature exists.");
SpawnGroupTemplateData group = cdata.spawnGroupData;
// If creature in manual spawn group, don't spawn here, unless group is already active.
if (!group.flags.HasAnyFlag(SpawnGroupFlags.System))
{
if (!map.IsSpawnGroupActive(group.groupId))
{
obj.Dispose();
continue;
}
}
}
else if (obj.IsTypeId(TypeId.GameObject))
{
// If gameobject in manual spawn group, don't spawn here, unless group is already active.
GameObjectData godata = Global.ObjectMgr.GetGameObjectData(guid);
Cypher.Assert(godata != null, $"Tried to load gameobject with spawnId {guid}, but no such object exists.");
if (!godata.spawnGroupData.flags.HasAnyFlag(SpawnGroupFlags.System))
{
if (!map.IsSpawnGroupActive(godata.spawnGroupData.groupId))
{
obj.Dispose();
continue;
}
}
}
if (!obj.LoadFromDB(guid, map, false, false))
{
obj.Dispose();
continue;
}
AddObjectHelper(cell, ref count, map, obj);
}
else
obj.Dispose();
continue;
}
AddObjectHelper(cell, ref count, map, obj);
}
}
+42 -13
View File
@@ -29,29 +29,58 @@ namespace Game.Maps
public SpawnGroupFlags flags;
}
public class SpawnData
public class SpawnData : SpawnMetadata
{
public SpawnObjectType type;
public ulong spawnId;
public uint Id; // entry in respective _template table
public WorldLocation spawnPoint;
public PhaseUseFlagsValues phaseUseFlags;
public uint phaseId;
public uint phaseGroup;
public Position SpawnPoint;
public PhaseUseFlagsValues PhaseUseFlags;
public uint PhaseId;
public uint PhaseGroup;
public int terrainSwapMap;
public int spawntimesecs;
public List<Difficulty> spawnDifficulties;
public SpawnGroupTemplateData spawnGroupData;
public uint ScriptId;
public bool dbData;
public SpawnData(SpawnObjectType t)
public SpawnData(SpawnObjectType t) : base(t)
{
type = t;
spawnPoint = new WorldLocation();
SpawnPoint = new Position();
terrainSwapMap = -1;
spawnDifficulties = new List<Difficulty>();
dbData = true;
}
public static SpawnObjectType TypeFor<T>()
{
switch (typeof(T).Name)
{
case nameof(Creature):
return SpawnObjectType.Creature;
case nameof(GameObject):
return SpawnObjectType.GameObject;
case nameof(AreaTrigger):
return SpawnObjectType.AreaTrigger;
default:
return SpawnObjectType.NumSpawnTypes;
}
}
}
public class SpawnMetadata
{
public SpawnObjectType type;
public ulong SpawnId;
public uint MapId = 0xFFFFFFFF;
public bool dbData = true;
public SpawnGroupTemplateData spawnGroupData = null;
public static bool TypeInMask(SpawnObjectType type, SpawnObjectTypeMask mask) { return ((1 << (int)type) & (int)mask) != 0; }
public static bool TypeHasData(SpawnObjectType type) { return type < SpawnObjectType.NumSpawnTypesWithData; }
public static bool TypeIsValid(SpawnObjectType type) { return type < SpawnObjectType.NumSpawnTypes; }
public SpawnMetadata(SpawnObjectType t)
{
type = t;
}
public SpawnData ToSpawnData() { return TypeHasData(type) ? (SpawnData)this : null; }
}
}
+8 -6
View File
@@ -383,6 +383,8 @@ namespace Game
return IsPartOfAPool<Creature>(spawnId);
case SpawnObjectType.GameObject:
return IsPartOfAPool<GameObject>(spawnId);
case SpawnObjectType.AreaTrigger:
return 0;
default:
Cypher.Assert(false, $"Invalid spawn type {type} passed to PoolMgr.IsPartOfPool (with spawnId {spawnId})");
return 0;
@@ -481,7 +483,7 @@ namespace Game
if (data != null)
{
Global.ObjectMgr.RemoveCreatureFromGrid(guid, data);
Map map = Global.MapMgr.FindMap(data.spawnPoint.GetMapId(), 0);
Map map = Global.MapMgr.FindMap(data.MapId, 0);
if (map != null && !map.Instanceable())
{
var creatureBounds = map.GetCreatureBySpawnIdStore().LookupByKey(guid);
@@ -503,7 +505,7 @@ namespace Game
if (data != null)
{
Global.ObjectMgr.RemoveGameObjectFromGrid(guid, data);
Map map = Global.MapMgr.FindMap(data.spawnPoint.GetMapId(), 0);
Map map = Global.MapMgr.FindMap(data.MapId, 0);
if (map != null && !map.Instanceable())
{
var gameobjectBounds = map.GetGameObjectBySpawnIdStore().LookupByKey(guid);
@@ -620,9 +622,9 @@ namespace Game
Global.ObjectMgr.AddCreatureToGrid(obj.guid, data);
// Spawn if necessary (loaded grids only)
Map map = Global.MapMgr.FindMap(data.spawnPoint.GetMapId(), 0);
Map map = Global.MapMgr.FindMap(data.MapId, 0);
// We use spawn coords to spawn
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.spawnPoint))
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.SpawnPoint))
Creature.CreateCreatureFromDB(obj.guid, map);
}
}
@@ -635,9 +637,9 @@ namespace Game
Global.ObjectMgr.AddGameObjectToGrid(obj.guid, data);
// Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed
Map map = Global.MapMgr.FindMap(data.spawnPoint.GetMapId(), 0);
Map map = Global.MapMgr.FindMap(data.MapId, 0);
// We use current coords to unspawn, not spawn coords since creature can have changed grid
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.spawnPoint))
if (map != null && !map.Instanceable() && map.IsGridLoaded(data.SpawnPoint))
{
GameObject go = GameObject.CreateGameObjectFromDB(obj.guid, map, false);
if (go)