hondacrx
2023-05-19 16:23:44 -04:00
parent 24b0836710
commit dfceb4c044
40 changed files with 1910 additions and 1549 deletions
+1 -1
View File
@@ -389,7 +389,7 @@ namespace Game.DataStorage
foreach (var entry in TaxiPathNodeStorage.Values)
TaxiPathNodesByPath[entry.PathID][entry.NodeIndex] = entry;
var taxiMaskSize = ((TaxiNodesStorage.GetNumRows() - 1) / 8) + 1;
var taxiMaskSize = ((TaxiNodesStorage.GetNumRows() - 1) / (8 * 64) + 1) * 8;
TaxiNodesMask = new byte[taxiMaskSize];
OldContinentsNodesMask = new byte[taxiMaskSize];
HordeTaxiNodesMask = new byte[taxiMaskSize];
@@ -19,15 +19,16 @@ namespace Game.DataStorage
{
class DBReader
{
private const uint WDC3FmtSig = 0x33434457; // WDC3
private const uint WDC3FmtSig = 0x34434457; // WDC3
public WDCHeader Header;
public FieldMetaData[] FieldMeta;
public ColumnMetaData[] ColumnMeta;
public Value32[][] PalletData;
public Dictionary<int, Value32>[] CommonData;
Dictionary<int, int[]> _encryptedIDs;
public Dictionary<int, WDC3Row> Records = new();
public Dictionary<int, WDC4Row> Records = new();
public bool Load(Stream stream)
{
@@ -77,7 +78,6 @@ namespace Game.DataStorage
// common data
CommonData = new Dictionary<int, Value32>[ColumnMeta.Length];
for (int i = 0; i < ColumnMeta.Length; i++)
{
if (ColumnMeta[i].CompressionType == DB2ColumnCompression.Common)
@@ -90,17 +90,23 @@ namespace Game.DataStorage
}
}
long previousRecordCount = 0;
for (int sectionIndex = 0; sectionIndex < Header.SectionsCount; sectionIndex++)
// encrypted IDs
_encryptedIDs = new();
for (int i = 1; i < Header.SectionsCount; i++)
{
if (sections[sectionIndex].TactKeyLookup != 0)// && !hasTactKeyFunc(sections[sectionIndex].TactKeyLookup))
{
previousRecordCount += sections[sectionIndex].NumRecords;
//Console.WriteLine("Detected db2 with encrypted section! HasKey {0}", CASC.HasKey(Sections[sectionIndex].TactKeyLookup));
continue;
}
var encryptedIDCount = reader.ReadUInt32();
reader.BaseStream.Position = sections[sectionIndex].FileOffset;
// If tactkey in section header is 0'd out, skip these IDs
if (sections[i].TactKeyLookup == 0 || sections[i].TactKeyLookup == 0x5452494E49545900)
reader.BaseStream.Position += encryptedIDCount * 4;
else
_encryptedIDs.Add(i, reader.ReadArray<int>(encryptedIDCount));
}
long previousRecordCount = 0;
foreach (var section in sections)
{
reader.BaseStream.Position = section.FileOffset;
byte[] recordsData;
Dictionary<long, string> stringsTable = null;
@@ -109,12 +115,12 @@ namespace Game.DataStorage
if (!Header.HasOffsetTable())
{
// records data
recordsData = reader.ReadBytes((int)(sections[sectionIndex].NumRecords * Header.RecordSize));
recordsData = reader.ReadBytes((int)(section.NumRecords * Header.RecordSize));
// string data
stringsTable = new Dictionary<long, string>();
for (int i = 0; i < sections[sectionIndex].StringTableSize;)
for (int i = 0; i < section.StringTableSize;)
{
long oldPos = reader.BaseStream.Position;
@@ -126,31 +132,63 @@ namespace Game.DataStorage
else
{
// sparse data with inlined strings
recordsData = reader.ReadBytes(sections[sectionIndex].SparseTableOffset - sections[sectionIndex].FileOffset);
recordsData = reader.ReadBytes(section.OffsetRecordsEndOffset - section.FileOffset);
if (reader.BaseStream.Position != sections[sectionIndex].SparseTableOffset)
if (reader.BaseStream.Position != section.OffsetRecordsEndOffset)
throw new Exception("reader.BaseStream.Position != sections[sectionIndex].SparseTableOffset");
}
// skip encrypted sections => has tact key + record data is zero filled
if (section.TactKeyLookup != 0 && Array.TrueForAll(recordsData, x => x == 0))
{
bool completelyZero = false;
if (section.IndexDataSize > 0 || section.CopyTableCount > 0)
{
// this will be the record id from m_indexData or m_copyData
// if this is zero then the id for this record will be zero which is invalid
completelyZero = reader.ReadInt32() == 0;
reader.BaseStream.Position -= 4;
}
else if (section.OffsetMapIDCount > 0)
{
// this will be the first m_sparseEntries entry
// confirm it's size is not zero otherwise it is invalid
completelyZero = reader.Read<SparseEntry>().Size == 0;
reader.BaseStream.Position -= 6;
}
else
{
// there is no additional data and recordsData is already known to be zeroed
// therefore the record will have an id of zero which is invalid
completelyZero = true;
}
if (completelyZero)
{
previousRecordCount += section.NumRecords;
continue;
}
}
Array.Resize(ref recordsData, recordsData.Length + 8); // pad with extra zeros so we don't crash when reading
// index data
int[] indexData = reader.ReadArray<int>((uint)(sections[sectionIndex].IndexDataSize / 4));
bool isIndexEmpty = Header.HasIndexTable() && indexData.Count(i => i == 0) == sections[sectionIndex].NumRecords;
int[] indexData = reader.ReadArray<int>((uint)(section.IndexDataSize / 4));
bool isIndexEmpty = Header.HasIndexTable() && indexData.Count(i => i == 0) == section.NumRecords;
// duplicate rows data
Dictionary<int, int> copyData = new();
for (int i = 0; i < sections[sectionIndex].NumCopyRecords; i++)
for (int i = 0; i < section.CopyTableCount; i++)
copyData[reader.ReadInt32()] = reader.ReadInt32();
if (sections[sectionIndex].NumSparseRecords > 0)
sparseEntries = reader.ReadArray<SparseEntry>((uint)sections[sectionIndex].NumSparseRecords);
if (section.OffsetMapIDCount > 0)
sparseEntries = reader.ReadArray<SparseEntry>((uint)section.OffsetMapIDCount);
// reference data
ReferenceData refData = null;
if (sections[sectionIndex].ParentLookupDataSize > 0)
if (section.ParentLookupDataSize > 0)
{
refData = new ReferenceData
{
@@ -172,10 +210,9 @@ namespace Game.DataStorage
};
}
if (sections[sectionIndex].NumSparseRecords > 0)
if (section.OffsetMapIDCount > 0)
{
// TODO: use this shit
int[] sparseIndexData = reader.ReadArray<int>((uint)sections[sectionIndex].NumSparseRecords);
int[] sparseIndexData = reader.ReadArray<int>((uint)section.OffsetMapIDCount);
if (Header.HasIndexTable() && indexData.Length != sparseIndexData.Length)
throw new Exception("indexData.Length != sparseIndexData.Length");
@@ -185,11 +222,11 @@ namespace Game.DataStorage
BitReader bitReader = new(recordsData);
for (int i = 0; i < sections[sectionIndex].NumRecords; ++i)
for (int i = 0; i < section.NumRecords; ++i)
{
bitReader.Position = 0;
if (Header.HasOffsetTable())
bitReader.Offset = sparseEntries[i].Offset - sections[sectionIndex].FileOffset;
bitReader.Offset = sparseEntries[i].Offset - section.FileOffset;
else
bitReader.Offset = i * (int)Header.RecordSize;
@@ -198,7 +235,7 @@ namespace Game.DataStorage
long recordIndex = i + previousRecordCount;
long recordOffset = (recordIndex * Header.RecordSize) - (Header.RecordCount * Header.RecordSize);
var rec = new WDC3Row(this, bitReader, (int)recordOffset, Header.HasIndexTable() ? (isIndexEmpty ? i : indexData[i]) : -1, hasRef ? refId : -1, stringsTable);
var rec = new WDC4Row(this, bitReader, (int)recordOffset, Header.HasIndexTable() ? (isIndexEmpty ? i : indexData[i]) : -1, hasRef ? refId : -1, stringsTable);
Records.Add(rec.Id, rec);
}
@@ -212,7 +249,7 @@ namespace Game.DataStorage
}
}
previousRecordCount += sections[sectionIndex].NumRecords;
previousRecordCount += section.NumRecords;
}
}
@@ -220,7 +257,7 @@ namespace Game.DataStorage
}
}
class WDC3Row
class WDC4Row
{
private BitReader _data;
private int _dataOffset;
@@ -236,7 +273,7 @@ namespace Game.DataStorage
private Dictionary<int, Value32>[] _commonData;
private Dictionary<long, string> _stringsTable;
public WDC3Row(DBReader reader, BitReader data, int recordsOffset, int id, int refId, Dictionary<long, string> stringsTable)
public WDC4Row(DBReader reader, BitReader data, int recordsOffset, int id, int refId, Dictionary<long, string> stringsTable)
{
_data = data;
_recordsOffset = recordsOffset;
@@ -527,9 +564,9 @@ namespace Game.DataStorage
return obj;
}
public WDC3Row Clone()
public WDC4Row Clone()
{
return (WDC3Row)MemberwiseClone();
return (WDC4Row)MemberwiseClone();
}
}
@@ -537,12 +574,12 @@ namespace Game.DataStorage
{
public bool HasIndexTable()
{
return Convert.ToBoolean(Flags & HeaderFlags.IndexMap);
return Convert.ToBoolean(Flags & HeaderFlags.Index);
}
public bool HasOffsetTable()
{
return Convert.ToBoolean(Flags & HeaderFlags.OffsetMap);
return Convert.ToBoolean(Flags & HeaderFlags.Sparse);
}
public uint Signature;
@@ -647,11 +684,11 @@ namespace Game.DataStorage
public int FileOffset;
public int NumRecords;
public int StringTableSize;
public int SparseTableOffset; // CatalogDataOffset, absolute value, {uint offset, ushort size}[MaxId - MinId + 1]
public int OffsetRecordsEndOffset; // CatalogDataOffset, absolute value, {uint offset, ushort size}[MaxId - MinId + 1]
public int IndexDataSize; // int indexData[IndexDataSize / 4]
public int ParentLookupDataSize; // uint NumRecords, uint minId, uint maxId, {uint id, uint index}[NumRecords], questionable usefulness...
public int NumSparseRecords;
public int NumCopyRecords;
public int OffsetMapIDCount;
public int CopyTableCount;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
+4 -1
View File
@@ -122,6 +122,7 @@ namespace Game.DataStorage
public ushort UiOrderIndex;
public int Flags;
public int AddedInPatch;
public int SoundKitID;
public int[] SwatchColor = new int[2];
}
@@ -147,6 +148,7 @@ namespace Game.DataStorage
public int ChrCustomizationDisplayInfoID;
public int ChrCustItemGeoModifyID;
public int ChrCustomizationVoiceID;
public int AnimKitID;
}
public sealed class ChrCustomizationOptionRecord
@@ -329,6 +331,7 @@ namespace Game.DataStorage
public int TargetLevelMin;
public int TargetLevelMax;
public int MinItemLevel;
public float QuestXpMultiplier;
public ContentTuningFlag GetFlags() { return (ContentTuningFlag)Flags; }
@@ -606,7 +609,7 @@ namespace Game.DataStorage
public Vector2 Pos;
public Vector2 PreSLSquishPos;
public uint Id;
public ushort CurveID;
public uint CurveID;
public byte OrderIndex;
}
}
@@ -129,6 +129,8 @@ namespace Game.DataStorage
public ushort ChildItemLevelSelectorID;
public uint ChildItemBonusListGroupID;
public uint IblGroupPointsModSetID;
public int Unknown1010_1;
public int Unknown1010_2;
public uint ParentItemBonusTreeID;
}
@@ -227,5 +227,6 @@ namespace Game.DataStorage
public byte KeyID;
public uint AudioFileDataID;
public uint SubtitleFileDataID;
public int SubtitleFileFormat;
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ namespace Game.DataStorage
public uint Id;
public int ParentUiMapID;
public int Flags;
public uint System;
public byte System;
public UiMapType Type;
public int BountySetID;
public uint BountyDisplayLocation;
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Game.DataStorage
{
public uint Id;
public VehicleFlags Flags;
public byte FlagsB;
public int FlagsB;
public float TurnSpeed;
public float PitchSpeed;
public float PitchMin;
@@ -1430,6 +1430,7 @@ namespace Game.Entities
public uint turnpersonallootsecurityoff; // 22 turn personal loot security off, enum { false, true, }; Default: false
public uint ClearObjectVignetteonOpening; // 23 Clear Object Vignette on Opening, enum { false, true, }; Default: false
public uint InteractRadiusOverride; // 24 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0
public uint Overrideminimaptrackingicon; // 25 Override minimap tracking icon, References: UiTextureAtlasMember, NoValue = 0
}
public struct challengemodereward
File diff suppressed because it is too large Load Diff
@@ -265,6 +265,7 @@ namespace Game.Entities
bool HasSpline = unit.IsSplineEnabled();
bool HasInertia = unit.m_movementInfo.inertia.HasValue;
bool HasAdvFlying = unit.m_movementInfo.advFlying.HasValue;
bool HasStandingOnGameObjectGUID = unit.m_movementInfo.standingOnGameObjectGUID.HasValue;
data.WritePackedGuid(GetGUID()); // MoverGUID
@@ -287,6 +288,7 @@ namespace Game.Entities
//for (public uint i = 0; i < RemoveForcesIDs.Count; ++i)
// *data << ObjectGuid(RemoveForcesIDs);
data.WriteBit(HasStandingOnGameObjectGUID); // HasStandingOnGameObjectGUID
data.WriteBit(!unit.m_movementInfo.transport.guid.IsEmpty()); // HasTransport
data.WriteBit(HasFall); // HasFall
data.WriteBit(HasSpline); // HasSpline - marks that the unit uses spline movement
@@ -297,6 +299,9 @@ namespace Game.Entities
if (!unit.m_movementInfo.transport.guid.IsEmpty())
MovementExtensions.WriteTransportInfo(data, unit.m_movementInfo.transport);
if (HasStandingOnGameObjectGUID)
data.WritePackedGuid(unit.m_movementInfo.standingOnGameObjectGUID.Value);
if (HasInertia)
{
data.WriteInt32(unit.m_movementInfo.inertia.Value.id);
@@ -3774,6 +3779,7 @@ namespace Game.Entities
public JumpInfo jump;
public float stepUpStartElevation { get; set; }
public AdvFlying? advFlying;
public ObjectGuid? standingOnGameObjectGUID;
public MovementInfo()
{
+4 -26
View File
@@ -3684,19 +3684,8 @@ namespace Game.Entities
stmt.AddValue(index++, GetDrunkValue());
stmt.AddValue(index++, GetHealth());
int storedPowers = 0;
for (PowerType powerType = 0; powerType < PowerType.Max; ++powerType)
{
if (GetPowerIndex(powerType) != (int)PowerType.Max)
{
stmt.AddValue(index++, m_unitData.Power[storedPowers]);
if (++storedPowers >= (int)PowerType.MaxPerClass)
break;
}
}
for (; storedPowers < (int)PowerType.MaxPerClass; ++storedPowers)
stmt.AddValue(index++, 0);
for (int i = 0; i < (int)PowerType.MaxPerClass; ++i)
stmt.AddValue(index++, m_unitData.Power[i]);
stmt.AddValue(index++, GetSession().GetLatency());
stmt.AddValue(index++, GetActiveTalentGroup());
@@ -3830,19 +3819,8 @@ namespace Game.Entities
stmt.AddValue(index++, GetDrunkValue());
stmt.AddValue(index++, GetHealth());
int storedPowers = 0;
for (PowerType powerType = 0; powerType < PowerType.Max; ++powerType)
{
if (GetPowerIndex(powerType) != (int)PowerType.Max)
{
stmt.AddValue(index++, m_unitData.Power[storedPowers]);
if (++storedPowers >= (int)PowerType.MaxPerClass)
break;
}
}
for (; storedPowers < (int)PowerType.MaxPerClass; ++storedPowers)
stmt.AddValue(index++, 0);
for (int i = 0; i < (int)PowerType.MaxPerClass; ++i)
stmt.AddValue(index++, m_unitData.Power[i]);
stmt.AddValue(index++, GetSession().GetLatency());
stmt.AddValue(index++, GetActiveTalentGroup());
+37
View File
@@ -5395,6 +5395,43 @@ namespace Game.Entities
GetSceneMgr().TriggerDelayedScenes();
}
public void AddSpellCategoryCooldownMod(int spellCategoryId, int mod)
{
int categoryIndex = m_activePlayerData.CategoryCooldownMods.FindIndexIf(mod => mod.SpellCategoryID == spellCategoryId);
if (categoryIndex < 0)
{
CategoryCooldownMod newMod = new();
newMod.SpellCategoryID = spellCategoryId;
newMod.ModCooldown = -mod;
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CategoryCooldownMods), newMod);
}
else
{
CategoryCooldownMod g = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CategoryCooldownMods, categoryIndex);
SetUpdateFieldValue(ref g.ModCooldown, m_activePlayerData.CategoryCooldownMods[categoryIndex].ModCooldown - mod);
}
}
public void RemoveSpellCategoryCooldownMod(int spellCategoryId, int mod)
{
int categoryIndex = m_activePlayerData.CategoryCooldownMods.FindIndexIf(mod => mod.SpellCategoryID == spellCategoryId);
if (categoryIndex < 0)
return;
if (m_activePlayerData.CategoryCooldownMods[categoryIndex].ModCooldown + mod == 0)
{
RemoveDynamicUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CategoryCooldownMods), categoryIndex);
}
else
{
CategoryCooldownMod g = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CategoryCooldownMods, categoryIndex);
SetUpdateFieldValue(ref g.ModCooldown, m_activePlayerData.CategoryCooldownMods[categoryIndex].ModCooldown + mod);
}
}
public void RemoveSocial()
{
SocialMgr.RemovePlayerSocial(GetGUID());
+2 -2
View File
@@ -19,7 +19,7 @@ namespace Game.Entities
public void InitTaxiNodesForLevel(Race race, Class chrClass, uint level)
{
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / 8) + 1];
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / (8 * 64) + 1) * 8];
// class specific initial known nodes
if (chrClass == Class.Deathknight)
@@ -93,7 +93,7 @@ namespace Game.Entities
public void LoadTaxiMask(string data)
{
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / 8) + 1];
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / (8 * 64) + 1) * 8];
var split = new StringArray(data, ' ');
+7
View File
@@ -140,6 +140,13 @@ namespace Game.Entities
case UnitMods.ArcaneCharges:
case UnitMods.Fury:
case UnitMods.Pain:
case UnitMods.Essence:
case UnitMods.RuneBlood:
case UnitMods.RuneFrost:
case UnitMods.RuneUnholy:
case UnitMods.AlternateQuest:
case UnitMods.AlternateEncounter:
case UnitMods.AlternateMount:
UpdateMaxPower((PowerType)(unitMod - UnitMods.PowerStart));
break;
case UnitMods.ResistanceHoly:
-6
View File
@@ -696,12 +696,6 @@ namespace Game
}
}
[WorldPacketHandler(ClientOpcodes.RequestCategoryCooldowns, Processing = PacketProcessing.Inplace)]
void HandleRequestCategoryCooldowns(RequestCategoryCooldowns requestCategoryCooldowns)
{
GetPlayer().SendSpellCategoryCooldowns();
}
[WorldPacketHandler(ClientOpcodes.KeyboundOverride, Processing = PacketProcessing.ThreadSafe)]
void HandleKeyboundOverride(KeyboundOverride keyboundOverride)
{
+4
View File
@@ -278,6 +278,7 @@ namespace Game.Loots
FillPacket(startLootRoll.Item);
startLootRoll.Item.UIType = LootSlotType.RollOngoing;
startLootRoll.DungeonEncounterID = m_loot.GetDungeonEncounterId();
player.SendPacket(startLootRoll);
}
@@ -299,6 +300,7 @@ namespace Game.Loots
lootAllPassed.LootObj = m_loot.GetGUID();
FillPacket(lootAllPassed.Item);
lootAllPassed.Item.UIType = LootSlotType.AllowLoot;
lootAllPassed.DungeonEncounterID = m_loot.GetDungeonEncounterId();
lootAllPassed.Write();
foreach (var (playerGuid, roll) in m_rollVoteMap)
@@ -325,6 +327,7 @@ namespace Game.Loots
lootRoll.Autopassed = false;
FillPacket(lootRoll.Item);
lootRoll.Item.UIType = LootSlotType.RollOngoing;
lootRoll.DungeonEncounterID = m_loot.GetDungeonEncounterId();
lootRoll.Write();
foreach (var (playerGuid, roll) in m_rollVoteMap)
@@ -381,6 +384,7 @@ namespace Game.Loots
lootRollWon.RollType = rollType;
FillPacket(lootRollWon.Item);
lootRollWon.Item.UIType = LootSlotType.Locked;
lootRollWon.DungeonEncounterID = m_loot.GetDungeonEncounterId();
lootRollWon.MainSpec = true; // offspec rolls not implemented
lootRollWon.Write();
@@ -718,6 +718,9 @@ namespace Game.Networking.Packets
if (MmrChange.HasValue)
data.WriteInt32(MmrChange.Value);
if (PostMatchMMR.HasValue)
data.WriteUInt32(PostMatchMMR.Value);
}
public ObjectGuid PlayerGUID;
@@ -731,6 +734,7 @@ namespace Game.Networking.Packets
public int? RatingChange;
public uint? PreMatchMMR;
public int? MmrChange;
public uint? PostMatchMMR;
public List<PVPMatchPlayerPVPStat> Stats = new();
public int PrimaryTalentTree;
public int Sex;
@@ -216,12 +216,12 @@ namespace Game.Networking.Packets
public override void Read()
{
PetGuid = _worldPacket.ReadPackedGuid();
Flags = _worldPacket.ReadUInt32();
Flags = _worldPacket.ReadUInt16();
ControlType = (FlagsControlType)_worldPacket.ReadBits<byte>(2);
}
public ObjectGuid PetGuid;
public uint Flags;
public ushort Flags;
public FlagsControlType ControlType;
}
@@ -224,7 +224,7 @@ namespace Game.Networking.Packets
public byte RaceId;
public Class ClassId;
public byte SexId;
public Array<ChrCustomizationChoice> Customizations = new(72);
public Array<ChrCustomizationChoice> Customizations = new(125);
public byte ExperienceLevel;
public uint ZoneId;
public uint MapId;
@@ -566,7 +566,7 @@ namespace Game.Networking.Packets
public string Name;
public byte SexID;
public byte RaceID;
public Array<ChrCustomizationChoice> Customizations = new(72);
public Array<ChrCustomizationChoice> Customizations = new(125);
}
}
@@ -878,7 +878,7 @@ namespace Game.Networking.Packets
}
public byte NewSex;
public Array<ChrCustomizationChoice> Customizations = new(72);
public Array<ChrCustomizationChoice> Customizations = new(125);
public int CustomizedRace;
}
@@ -1028,7 +1028,7 @@ namespace Game.Networking.Packets
ObjectGuid CharGUID;
string CharName = "";
byte SexID;
Array<ChrCustomizationChoice> Customizations = new(72);
Array<ChrCustomizationChoice> Customizations = new(125);
}
class CharCustomizeFailure : ServerPacket
@@ -1090,7 +1090,7 @@ namespace Game.Networking.Packets
public Race RaceId = Race.None;
public Class ClassId = Class.None;
public Gender Sex = Gender.None;
public Array<ChrCustomizationChoice> Customizations = new(72);
public Array<ChrCustomizationChoice> Customizations = new(125);
public uint? TemplateSet;
public bool IsTrialBoost;
public bool UseNPE;
@@ -1111,7 +1111,7 @@ namespace Game.Networking.Packets
public ObjectGuid CharGUID;
public Gender SexID = Gender.None;
public string CharName;
public Array<ChrCustomizationChoice> Customizations = new(72);
public Array<ChrCustomizationChoice> Customizations = new(125);
}
public class CharRaceOrFactionChangeInfo
@@ -1122,7 +1122,7 @@ namespace Game.Networking.Packets
public ObjectGuid Guid;
public bool FactionChange;
public string Name;
public Array<ChrCustomizationChoice> Customizations = new(72);
public Array<ChrCustomizationChoice> Customizations = new(125);
}
public class CharacterUndeleteInfo
+28 -16
View File
@@ -12,17 +12,30 @@ namespace Game.Networking.Packets
{
public class ChatMessage : ClientPacket
{
public string Text;
public Language Language = Language.Universal;
public bool IsSecure = true;
public ChatMessage(WorldPacket packet) : base(packet) { }
public override void Read()
{
Language = (Language)_worldPacket.ReadInt32();
uint len = _worldPacket.ReadBits<uint>(11);
switch (GetOpcode())
{
case ClientOpcodes.ChatMessageSay:
case ClientOpcodes.ChatMessageParty:
case ClientOpcodes.ChatMessageRaid:
case ClientOpcodes.ChatMessageRaidWarning:
case ClientOpcodes.ChatMessageInstanceChat:
IsSecure = _worldPacket.HasBit();
break;
default:
break;
}
Text = _worldPacket.ReadString(len);
}
public string Text;
public Language Language = Language.Universal;
}
public class ChatMessageWhisper : ClientPacket
@@ -45,6 +58,12 @@ namespace Game.Networking.Packets
public class ChatMessageChannel : ClientPacket
{
public Language Language = Language.Universal;
public ObjectGuid ChannelGUID;
public string Text;
public string Target;
public bool? IsSecure;
public ChatMessageChannel(WorldPacket packet) : base(packet) { }
public override void Read()
@@ -53,14 +72,12 @@ namespace Game.Networking.Packets
ChannelGUID = _worldPacket.ReadPackedGuid();
uint targetLen = _worldPacket.ReadBits<uint>(9);
uint textLen = _worldPacket.ReadBits<uint>(11);
if (_worldPacket.HasBit())
IsSecure = _worldPacket.HasBit();
Target = _worldPacket.ReadString(targetLen);
Text = _worldPacket.ReadString(textLen);
}
public Language Language = Language.Universal;
public ObjectGuid ChannelGUID;
public string Text;
public string Target;
}
public class ChatAddonMessage : ClientPacket
@@ -143,7 +160,6 @@ namespace Game.Networking.Packets
SenderGUID.Clear();
SenderAccountGUID.Clear();
SenderGuildGUID.Clear();
PartyGUID.Clear();
TargetGUID.Clear();
SenderName = "";
TargetName = "";
@@ -181,10 +197,6 @@ namespace Game.Networking.Packets
_ChatFlags = playerSender.GetChatFlags();
SenderGuildGUID = ObjectGuid.Create(HighGuid.Guild, playerSender.GetGuildId());
Group group = playerSender.GetGroup();
if (group)
PartyGUID = group.GetGUID();
}
}
@@ -207,15 +219,15 @@ namespace Game.Networking.Packets
_worldPacket.WritePackedGuid(TargetGUID);
_worldPacket.WriteUInt32(TargetVirtualAddress);
_worldPacket.WriteUInt32(SenderVirtualAddress);
_worldPacket.WritePackedGuid(PartyGUID);
_worldPacket.WriteUInt32(AchievementID);
_worldPacket.WriteFloat(DisplayTime);
_worldPacket.WriteUInt32(SpellID);
_worldPacket.WriteBits(SenderName.GetByteCount(), 11);
_worldPacket.WriteBits(TargetName.GetByteCount(), 11);
_worldPacket.WriteBits(Prefix.GetByteCount(), 5);
_worldPacket.WriteBits(Channel.GetByteCount(), 7);
_worldPacket.WriteBits(ChatText.GetByteCount(), 12);
_worldPacket.WriteBits((byte)_ChatFlags, 15);
_worldPacket.WriteBits((ushort)_ChatFlags, 15);
_worldPacket.WriteBit(HideChatLog);
_worldPacket.WriteBit(FakeSenderName);
_worldPacket.WriteBit(Unused_801.HasValue);
@@ -241,7 +253,6 @@ namespace Game.Networking.Packets
public ObjectGuid SenderGuildGUID;
public ObjectGuid SenderAccountGUID;
public ObjectGuid TargetGUID;
public ObjectGuid PartyGUID;
public uint SenderVirtualAddress;
public uint TargetVirtualAddress;
public string SenderName = "";
@@ -252,6 +263,7 @@ namespace Game.Networking.Packets
public uint AchievementID;
public ChatFlags _ChatFlags;
public float DisplayTime;
public uint SpellID;
public uint? Unused_801;
public bool HideChatLog;
public bool FakeSenderName;
@@ -551,7 +551,7 @@ namespace Game.Networking.Packets
attackRoundInfo.WriteInt8(ContentTuning.TargetScalingLevelDelta);
attackRoundInfo.WriteFloat(ContentTuning.PlayerItemLevel);
attackRoundInfo.WriteFloat(ContentTuning.TargetItemLevel);
attackRoundInfo.WriteUInt16(ContentTuning.ScalingHealthItemLevelCurveID);
attackRoundInfo.WriteUInt32(ContentTuning.ScalingHealthItemLevelCurveID);
attackRoundInfo.WriteUInt32((uint)ContentTuning.Flags);
attackRoundInfo.WriteUInt32(ContentTuning.PlayerContentTuningID);
attackRoundInfo.WriteUInt32(ContentTuning.TargetContentTuningID);
+40 -28
View File
@@ -259,6 +259,15 @@ namespace Game.Networking.Packets
class StartLootRoll : ServerPacket
{
public ObjectGuid LootObj;
public int MapID;
public uint RollTime;
public LootMethod Method;
public RollMask ValidRolls;
public Array<LootRollIneligibilityReason> LootRollIneligibleReason = new Array<LootRollIneligibilityReason>(4);
public LootItemData Item = new();
public uint DungeonEncounterID;
public StartLootRoll() : base(ServerOpcodes.StartLootRoll) { }
public override void Write()
@@ -271,20 +280,22 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32((uint)reason);
_worldPacket.WriteUInt8((byte)Method);
_worldPacket.WriteUInt32(DungeonEncounterID);
Item.Write(_worldPacket);
}
public ObjectGuid LootObj;
public int MapID;
public uint RollTime;
public LootMethod Method;
public RollMask ValidRolls;
public Array<LootRollIneligibilityReason> LootRollIneligibleReason = new Array<LootRollIneligibilityReason>(4);
public LootItemData Item = new();
}
class LootRollBroadcast : ServerPacket
{
public ObjectGuid LootObj;
public ObjectGuid Player;
public int Roll; // Roll value can be negative, it means that it is an "offspec" roll but only during roll selection broadcast (not when sending the result)
public RollVote RollType;
public LootItemData Item = new();
public bool Autopassed; // Triggers message |HlootHistory:%d|h[Loot]|h: You automatically passed on: %s because you cannot loot that item.
public bool OffSpec;
public uint DungeonEncounterID;
public LootRollBroadcast() : base(ServerOpcodes.LootRoll) { }
public override void Write()
@@ -293,21 +304,24 @@ namespace Game.Networking.Packets
_worldPacket.WritePackedGuid(Player);
_worldPacket.WriteInt32(Roll);
_worldPacket.WriteUInt8((byte)RollType);
_worldPacket.WriteUInt32(DungeonEncounterID);
Item.Write(_worldPacket);
_worldPacket.WriteBit(Autopassed);
_worldPacket.WriteBit(OffSpec);
_worldPacket.FlushBits();
}
public ObjectGuid LootObj;
public ObjectGuid Player;
public int Roll; // Roll value can be negative, it means that it is an "offspec" roll but only during roll selection broadcast (not when sending the result)
public RollVote RollType;
public LootItemData Item = new();
public bool Autopassed; // Triggers message |HlootHistory:%d|h[Loot]|h: You automatically passed on: %s because you cannot loot that item.
}
class LootRollWon : ServerPacket
{
public ObjectGuid LootObj;
public ObjectGuid Winner;
public int Roll;
public RollVote RollType;
public LootItemData Item = new();
public bool MainSpec;
public uint DungeonEncounterID;
public LootRollWon() : base(ServerOpcodes.LootRollWon) { }
public override void Write()
@@ -316,45 +330,43 @@ namespace Game.Networking.Packets
_worldPacket.WritePackedGuid(Winner);
_worldPacket.WriteInt32(Roll);
_worldPacket.WriteUInt8((byte)RollType);
_worldPacket.WriteUInt32(DungeonEncounterID);
Item.Write(_worldPacket);
_worldPacket.WriteBit(MainSpec);
_worldPacket.FlushBits();
}
public ObjectGuid LootObj;
public ObjectGuid Winner;
public int Roll;
public RollVote RollType;
public LootItemData Item = new();
public bool MainSpec;
}
class LootAllPassed : ServerPacket
{
public ObjectGuid LootObj;
public LootItemData Item = new();
public uint DungeonEncounterID;
public LootAllPassed() : base(ServerOpcodes.LootAllPassed) { }
public override void Write()
{
_worldPacket.WritePackedGuid(LootObj);
_worldPacket.WriteUInt32(DungeonEncounterID);
Item.Write(_worldPacket);
}
public ObjectGuid LootObj;
public LootItemData Item = new();
}
class LootRollsComplete : ServerPacket
{
public ObjectGuid LootObj;
public byte LootListID;
public int DungeonEncounterID;
public LootRollsComplete() : base(ServerOpcodes.LootRollsComplete) { }
public override void Write()
{
_worldPacket.WritePackedGuid(LootObj);
_worldPacket.WriteUInt8(LootListID);
_worldPacket.WriteInt32(DungeonEncounterID);
}
public ObjectGuid LootObj;
public byte LootListID;
}
class MasterLootCandidateList : ServerPacket
+20 -11
View File
@@ -106,7 +106,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(QuantityGainSource.HasValue);
_worldPacket.WriteBit(QuantityLostSource.HasValue);
_worldPacket.WriteBit(FirstCraftOperationID.HasValue);
_worldPacket.WriteBit(LastSpendTime.HasValue);
_worldPacket.WriteBit(NextRechargeTime.HasValue);
_worldPacket.WriteBit(RechargeCycleStartTime.HasValue);
_worldPacket.FlushBits();
if (WeeklyQuantity.HasValue)
@@ -133,8 +134,11 @@ namespace Game.Networking.Packets
if (FirstCraftOperationID.HasValue)
_worldPacket.WriteUInt32(FirstCraftOperationID.Value);
if (LastSpendTime.HasValue)
_worldPacket.WriteInt64(LastSpendTime.Value);
if (NextRechargeTime.HasValue)
_worldPacket.WriteInt64(NextRechargeTime.Value);
if (RechargeCycleStartTime.HasValue)
_worldPacket.WriteInt64(RechargeCycleStartTime.Value);
}
public uint Type;
@@ -149,7 +153,8 @@ namespace Game.Networking.Packets
public CurrencyGainSource? QuantityGainSource;
public CurrencyDestroyReason? QuantityLostSource;
public uint? FirstCraftOperationID;
public long? LastSpendTime;
public long? NextRechargeTime;
public long? RechargeCycleStartTime;
public bool SuppressChatLog;
}
@@ -197,7 +202,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(data.TrackedQuantity.HasValue);
_worldPacket.WriteBit(data.MaxQuantity.HasValue);
_worldPacket.WriteBit(data.TotalEarned.HasValue);
_worldPacket.WriteBit(data.LastSpendTime.HasValue);
_worldPacket.WriteBit(data.NextRechargeTime.HasValue);
_worldPacket.WriteBit(data.RechargeCycleStartTime.HasValue);
_worldPacket.WriteBits(data.Flags, 5);
_worldPacket.FlushBits();
@@ -211,8 +217,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt32(data.MaxQuantity.Value);
if (data.TotalEarned.HasValue)
_worldPacket.WriteInt32(data.TotalEarned.Value);
if (data.LastSpendTime.HasValue)
_worldPacket.WriteInt64(data.LastSpendTime.Value);
if (data.NextRechargeTime.HasValue)
_worldPacket.WriteInt64(data.NextRechargeTime.Value);
if (data.RechargeCycleStartTime.HasValue)
_worldPacket.WriteInt64(data.RechargeCycleStartTime.Value);
}
}
@@ -227,7 +235,8 @@ namespace Game.Networking.Packets
public uint? TrackedQuantity;
public int? MaxQuantity;
public int? TotalEarned;
public long? LastSpendTime;
public long? NextRechargeTime;
public long? RechargeCycleStartTime;
public byte Flags;
}
}
@@ -1387,10 +1396,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(IsFullUpdate);
_worldPacket.WriteInt32(Mounts.Count);
foreach (var spell in Mounts)
foreach (var (spellId, flags) in Mounts)
{
_worldPacket.WriteUInt32(spell.Key);
_worldPacket.WriteBits(spell.Value, 2);
_worldPacket.WriteUInt32(spellId);
_worldPacket.WriteBits(flags, 4);
}
_worldPacket.FlushBits();
@@ -83,8 +83,7 @@ namespace Game.Networking.Packets
data.ReadPackedGuid();
}
// ResetBitReader
bool hasStandingOnGameObjectGUID = data.HasBit();
bool hasTransport = data.HasBit();
bool hasFall = data.HasBit();
bool hasSpline = data.HasBit(); // todo 6.x read this infos
@@ -97,6 +96,9 @@ namespace Game.Networking.Packets
if (hasTransport)
ReadTransportInfo(data, ref movementInfo.transport);
if (hasStandingOnGameObjectGUID)
movementInfo.standingOnGameObjectGUID = data.ReadPackedGuid();
if (hasInertia)
{
MovementInfo.Inertia inertia = new();
@@ -143,6 +145,7 @@ namespace Game.Networking.Packets
bool hasSpline = false; // todo 6.x send this infos
bool hasInertia = movementInfo.inertia.HasValue;
bool hasAdvFlying = movementInfo.advFlying.HasValue;
bool hasStandingOnGameObjectGUID = movementInfo.standingOnGameObjectGUID.HasValue;
data.WritePackedGuid(movementInfo.Guid);
data.WriteUInt32((uint)movementInfo.GetMovementFlags());
@@ -167,6 +170,7 @@ namespace Game.Networking.Packets
_worldPacket << ObjectGuid;
}*/
data.WriteBit(hasStandingOnGameObjectGUID);
data.WriteBit(hasTransportData);
data.WriteBit(hasFallData);
data.WriteBit(hasSpline);
@@ -179,6 +183,9 @@ namespace Game.Networking.Packets
if (hasTransportData)
WriteTransportInfo(data, movementInfo.transport);
if (hasStandingOnGameObjectGUID)
data.WritePackedGuid(movementInfo.standingOnGameObjectGUID.Value);
if (hasInertia)
{
data.WriteInt32(movementInfo.inertia.Value.id);
+13 -15
View File
@@ -61,18 +61,11 @@ namespace Game.Networking.Packets
public override void Read() { }
}
public class RequestCategoryCooldowns : ClientPacket
{
public RequestCategoryCooldowns(WorldPacket packet) : base(packet) { }
public override void Read() { }
}
public class SpellCategoryCooldown : ServerPacket
{
public List<CategoryCooldownInfo> CategoryCooldowns = new();
public SpellCategoryCooldown() : base(ServerOpcodes.CategoryCooldown, ConnectionType.Instance) { }
public SpellCategoryCooldown() : base(ServerOpcodes.SpellCategoryCooldown, ConnectionType.Instance) { }
public override void Write()
{
@@ -1337,7 +1330,7 @@ namespace Game.Networking.Packets
data.WriteFloat(PlayerItemLevel);
data.WriteFloat(TargetItemLevel);
data.WriteInt16(PlayerLevelDelta);
data.WriteUInt16(ScalingHealthItemLevelCurveID);
data.WriteUInt32(ScalingHealthItemLevelCurveID);
data.WriteUInt8(TargetLevel);
data.WriteUInt8(Expansion);
data.WriteInt8(TargetScalingLevelDelta);
@@ -1353,7 +1346,7 @@ namespace Game.Networking.Packets
public short PlayerLevelDelta;
public float PlayerItemLevel;
public float TargetItemLevel;
public ushort ScalingHealthItemLevelCurveID;
public uint ScalingHealthItemLevelCurveID;
public byte TargetLevel;
public byte Expansion;
public sbyte TargetScalingLevelDelta;
@@ -1641,7 +1634,8 @@ namespace Game.Networking.Packets
public MissileTrajectoryRequest MissileTrajectory;
public MovementInfo MoveUpdate;
public List<SpellWeight> Weight = new();
public Array<SpellCraftingReagent> OptionalReagents = new(3);
public Array<SpellCraftingReagent> OptionalReagents = new(6);
public Array<SpellCraftingReagent> RemovedModifications = new(6);
public Array<SpellExtraCurrencyCost> OptionalCurrencies = new(5 /*MAX_ITEM_EXT_COST_CURRENCIES*/);
public ulong? CraftingOrderID;
public ObjectGuid CraftingNPC;
@@ -1659,10 +1653,11 @@ namespace Game.Networking.Packets
MissileTrajectory.Read(data);
CraftingNPC = data.ReadPackedGuid();
var optionalCurrencies = data.ReadUInt32();
var optionalReagents = data.ReadUInt32();
var optionalCurrenciesCount = data.ReadUInt32();
var optionalReagentsCount = data.ReadUInt32();
var removedModificationsCount = data.ReadUInt32();
for (var i = 0; i < optionalCurrencies; ++i)
for (var i = 0; i < optionalCurrenciesCount; ++i)
OptionalCurrencies[i].Read(data);
SendCastFlags = data.ReadBits<uint>(5);
@@ -1675,9 +1670,12 @@ namespace Game.Networking.Packets
if (hasCraftingOrderID)
CraftingOrderID = data.ReadUInt64();
for (var i = 0; i < optionalReagents; ++i)
for (var i = 0; i < optionalReagentsCount; ++i)
OptionalReagents[i].Read(data);
for (var i = 0; i < removedModificationsCount; ++i)
RemovedModifications[i].Read(data);
if (hasMoveUpdate)
MoveUpdate = MovementExtensions.ReadMovementInfo(data);
@@ -43,8 +43,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(WindowInfo.HasValue);
_worldPacket.FlushBits();
_worldPacket.WriteInt32(CanLandNodes.Length);
_worldPacket.WriteInt32(CanUseNodes.Length);
_worldPacket.WriteInt32(CanLandNodes.Length / 8); // client reads this in uint64 blocks, size is ensured to be divisible by 8 in TaxiMask constructor
_worldPacket.WriteInt32(CanUseNodes.Length / 8); // client reads this in uint64 blocks, size is ensured to be divisible by 8 in TaxiMask constructor
if (WindowInfo.HasValue)
{
+6 -1
View File
@@ -366,13 +366,18 @@ namespace Game
if (questXp == null || xpDifficulty >= 10)
return 0;
uint xp = questXp.Difficulty[xpDifficulty];
var contentTuning = CliDB.ContentTuningStorage.LookupByKey(contentTuningId);
if (contentTuning != null)
xp = (uint)(xp * contentTuning.QuestXpMultiplier);
int diffFactor = (int)(2 * (questLevel - player.GetLevel()) + 12);
if (diffFactor < 1)
diffFactor = 1;
else if (diffFactor > 10)
diffFactor = 10;
uint xp = (uint)(diffFactor * questXp.Difficulty[xpDifficulty] * xpMultiplier / 10);
xp = (uint)(diffFactor * xp * xpMultiplier / 10);
if (player.GetLevel() >= Global.ObjectMgr.GetMaxLevelForExpansion(PlayerConst.CurrentExpansion - 1) && player.GetSession().GetExpansion() == PlayerConst.CurrentExpansion && expansion >= 0 && expansion < (int)PlayerConst.CurrentExpansion)
xp = (uint)(xp / 9.0f);
+8 -3
View File
@@ -5633,9 +5633,14 @@ namespace Game.Spells
if (!mode.HasAnyFlag(AuraEffectHandleModes.Real))
return;
Player player = aurApp.GetTarget().ToPlayer();
if (player)
player.SendSpellCategoryCooldowns();
Player target = aurApp.GetTarget().ToPlayer();
if (target == null)
return;
if (apply)
target.AddSpellCategoryCooldownMod(GetMiscValue(), GetAmount());
else
target.RemoveSpellCategoryCooldownMod(GetMiscValue(), GetAmount());
}
[AuraEffectHandler(AuraType.ShowConfirmationPrompt)]
+10 -2
View File
@@ -1270,7 +1270,7 @@ namespace Game.Spells
uint creatureType = target.GetCreatureTypeMask();
return TargetCreatureType == 0 || creatureType == 0 || Convert.ToBoolean(creatureType & TargetCreatureType);
return TargetCreatureType == 0 || creatureType == 0 || (creatureType & TargetCreatureType) != 0 || target.HasAuraType(AuraType.IgnoreSpellCreatureTypeRequirements);
}
public SpellSchoolMask GetSchoolMask()
@@ -4824,7 +4824,15 @@ namespace Game.Spells
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 303 SPELL_EFFECT_CREATE_TRAIT_TREE_CONFIG
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 304 SPELL_EFFECT_CHANGE_ACTIVE_COMBAT_TRAIT_CONFIG
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 305 SPELL_EFFECT_305
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 306 SPELL_EFFECT_306
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 306 SPELL_EFFECT_306
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 307 SPELL_EFFECT_307
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 308 SPELL_EFFECT_308
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 309 SPELL_EFFECT_309
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 310 SPELL_EFFECT_310
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 311 SPELL_EFFECT_311
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 312 SPELL_EFFECT_312
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 313 SPELL_EFFECT_313
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 314 SPELL_EFFECT_314
};
#region Fields