diff --git a/Source/Framework/Constants/MapConst.cs b/Source/Framework/Constants/MapConst.cs index 1a29983a4..5d2a16a93 100644 --- a/Source/Framework/Constants/MapConst.cs +++ b/Source/Framework/Constants/MapConst.cs @@ -72,7 +72,7 @@ namespace Framework.Constants public const uint mmapMagic = 0x4D4D4150; // 'MMAP' public const int mmapVersion = 9; - public const string VMapMagic = "VMAP_4.8"; + public const string VMapMagic = "VMAP_4.9"; public const float VMAPInvalidHeightValue = -200000.0f; } diff --git a/Source/Game/Chat/Commands/NPCCommands.cs b/Source/Game/Chat/Commands/NPCCommands.cs index a5f2edb4d..72ed00812 100644 --- a/Source/Game/Chat/Commands/NPCCommands.cs +++ b/Source/Game/Chat/Commands/NPCCommands.cs @@ -150,17 +150,17 @@ namespace Game.Chat handler.SendSysMessage(CypherStrings.NpcinfoHealth, target.GetCreateHealth(), target.GetMaxHealth(), target.GetHealth()); handler.SendSysMessage(CypherStrings.NpcinfoInhabitType, cInfo.InhabitType); - handler.SendSysMessage(CypherStrings.NpcinfoUnitFieldFlags, target.m_unitData.Flags); + handler.SendSysMessage(CypherStrings.NpcinfoUnitFieldFlags, (uint)target.m_unitData.Flags); foreach (UnitFlags value in Enum.GetValues(typeof(UnitFlags))) if (target.HasUnitFlag(value)) handler.SendSysMessage("{0} (0x{1:X})", (UnitFlags)value, value); - handler.SendSysMessage(CypherStrings.NpcinfoUnitFieldFlags2, target.m_unitData.Flags2); + handler.SendSysMessage(CypherStrings.NpcinfoUnitFieldFlags2, (uint)target.m_unitData.Flags2); foreach (UnitFlags2 value in Enum.GetValues(typeof(UnitFlags2))) if (target.HasUnitFlag2(value)) handler.SendSysMessage("{0} (0x{1:X})", (UnitFlags2)value, value); - handler.SendSysMessage(CypherStrings.NpcinfoUnitFieldFlags3, target.m_unitData.Flags3); + handler.SendSysMessage(CypherStrings.NpcinfoUnitFieldFlags3, (uint)target.m_unitData.Flags3); foreach (UnitFlags3 value in Enum.GetValues(typeof(UnitFlags3))) if (target.HasUnitFlag3(value)) handler.SendSysMessage("{0} (0x{1:X})", (UnitFlags3)value, value); @@ -185,7 +185,7 @@ namespace Game.Chat handler.SendSysMessage("{0} (0x{1:X})", (CreatureFlagsExtra)value, value); handler.SendSysMessage(CypherStrings.NpcinfoNpcFlags, npcflags); - foreach (ulong value in Enum.GetValues(typeof(NPCFlags))) + foreach (uint value in Enum.GetValues(typeof(NPCFlags))) if (npcflags.HasAnyFlag(value)) handler.SendSysMessage("{0} (0x{1:X})", (NPCFlags)value, value); diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index 96d2a8f9d..2055b755c 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -1118,56 +1118,56 @@ namespace Game.DataStorage { case ExpectedStatType.CreatureHealth: value = expectedStatRecord.CreatureHealth; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.CreatureHealthMod : 1.0f); if (classMod != null) value *= classMod.CreatureHealthMod; break; case ExpectedStatType.PlayerHealth: value = expectedStatRecord.PlayerHealth; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.PlayerHealthMod : 1.0f); if (classMod != null) value *= classMod.PlayerHealthMod; break; case ExpectedStatType.CreatureAutoAttackDps: value = expectedStatRecord.CreatureAutoAttackDps; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.CreatureAutoAttackDPSMod : 1.0f); if (classMod != null) value *= classMod.CreatureAutoAttackDPSMod; break; case ExpectedStatType.CreatureArmor: value = expectedStatRecord.CreatureArmor; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.CreatureArmorMod : 1.0f); if (classMod != null) value *= classMod.CreatureArmorMod; break; case ExpectedStatType.PlayerMana: value = expectedStatRecord.PlayerMana; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.PlayerManaMod : 1.0f); if (classMod != null) value *= classMod.PlayerManaMod; break; case ExpectedStatType.PlayerPrimaryStat: value = expectedStatRecord.PlayerPrimaryStat; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.PlayerPrimaryStatMod : 1.0f); if (classMod != null) value *= classMod.PlayerPrimaryStatMod; break; case ExpectedStatType.PlayerSecondaryStat: value = expectedStatRecord.PlayerSecondaryStat; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.PlayerSecondaryStatMod : 1.0f); if (classMod != null) value *= classMod.PlayerSecondaryStatMod; break; case ExpectedStatType.ArmorConstant: value = expectedStatRecord.ArmorConstant; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.ArmorConstantMod : 1.0f); if (classMod != null) value *= classMod.ArmorConstantMod; @@ -1176,7 +1176,7 @@ namespace Game.DataStorage break; case ExpectedStatType.CreatureSpellDamage: value = expectedStatRecord.CreatureSpellDamage; - if (contentTuningMods != null) + if (!contentTuningMods.Empty()) value *= contentTuningMods.Sum(expectedStatMod => expectedStatMod != null ? expectedStatMod.CreatureSpellDamageMod : 1.0f); if (classMod != null) value *= classMod.CreatureSpellDamageMod; diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 397de7fd6..382f16268 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -2478,6 +2478,7 @@ namespace Game.Entities CreatureTemplate cInfo = GetCreatureTemplate(); CreatureLevelScaling scaling = cInfo.GetLevelScaling(GetMap().GetDifficultyID()); float baseHealth = Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, level, cInfo.GetHealthScalingExpansion(), scaling.ContentTuningID, (Class)cInfo.UnitClass); + return (ulong)(baseHealth * cInfo.ModHealth * cInfo.ModHealthExtra); } diff --git a/Source/Game/Entities/Object/Position.cs b/Source/Game/Entities/Object/Position.cs index 5cf5b5b94..05dad5de2 100644 --- a/Source/Game/Entities/Object/Position.cs +++ b/Source/Game/Entities/Object/Position.cs @@ -43,6 +43,14 @@ namespace Game.Entities posZ = vector.Z; } + public Position(Position position) + { + posX = position.posX; + posY = position.posY; + posZ = position.posZ; + Orientation = position.Orientation; + } + public float GetPositionX() { return posX; diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index 3fbdfedd6..7b6d9a4b0 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -488,8 +488,8 @@ namespace Game.Entities if (val == 0) val = 1; - ulong health = GetHealth(); SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MaxHealth), val); + ulong health = GetHealth(); // group update if (IsTypeId(TypeId.Player)) diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 9ecd0a798..f73d88727 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -678,6 +678,10 @@ namespace Game.Maps Cypher.Assert(_zonePlayerCountMap[oldZone] != 0, $"A player left zone {oldZone} (went to {newZone}) - but there were no players in the zone!"); --_zonePlayerCountMap[oldZone]; } + + if (!_zonePlayerCountMap.ContainsKey(newZone)) + _zonePlayerCountMap[newZone] = 0; + ++_zonePlayerCountMap[newZone]; } @@ -2172,8 +2176,10 @@ namespace Game.Maps if (vmapData.areaInfo.HasValue) data.areaInfo.Set(new PositionFullTerrainStatus.AreaInfo(vmapData.areaInfo.Value.AdtId, vmapData.areaInfo.Value.RootId, vmapData.areaInfo.Value.GroupId, vmapData.areaInfo.Value.MogpFlags)); + float mapHeight = MapConst.InvalidHeight; GridMap gmap = GetGridMap(terrainMapId, x, y); - float mapHeight = gmap.GetHeight(x, y); + if (gmap != null) + mapHeight = gmap.GetHeight(x, y); // area lookup AreaTableRecord areaEntry = null; @@ -2661,8 +2667,8 @@ namespace Game.Maps Cypher.Assert(info != null); // spawnid store - GetRespawnMapForType(info.type).Remove(info.spawnId); - Cypher.Assert(GetRespawnMapForType(info.type).Count == 1, $"Respawn stores inconsistent for map {GetId()}, spawnid {info.spawnId} (type {info.type})"); + 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); @@ -5646,6 +5652,8 @@ namespace Game.Maps { public int Compare(RespawnInfo a, RespawnInfo b) { + if (a == b) + return 0; if (a.respawnTime != b.respawnTime) return a.respawnTime.CompareTo(b.respawnTime); if (a.spawnId != b.spawnId) diff --git a/Source/Game/Movement/Generators/RandomMovement.cs b/Source/Game/Movement/Generators/RandomMovement.cs index 987012e0e..baefabba8 100644 --- a/Source/Game/Movement/Generators/RandomMovement.cs +++ b/Source/Game/Movement/Generators/RandomMovement.cs @@ -92,7 +92,7 @@ namespace Game.Movement owner.AddUnitState(UnitState.RoamingMove); - Position position = _reference; + Position position = new Position(_reference); float distance = RandomHelper.FRand(0.0f, 1.0f) * _wanderDistance; float angle = RandomHelper.FRand(0.0f, 1.0f) * MathF.PI * 2.0f; owner.MovePositionToFirstCollision(ref position, distance, angle); diff --git a/Source/Game/Spells/SpellManager.cs b/Source/Game/Spells/SpellManager.cs index a4ed51eda..c0b86abea 100644 --- a/Source/Game/Spells/SpellManager.cs +++ b/Source/Game/Spells/SpellManager.cs @@ -455,7 +455,7 @@ namespace Game.Entities { do { - procEntry = mSpellProcMap.LookupByKey((spellInfo.Id, difficulty.FallbackDifficultyID)); + procEntry = mSpellProcMap.LookupByKey((spellInfo.Id, (Difficulty)difficulty.FallbackDifficultyID)); if (procEntry != null) return procEntry;