hondacrx
2023-05-19 16:23:44 -04:00
parent 24b0836710
commit dfceb4c044
40 changed files with 1910 additions and 1549 deletions
+6 -6
View File
@@ -19,11 +19,11 @@ namespace Framework.Constants
public enum HeaderFlags : short
{
None = 0x0,
OffsetMap = 0x1,
SecondIndex = 0x2,
IndexMap = 0x4,
Unknown = 0x8,
Compressed = 0x10,
Sparse = 0x1,
SecondaryKey = 0x2,
Index = 0x4,
Unknown1 = 0x8,
BitPacked = 0x10,
}
[Flags]
@@ -2380,7 +2380,7 @@ namespace Framework.Constants
Max
}
public enum UiMapType : uint
public enum UiMapType : byte
{
Cosmic = 0,
World = 1,
+17 -2
View File
@@ -152,8 +152,17 @@ namespace Framework.Constants
OffensiveSlot3 = 213,
OffensiveSlot4 = 214,
UtilitySlot1 = 215,
DefensiveSlot1 = 216,
MobilitySlot1 = 217
UtilitySlot2 = 216,
UtilitySlot3 = 217,
UtilitySlot4 = 218,
DefensiveSlot1 = 219,
DefensiveSlot2 = 220,
DefensiveSlot3 = 221,
DefensiveSlot4 = 222,
WeaponSlot1 = 223,
WeaponSlot2 = 224,
WeaponSlot3 = 225,
WeaponSlot4 = 226,
}
public struct EquipmentSlot
@@ -387,6 +396,12 @@ namespace Framework.Constants
CraftingReagentSlot7 = 50,
CraftingReagentSlot8 = 51,
CraftingReagentSlot9 = 52,
CraftingReagentSlot10 = 53,
CraftingReagentSlot11 = 54,
CraftingReagentSlot12 = 55,
CraftingReagentSlot13 = 56,
CraftingReagentSlot14 = 57,
Max
}
+1
View File
@@ -19,6 +19,7 @@ namespace Framework.Constants
Need = 0x02,
Greed = 0x04,
Disenchant = 0x08,
Transmog = 0x10,
AllNoDisenchant = 0x07,
AllMask = 0x0f
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -140,7 +140,8 @@ namespace Framework.Constants
BossSound = 0x20, // Plays "RaidBossEmoteWarning" sound on raid boss emote/whisper
Mobile = 0x40,
Guide = 0x1000,
Newcomer = 0x2000
Newcomer = 0x2000,
Censored = 0x4000
}
public enum DrunkenState
@@ -546,7 +547,7 @@ namespace Framework.Constants
// first slot for item stored (in any way in player items data)
Start = 0,
// last+1 slot for item stored (in any way in player items data)
End = 218,
End = 227,
Count = (End - Start)
}
+15 -3
View File
@@ -814,11 +814,17 @@ namespace Framework.Constants
Fury = 17,
Pain = 18,
Essence = 19,
Max = 20,
RuneBlood = 20,
RuneFrost = 21,
RuneUnholy = 22,
AlternateQuest = 23,
AlternateEncounter = 24,
AlternateMount = 25,
Max = 26,
All = 127, // default for class?
Health = -2, // (-2 as signed value)
MaxPerClass = 7
MaxPerClass = 10
}
public enum Stats
@@ -3046,7 +3052,13 @@ namespace Framework.Constants
UseWeeklyRewardsDisabled = 1113,
CrossFactionGroupJoined = 1114,
CantTargetUnfriendlyInOverworld = 1115,
EquipablespellsSlotsFull = 1116
EquipablespellsSlotsFull = 1116,
WowLabsPartyErrorTypePartyIsFull = 1117,
WowLabsPartyErrorTypeMaxInviteSent = 1118,
WowLabsPartyErrorTypePlayerAlreadyInvited = 1119,
WowLabsPartyErrorTypePartyInviteInvalid = 1120,
WowLabsLobbyMatchmakerErrorEnterQueueFailed = 1121,
WowLabsLobbyMatchmakerErrorLeaveQueueFailed = 1122,
}
public enum SceneFlags
@@ -543,6 +543,7 @@ namespace Framework.Constants
DisableNavigation = 533, // Disables Map Pins
Unk534 = 534,
Unk535 = 535,
IgnoreSpellCreatureTypeRequirements = 536,
Total
}
@@ -1350,6 +1350,7 @@ namespace Framework.Constants
YouCanOnlyDoThisWhileMidair = 638, // You Can Only Do This While Midair.
YouCannotDoThatWhileAirborne = 639, // You Cannot Do That While Airborne.
PocopocIsUnavailableOnQuestline = 640, // Pocopoc Is Unavailable To Summon During The Questline A Means To An End.
CannontCastThatWithAuraOfReckoningTalent = 650, // You cannot cast that while Aura of Reckoning is talented.
RequiresSulfuronSlammer = 711, // Requires Sulfuron Slammer
NotReadyYet = 788, // Not Ready Yet.
QualityOfTieredMedallionSettingIsTooLow = 789, // The Quality Of Your Tiered Medallion Setting Is Too Low To Add Another Socket To This Item.
@@ -1386,6 +1387,23 @@ namespace Framework.Constants
ThereIsNoMoreRoomOnThatHandhold = 820, // There Is No More Room On That Handhold.
YouMustUnblockThisSpotByCompletingADailyQuest = 821, // You Must Unblock This Spot By Completing A Daily Quest.
YouMustBeCloserToAnIceHoleToDoThat = 822, // You Must Be Closer To An Ice Hole To Do That.
ShadowflameIsTooStrongToBear = 823, // The Shadowflame Is Too Strong To Bear.
SomeoneHasAlreadyOverloadedThis = 824, // Someone Has Already Overloaded This.
RequiresNokhudTrainingCourse = 825, // Requires Nokhud Training Course.
ThisRecipeIsCurrentlyDisabled = 826, // This Recipe Is Currently Disabled. Please Try Again Later.
YouDoNotHaveTheCorrectBattlePetSummoned = 827, // You Do Not Have The Correct Battle Pet Summoned.
YouAlreadyHaveAtLeastOneConjuredPhial = 828, // You Already Have At Least One Conjured Phial.
MarkedTooManyTreasuresInTheForbiddenReach = 830, // You Have Already Marked Too Many Treasures In The Forbidden Reach. Collect A Few Before Unsealing More Forbidden Reach Treasure Scrolls.
RequiresADjaradinPillarShard = 831, // Requires A Djaradin Pillar Shard.
RequiresAResilientStone = 832, // Requires A Resilient Stone.
MyrritCannotCarryAnyMoreMaps = 835, // Myrrit Cannot Carry Any More Maps. Go On A Dig With Him!
RequiresNiffenCaveDiveKeyandShieldDisabled = 850, // Requires Niffen Cave Dive Key And Shield Disabled.
ElusiveCreatureBaitWasRecentlyUsed = 851, // You Cannot Lure Anything In This Area For A Few Minutes. Elusive Creature Bait Was Recently Used.
YouDontHaveTheSwirlingMojoStone = 999, // You Don'T Have The Swirling Mojo Stone Equipped.
YouMustBeNearADragonflightOathstone = 1000, // You Must Be Near One Of The Five Dragonflight Oathstones In The Dragon Isles.
CanOnlyUseThisItemWhileAirborne = 1001, // You Can Only Use This Item While Airborne.
YouMustBeInVisageForm = 2222, // You Must Be In Visage Form To Do This.
TooCloseToAnotherMoltenRitual = 2424, // You Can'T Begin A Molten Ritual This Close To Another One.
}
public enum SpellMissInfo
@@ -2483,6 +2501,14 @@ namespace Framework.Constants
ChangeActiveCombatTraitConfig = 304,
Unk305 = 305,
Unk306 = 306,
Unk307 = 307,
CancelPreloadWorld = 308,
PreloadWorld = 309,
Unk310 = 310,
EnsureWorldLoaded = 311,
Unk312 = 312,
ChangeItemBonuses2 = 313, // MiscValue[0] = ItemBonusTreeID to preserve
AddSocketBonus = 314, // MiscValue[0] = required ItemBonusTreeID
TotalSpellEffects
}
+10 -1
View File
@@ -154,6 +154,12 @@ namespace Framework.Constants
Fury,
Pain,
Essence,
RuneBlood,
RuneFrost,
RuneUnholy,
AlternateQuest,
AlternateEncounter,
AlternateMount,
Armor, // ARMOR..RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
ResistanceHoly,
ResistanceFire,
@@ -173,8 +179,9 @@ namespace Framework.Constants
ResistanceStart = Armor,
ResistanceEnd = ResistanceArcane + 1,
PowerStart = Mana,
PowerEnd = Essence + 1
PowerEnd = AlternateMount + 1
}
public enum UnitModifierFlatType
{
Base = 0,
@@ -182,12 +189,14 @@ namespace Framework.Constants
Total = 2,
End = 3
}
public enum UnitModifierPctType
{
Base = 0,
Total = 1,
End = 2
}
public enum VictimState
{
Intact = 0, // set when attacker misses
@@ -69,8 +69,9 @@ namespace Framework.Database
PrepareStatement(CharStatements.SEL_CHARACTER, "SELECT c.guid, account, name, race, class, gender, level, xp, money, inventorySlots, bankSlots, restState, playerFlags, playerFlagsEx, " +
"position_x, position_y, position_z, map, orientation, taximask, createTime, createMode, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, " +
"resettalents_time, primarySpecialization, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, summonedPetNumber, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, " +
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, power4, power5, power6, power7, instance_id, activeTalentGroup, lootSpecId, exploredZones, " +
"knownTitles, actionBars, raidDifficulty, legacyRaidDifficulty, fishingSteps, honor, honorLevel, honorRestState, honorRestBonus, numRespecs " +
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " +
"health, power1, power2, power3, power4, power5, power6, power7, power8, power9, power10, instance_id, activeTalentGroup, lootSpecId, exploredZones, knownTitles, actionBars, " +
"raidDifficulty, legacyRaidDifficulty, fishingSteps, honor, honorLevel, honorRestState, honorRestBonus, numRespecs " +
"FROM characters c LEFT JOIN character_fishingsteps cfs ON c.guid = cfs.guid WHERE c.guid = ?");
PrepareStatement(CharStatements.SEL_CHARACTER_CUSTOMIZATIONS, "SELECT chrCustomizationOptionID, chrCustomizationChoiceID FROM character_customizations WHERE guid = ? ORDER BY chrCustomizationOptionID");
@@ -444,13 +445,13 @@ namespace Framework.Database
"map, instance_id, dungeonDifficulty, raidDifficulty, legacyRaidDifficulty, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, " +
"taximask, createTime, createMode, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, primarySpecialization, " +
"extra_flags, summonedPetNumber, at_login, death_expire_time, taxi_path, totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, " +
"power4, power5, power6, power7, latency, activeTalentGroup, lootSpecId, exploredZones, equipmentCache, knownTitles, actionBars, lastLoginBuild) VALUES " +
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
"power4, power5, power6, power7, power8, power9, power10, latency, activeTalentGroup, lootSpecId, exploredZones, equipmentCache, knownTitles, actionBars, lastLoginBuild) VALUES " +
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
PrepareStatement(CharStatements.UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,inventorySlots=?,bankSlots=?,restState=?,playerFlags=?,playerFlagsEx=?," +
"map=?,instance_id=?,dungeonDifficulty=?,raidDifficulty=?,legacyRaidDifficulty=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?," +
"logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,numRespecs=?,primarySpecialization=?,extra_flags=?,summonedPetNumber=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?," +
"totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?," +
"watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,power6=?,power7=?,latency=?,activeTalentGroup=?,lootSpecId=?,exploredZones=?," +
"watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,power6=?,power7=?,power8=?,power9=?,power10=?,latency=?,activeTalentGroup=?,lootSpecId=?,exploredZones=?," +
"equipmentCache=?,knownTitles=?,actionBars=?,online=?,honor=?,honorLevel=?,honorRestState=?,honorRestBonus=?,lastLoginBuild=? WHERE guid=?");
PrepareStatement(CharStatements.UPD_ADD_AT_LOGIN_FLAG, "UPDATE characters SET at_login = at_login | ? WHERE guid = ?");
@@ -618,9 +619,9 @@ namespace Framework.Database
PrepareStatement(CharStatements.DEL_CHAR_SPELL_FAVORITE_BY_CHAR, "DELETE FROM character_spell_favorite WHERE guid = ?");
PrepareStatement(CharStatements.INS_CHAR_SPELL_FAVORITE, "INSERT INTO character_spell_favorite (guid, spell) VALUES (?, ?)");
PrepareStatement(CharStatements.DEL_CHAR_STATS, "DELETE FROM character_stats WHERE guid = ?");
PrepareStatement(CharStatements.INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, strength, agility, stamina, intellect, " +
"armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, " +
"spellPower, resilience) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
PrepareStatement(CharStatements.INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, maxpower8, maxpower9, maxpower10, " +
"strength, agility, stamina, intellect, armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, " +
"attackPower, rangedAttackPower, spellPower, resilience) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
PrepareStatement(CharStatements.DEL_PETITION_BY_OWNER, "DELETE FROM petition WHERE ownerguid = ?");
PrepareStatement(CharStatements.DEL_PETITION_SIGNATURE_BY_OWNER, "DELETE FROM petition_sign WHERE ownerguid = ?");
PrepareStatement(CharStatements.INS_CHAR_GLYPHS, "INSERT INTO character_glyphs VALUES(?, ?, ?)");
@@ -254,7 +254,7 @@ namespace Framework.Database
// ChrCustomizationChoice.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE, "SELECT Name, ID, ChrCustomizationOptionID, ChrCustomizationReqID, " +
"ChrCustomizationVisReqID, SortOrder, UiOrderIndex, Flags, AddedInPatch, SwatchColor1, SwatchColor2 FROM chr_customization_choice" +
"ChrCustomizationVisReqID, SortOrder, UiOrderIndex, Flags, AddedInPatch, SoundKitID, SwatchColor1, SwatchColor2 FROM chr_customization_choice" +
" WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE_LOCALE, "SELECT ID, Name_lang FROM chr_customization_choice_locale" +
" WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
@@ -266,8 +266,8 @@ namespace Framework.Database
// ChrCustomizationElement.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_ELEMENT, "SELECT ID, ChrCustomizationChoiceID, RelatedChrCustomizationChoiceID, " +
"ChrCustomizationGeosetID, ChrCustomizationSkinnedModelID, ChrCustomizationMaterialID, ChrCustomizationBoneSetID, " +
"ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID, ChrCustItemGeoModifyID, ChrCustomizationVoiceID FROM chr_customization_element" +
" WHERE (`VerifiedBuild` > 0) = ?");
"ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID, ChrCustItemGeoModifyID, ChrCustomizationVoiceID, AnimKitID" +
" FROM chr_customization_element WHERE (`VerifiedBuild` > 0) = ?");
// ChrCustomizationOption.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION, "SELECT Name, ID, SecondaryID, Flags, ChrModelID, SortIndex, ChrCustomizationCategoryID, " +
@@ -329,7 +329,7 @@ namespace Framework.Database
// ContentTuning.db2
PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING, "SELECT ID, Flags, ExpansionID, MinLevel, MaxLevel, MinLevelType, MaxLevelType, TargetLevelDelta, " +
"TargetLevelMaxDelta, TargetLevelMin, TargetLevelMax, MinItemLevel FROM content_tuning WHERE (`VerifiedBuild` > 0) = ?");
"TargetLevelMaxDelta, TargetLevelMin, TargetLevelMax, MinItemLevel, QuestXpMultiplier FROM content_tuning WHERE (`VerifiedBuild` > 0) = ?");
// ContentTuningXExpected.db2
PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING_X_EXPECTED, "SELECT ID, ExpectedStatModID, MinMythicPlusSeasonID, MaxMythicPlusSeasonID, " +
@@ -659,7 +659,8 @@ namespace Framework.Database
// ItemBonusTreeNode.db2
PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_TREE_NODE, "SELECT ID, ItemContext, ChildItemBonusTreeID, ChildItemBonusListID, ChildItemLevelSelectorID, " +
"ChildItemBonusListGroupID, IblGroupPointsModSetID, ParentItemBonusTreeID FROM item_bonus_tree_node WHERE (`VerifiedBuild` > 0) = ?");
"ChildItemBonusListGroupID, IblGroupPointsModSetID, Unknown1010_1, Unknown1010_2, ParentItemBonusTreeID FROM item_bonus_tree_node" +
" WHERE (`VerifiedBuild` > 0) = ?");
// ItemChildEquipment.db2
PrepareStatement(HotfixStatements.SEL_ITEM_CHILD_EQUIPMENT, "SELECT ID, ParentItemID, ChildItemID, ChildItemEquipSlot FROM item_child_equipment" +
@@ -914,7 +915,8 @@ namespace Framework.Database
" WHERE (`VerifiedBuild` > 0) = ?");
// Movie.db2
PrepareStatement(HotfixStatements.SEL_MOVIE, "SELECT ID, Volume, KeyID, AudioFileDataID, SubtitleFileDataID FROM movie WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_MOVIE, "SELECT ID, Volume, KeyID, AudioFileDataID, SubtitleFileDataID, SubtitleFileFormat FROM movie" +
" WHERE (`VerifiedBuild` > 0) = ?");
// NameGen.db2
PrepareStatement(HotfixStatements.SEL_NAME_GEN, "SELECT ID, Name, RaceID, Sex FROM name_gen WHERE (`VerifiedBuild` > 0) = ?");
+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();
// 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));
}
reader.BaseStream.Position = sections[sectionIndex].FileOffset;
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)]
+9 -1
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()
@@ -4825,6 +4825,14 @@ namespace Game.Spells
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), // 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