Core: Updated to 10.0.2

Port From (https://github.com/TrinityCore/TrinityCore/commit/e98e1283ea0034baf6be9aa2ffb386eb5582801b)
This commit is contained in:
hondacrx
2022-12-28 15:25:15 -05:00
parent 2dc12dbb69
commit 989b80b056
100 changed files with 6591 additions and 4112 deletions
+19 -4
View File
@@ -421,10 +421,21 @@ namespace Framework.Constants
PlayerBestWeeklyWinPvpTierInBracketEqualOrGreaterThan = 325, // (Mainline) Player has best weekly win at or above "{@PVP_TIER_ENUM}" for "{@PVP_BRACKET}" PlayerBestWeeklyWinPvpTierInBracketEqualOrGreaterThan = 325, // (Mainline) Player has best weekly win at or above "{@PVP_TIER_ENUM}" for "{@PVP_BRACKET}"
PlayerHasVanillaCollectorsEdition = 326, // Player has Vanilla Collector's Edition PlayerHasVanillaCollectorsEdition = 326, // Player has Vanilla Collector's Edition
PlayerHasItemWithKeystoneLevelModifierEqualOrGreaterThan = 327, PlayerHasItemWithKeystoneLevelModifierEqualOrGreaterThan = 327,
PlayerMythicPlusRatingInDisplaySeasonEqualOrGreaterThan = 329, /*NYI*/ // Player has Mythic+ Rating of at least "{#DungeonScore}" in {DisplaySeason} PlayerMythicPlusRatingInDisplaySeasonEqualOrGreaterThan = 329, /*NYI*/ // Player has Mythic+ Rating of at least "{#DungeonScore}" in {DisplaySeason}
PlayerMythicPlusLadderRatingInDisplaySeasonEqualOrGreaterThan = 333, /*NYI*/ // Player has Mythic+ Ladder Rating of at least "{#DungeonScore}" in {DisplaySeason}
MythicPlusRatingIsInTop01Percent = 334, // top 0.1% rating MythicPlusRatingIsInTop01Percent = 334, /*NYI*/ // top 0.1% rating
PlayerAuraWithLabelStackCountEqualOrGreaterThan = 335, // Player has at least {#Stacks} stacks of aura "{Label}"
PlayerAuraWithLabelStackCountEqual = 336, // Target has exactly {#Stacks} stacks of aura with label "{Label}"
PlayerAuraWithLabelStackCountEqualOrLessThan = 337, // Player has at most {#Stacks} stacks of aura "{Label}"
PlayerIsInCrossFactionGroup = 338, // Player is in a cross faction group
PlayerHasTraitNodeEntryInActiveConfig = 340, // Player has {TraitNodeEntry} node in currently active config
PlayerHasTraitNodeEntryInActiveConfigRankGreaterOrEqualThan = 341, // Player has at least {#Rank} for {TraitNodeEntry} node in currently active config
PlayerHasPurchasedCombatTraitRanks = 342, /*NYI*/ // Player has purchased at least {#Count} talent points in active combat config
PlayerHasPurchasedTraitRanksInTraitTree = 343, /*NYI*/ // Player has purchased at least {#Count} ranks in {#TraitTree}
PlayerDaysSinceLogout = 344,
CraftingOrderSkillLineAbility = 347, /*NYI*/
CraftingOrderProfession = 348, /*NYI*/ // ProfessionEnum
PlayerCanUseItem = 351, // Player can use item {#Item}
} }
public enum CriteriaFailEvent : byte public enum CriteriaFailEvent : byte
@@ -714,7 +725,11 @@ namespace Framework.Constants
MythicPlusRatingAttained = 230, /*NYI*/ // (Player) Mythic+ Rating "{#DungeonScore}" attained MythicPlusRatingAttained = 230, /*NYI*/ // (Player) Mythic+ Rating "{#DungeonScore}" attained
SpentTalentPoint = 231, /*NYI*/ // (Player) spent talent point SpentTalentPoint = 231, /*NYI*/ // (Player) spent talent point
MythicPlusDisplaySeasonEnded = 234, /*NYI*/ // {DisplaySeason} MythicPlusDisplaySeasonEnded = 234, /*NYI*/ // {DisplaySeason}
WinRatedSoloShuffleRound = 239, /*NYI*/
ParticipateInRatedSoloShuffleRound = 240, /*NYI*/
ReputationAmountGained = 243, /*NYI*/ // Gain reputation amount with {FactionID}; accumulate, not highest
FulfillAnyCraftingOrder = 245, /*NYI*/
FulfillCraftingOrderType = 246, /*NYI*/ // {CraftingOrderType}
Count Count
} }
@@ -77,60 +77,64 @@ namespace Framework.Constants
CharCreateNewPlayer = 50, CharCreateNewPlayer = 50,
CharCreateNameReservationFull = 51, CharCreateNameReservationFull = 51,
CharCreateClassTrialNewcomer = 52, CharCreateDracthyrDuplicate = 52,
CharCreateClassTrialThrottleHour = 53, CharCreateDracthyrLevelRequirement = 53,
CharCreateClassTrialThrottleDay = 54, CharCreateDeathknightDuplicate = 54,
CharCreateClassTrialThrottleWeek = 55, CharCreateDeathknightLevelRequirement = 55,
CharCreateClassTrialThrottleAccount = 56, CharCreateClassTrialNewcomer = 56,
CharCreateClassTrialThrottleHour = 57,
CharCreateClassTrialThrottleDay = 58,
CharCreateClassTrialThrottleWeek = 59,
CharCreateClassTrialThrottleAccount = 60,
CharDeleteInProgress = 57, CharDeleteInProgress = 61,
CharDeleteSuccess = 58, CharDeleteSuccess = 62,
CharDeleteFailed = 59, CharDeleteFailed = 63,
CharDeleteFailedLockedForTransfer = 60, CharDeleteFailedLockedForTransfer = 64,
CharDeleteFailedGuildLeader = 61, CharDeleteFailedGuildLeader = 65,
CharDeleteFailedArenaCaptain = 62, CharDeleteFailedArenaCaptain = 66,
CharDeleteFailedHasHeirloomOrMail = 63, CharDeleteFailedHasHeirloomOrMail = 67,
CharDeleteFailedUpgradeInProgress = 64, CharDeleteFailedUpgradeInProgress = 68,
CharDeleteFailedHasWowToken = 65, CharDeleteFailedHasWowToken = 69,
CharDeleteFailedVasTransactionInProgress = 66, CharDeleteFailedVasTransactionInProgress = 70,
CharDeleteFailedCommunityOwner = 67, CharDeleteFailedCommunityOwner = 71,
CharLoginInProgress = 68, CharLoginInProgress = 72,
CharLoginSuccess = 69, CharLoginSuccess = 73,
CharLoginNoWorld = 70, CharLoginNoWorld = 74,
CharLoginDuplicateCharacter = 71, CharLoginDuplicateCharacter = 75,
CharLoginNoInstances = 72, CharLoginNoInstances = 76,
CharLoginFailed = 73, CharLoginFailed = 77,
CharLoginDisabled = 74, CharLoginDisabled = 78,
CharLoginNoCharacter = 75, CharLoginNoCharacter = 79,
CharLoginLockedForTransfer = 76, CharLoginLockedForTransfer = 80,
CharLoginLockedByBilling = 77, CharLoginLockedByBilling = 81,
CharLoginLockedByMobileAh = 78, CharLoginLockedByMobileAh = 82,
CharLoginTemporaryGmLock = 79, CharLoginTemporaryGmLock = 83,
CharLoginLockedByCharacterUpgrade = 80, CharLoginLockedByCharacterUpgrade = 84,
CharLoginLockedByRevokedCharacterUpgrade = 81, CharLoginLockedByRevokedCharacterUpgrade = 85,
CharLoginLockedByRevokedVasTransaction = 82, CharLoginLockedByRevokedVasTransaction = 86,
CharLoginLockedByRestriction = 83, CharLoginLockedByRestriction = 87,
CharLoginLockedForRealmPlaytype = 84, CharLoginLockedForRealmPlaytype = 88,
CharNameSuccess = 85, CharNameSuccess = 89,
CharNameFailure = 86, CharNameFailure = 90,
CharNameNoName = 87, CharNameNoName = 91,
CharNameTooShort = 88, CharNameTooShort = 92,
CharNameTooLong = 89, CharNameTooLong = 93,
CharNameInvalidCharacter = 90, CharNameInvalidCharacter = 94,
CharNameMixedLanguages = 91, CharNameMixedLanguages = 95,
CharNameProfane = 92, CharNameProfane = 96,
CharNameReserved = 93, CharNameReserved = 97,
CharNameInvalidApostrophe = 94, CharNameInvalidApostrophe = 98,
CharNameMultipleApostrophes = 95, CharNameMultipleApostrophes = 99,
CharNameThreeConsecutive = 96, CharNameThreeConsecutive = 100,
CharNameInvalidSpace = 97, CharNameInvalidSpace = 101,
CharNameConsecutiveSpaces = 98, CharNameConsecutiveSpaces = 102,
CharNameRussianConsecutiveSilentCharacters = 99, CharNameRussianConsecutiveSilentCharacters = 103,
CharNameRussianSilentCharacterAtBeginningOrEnd = 100, CharNameRussianSilentCharacterAtBeginningOrEnd = 104,
CharNameDeclensionDoesntMatchBaseName = 101, CharNameDeclensionDoesntMatchBaseName = 105,
CharNameSpacesDisallowed = 102, CharNameSpacesDisallowed = 106
} }
public enum CharacterUndeleteResult public enum CharacterUndeleteResult
+96 -3
View File
@@ -1491,7 +1491,13 @@ namespace Framework.Constants
OneshotStandVar0 = 991, OneshotStandVar0 = 991,
OneshotFlycustomspell01 = 992, OneshotFlycustomspell01 = 992,
OneshotSpelleffectDecay = 993, OneshotSpelleffectDecay = 993,
CreatureSpecial = 994, StateCreatureSpecial = 994,
OneshotWareact01 = 1001,
OneshotFlycustomspell04 = 1004,
OneshotTalkSubdued = 1005,
StateEmotetalk = 1006,
StateWainteraction = 1007,
OneshotTakeOffStart = 1009,
} }
public enum GlyphSlotType public enum GlyphSlotType
@@ -1715,6 +1721,75 @@ namespace Framework.Constants
GearDiff = 8 GearDiff = 8
} }
public enum PlayerInteractionType
{
None = 0,
TradePartner = 1,
Item = 2,
Gossip = 3,
QuestGiver = 4,
Merchant = 5,
TaxiNode = 6,
Trainer = 7,
Banker = 8,
AlliedRaceDetailsGiver = 9,
GuildBanker = 10,
Registrar = 11,
Vendor = 12,
PetitionVendor = 13,
TabardVendor = 14,
TalentMaster = 15,
SpecializationMaster = 16,
MailInfo = 17,
SpiritHealer = 18,
AreaSpiritHealer = 19,
Binder = 20,
Auctioneer = 21,
StableMaster = 22,
BattleMaster = 23,
Transmogrifier = 24,
LFGDungeon = 25,
VoidStorageBanker = 26,
BlackMarketAuctioneer = 27,
AdventureMap = 28,
WorldMap = 29,
GarrArchitect = 30,
GarrTradeskill = 31,
GarrMission = 32,
ShipmentCrafter = 33,
GarrRecruitment = 34,
GarrTalent = 35,
Trophy = 36,
PlayerChoice = 37,
ArtifactForge = 38,
ObliterumForge = 39,
ScrappingMachine = 40,
ContributionCollector = 41,
AzeriteRespec = 42,
IslandQueue = 43,
ItemInteraction = 44,
ChromieTime = 45,
CovenantPreview = 46,
AnimaDiversion = 47,
LegendaryCrafting = 48,
WeeklyRewards = 49,
Soulbind = 50,
CovenantSanctum = 51,
NewPlayerGuide = 52,
ItemUpgrade = 53,
AdventureJournal = 54,
Renown = 55,
AzeriteForge = 56,
PerksProgramVendor = 57,
ProfessionsCraftingOrder = 58,
Professions = 59,
ProfessionsCustomerOrder = 60,
TraitSystem = 61,
BarbersChoice = 62,
JailersTowerBuffs = 63,
MajorFactionRenown = 64
}
public enum PrestigeLevelInfoFlags : byte public enum PrestigeLevelInfoFlags : byte
{ {
Disabled = 0x01 // Prestige levels with this flag won't be included to calculate max prestigelevel. Disabled = 0x01 // Prestige levels with this flag won't be included to calculate max prestigelevel.
@@ -2129,6 +2204,23 @@ namespace Framework.Constants
CreatureSpellDamage = 9 CreatureSpellDamage = 9
} }
[Flags]
public enum TraitCombatConfigFlags
{
None = 0x0,
ActiveForSpec = 0x1,
StarterBuild = 0x2,
SharedActionBars = 0x4
}
public enum TraitConfigType
{
Invalid = 0,
Combat = 1,
Profession = 2,
Generic = 3
}
public enum UiMapFlag public enum UiMapFlag
{ {
None = 0x00, None = 0x00,
@@ -2426,7 +2518,7 @@ namespace Framework.Constants
ContentTuningPvpItemLevelDamageScaling = 15, ContentTuningPvpItemLevelDamageScaling = 15,
} }
public enum BattlePetSpeciesFlags : ushort public enum BattlePetSpeciesFlags : int
{ {
NoRename = 0x01, NoRename = 0x01,
WellKnown = 0x02, WellKnown = 0x02,
@@ -2443,7 +2535,8 @@ namespace Framework.Constants
NoLicenseRequired = 0x1000, NoLicenseRequired = 0x1000,
AddsAllowedWithBoss = 0x2000, AddsAllowedWithBoss = 0x2000,
HideUntilLearned = 0x4000, HideUntilLearned = 0x4000,
MatchPlayerHighPetLevel = 0x8000 MatchPlayerHighPetLevel = 0x8000,
NoWildPetAddsAllowed = 0x10000,
} }
public enum SpellVisualEffectNameType public enum SpellVisualEffectNameType
+27 -13
View File
@@ -13,7 +13,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
namespace Framework.Constants namespace Framework.Constants
{ {
@@ -48,24 +48,24 @@ namespace Framework.Constants
{ {
None = 0, // White chat bubble. Default None = 0, // White chat bubble. Default
Vendor = 1, // Brown bag Vendor = 1, // Brown bag
TaxiNode = 2, // White wing Taxinode = 2, // White wing
Trainer = 3, // Brown book Trainer = 3, // Brown book
SpiritHealer = 4, // Golden interaction wheel (with red center) SpiritHealer = 4, // Golden interaction wheel (with red center)
Binder = 5, // Golden interaction wheel Binder = 5, // Golden interaction wheel
Banker = 6, // Brown bag (with gold coin in lower corner) Banker = 6, // Brown bag (with gold coin in lower corner)
PetitionVendor = 7, // White chat bubble (with "..." inside) PetitionVendor = 7, // White chat bubble (with "..." inside)
TabardVendor = 8, // White tabard TabardVendor = 8, // White tabard
BattleMaster = 9, // Two crossed swords Battlemaster = 9, // Two crossed swords
Auctioneer = 10, // Stack of gold coins Auctioneer = 10, // Stack of gold coins
TalentMaster = 11, // White chat bubble TalentMaster = 11, // White chat bubble
StableMaster = 12, // White chat bubble Stablemaster = 12, // White chat bubble
PetSpecializationMaster = 13, /*DEPRECATED*/ // White chat bubble PetSpecializationMaster = 13, /*DEPRECATED*/ // White chat bubble
GuildBanker = 14, /*NYI*/ // White chat bubble GuildBanker = 14, // White chat bubble
SpellClick = 15, /*NYI*/ // White chat bubble Spellclick = 15, // White chat bubble
DisableXPGain = 16, // White chat bubble DisableXPGain = 16, // White chat bubble
EnableXPGain = 17, // White chat bubble EnableXPGain = 17, // White chat bubble
Mailbox = 18, // White chat bubble Mailbox = 18, // White chat bubble
WorldPVPQueue = 19, /*NYI*/ // White chat bubble WorldPvPQueue = 19, /*NYI*/ // White chat bubble
LFGDungeon = 20, /*NYI*/ // White chat bubble LFGDungeon = 20, /*NYI*/ // White chat bubble
ArtifactRespec = 21, /*NYI*/ // White chat bubble ArtifactRespec = 21, /*NYI*/ // White chat bubble
CemeterySelect = 22, /*DEPRECATED*/ // White chat bubble CemeterySelect = 22, /*DEPRECATED*/ // White chat bubble
@@ -73,25 +73,33 @@ namespace Framework.Constants
GlyphMaster = 24, /*DEPRECATED*/ // White chat bubble GlyphMaster = 24, /*DEPRECATED*/ // White chat bubble
QueueScenario = 25, /*NYI*/ // White chat bubble QueueScenario = 25, /*NYI*/ // White chat bubble
GarrisonArchitect = 26, /*NYI*/ // White chat bubble GarrisonArchitect = 26, /*NYI*/ // White chat bubble
GarrisonMission = 27, /*NYI*/ // White chat bubble GarrisonMissionNpc = 27, /*NYI*/ // White chat bubble
ShipmentCrafter = 28, /*NYI*/ // Brown document ShipmentCrafter = 28, /*NYI*/ // Brown document
GarrisonTradeskill = 29, /*NYI*/ // White chat bubble GarrisonTradeskillNpc = 29, /*NYI*/ // White chat bubble
GarrisonRecruitment = 30, /*NYI*/ // White chat bubble GarrisonRecruitment = 30, /*NYI*/ // White chat bubble
AdventureMap = 31, /*NYI*/ // White chat bubble AdventureMap = 31, /*NYI*/ // White chat bubble
GarrisonTalent = 32, // White chat bubble GarrisonTalent = 32, // White chat bubble
ContributionCollector = 33, /*NYI*/ // White chat bubble ContributionCollector = 33, /*NYI*/ // White chat bubble
Transmogrify = 34, // Purple helm Transmogrify = 34, // Purple helm
AzeriteRespec = 35, // White chat bubble AzeriteRespec = 35, // White chat bubble
IslandsMission = 36, /*NYI*/ // White chat bubble IslandsMissionNpc = 36, /*NYI*/ // White chat bubble
UIItemInteraction = 37, /*NYI*/ // White chat bubble UIItemInteraction = 37, /*NYI*/ // White chat bubble
WorldMap = 38, /*NYI*/ // White chat bubble WorldMap = 38, /*NYI*/ // White chat bubble
Soulbind = 39, /*NYI*/ // White chat bubble Soulbind = 39, /*NYI*/ // White chat bubble
ChromieTime = 40, /*NYI*/ // White chat bubble ChromieTimeNpc = 40, /*NYI*/ // White chat bubble
CovenantPreview = 41, /*NYI*/ // White chat bubble CovenantPreviewNpc = 41, /*NYI*/ // White chat bubble
RuneforgeLegendaryCrafting = 42, /*NYI*/ // White chat bubble RuneforgeLegendaryCrafting = 42, /*NYI*/ // White chat bubble
NewPlayerGuide = 43, /*NYI*/ // White chat bubble NewPlayerGuide = 43, /*NYI*/ // White chat bubble
RuneforgeLegendaryUpgrade = 44, /*NYI*/ // White chat bubble RuneforgeLegendaryUpgrade = 44, /*NYI*/ // White chat bubble
CovenantRenown = 45, /*NYI*/ // White chat bubble CovenantRenownNpc = 45, /*NYI*/ // White chat bubble
BlackMarketAuctionHouse = 46,
PerksProgramVendor = 47,
ProfessionsCraftingOrder = 48,
ProfessionsOpen = 49,
ProfessionsCustomerOrder = 50,
TraitSystem = 51,
BarbersChoice = 52,
MajorFactionRenown = 53,
Max Max
} }
@@ -162,4 +170,10 @@ namespace Framework.Constants
Item = 0, Item = 0,
Currency = 1 Currency = 1
} }
public enum GossipOptionFlags
{
None = 0x0,
QuestLabelPrepend = 0x1
}
} }
+5 -1
View File
@@ -13,7 +13,9 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System;
namespace Framework.Constants namespace Framework.Constants
{ {
@@ -60,6 +62,7 @@ namespace Framework.Constants
WorldPvp = 4, WorldPvp = 4,
} }
[Flags]
public enum GroupFlags public enum GroupFlags
{ {
None = 0x00, None = 0x00,
@@ -71,6 +74,7 @@ namespace Framework.Constants
OnePersonParty = 0x020, // Script_IsOnePersonParty() OnePersonParty = 0x020, // Script_IsOnePersonParty()
EveryoneAssistant = 0x040, // Script_IsEveryoneAssistant() EveryoneAssistant = 0x040, // Script_IsEveryoneAssistant()
GuildGroup = 0x100, GuildGroup = 0x100,
CrossFaction = 0x200,
MaskBgRaid = FakeRaid | Raid MaskBgRaid = FakeRaid | Raid
} }
+112 -25
View File
@@ -102,29 +102,65 @@ namespace Framework.Constants
}; };
} }
public struct ProfessionSlots
{
public const byte Profession1Tool = 19;
public const byte Profession1Gear1 = 20;
public const byte Profession1Gear2 = 21;
public const byte Profession2Tool = 22;
public const byte Profession2Gear1 = 23;
public const byte Profession2Gear2 = 24;
public const byte CookingTool = 25;
public const byte CookingGear1 = 26;
public const byte FishingTool = 27;
public const byte FishingGear1 = 28;
public const byte FishingGear2 = 29;
public const byte End = 30;
public const byte Start = Profession1Tool;
}
public struct InventorySlots public struct InventorySlots
{ {
public const byte BagStart = 19; public const byte BagStart = 30;
public const byte BagEnd = 23; public const byte BagEnd = 34;
public const byte ItemStart = 23;
public const byte ItemEnd = 51;
public const byte BankItemStart = 51; public const byte ReagentBagStart = 34;
public const byte BankItemEnd = 79; public const byte ReagentBagEnd = 35;
public const byte BankBagStart = 79;
public const byte BankBagEnd = 86;
public const byte BuyBackStart = 86; public const byte ItemStart = 35;
public const byte BuyBackEnd = 98; public const byte ItemEnd = 63;
public const byte ReagentStart = 98;
public const byte ReagentEnd = 196; public const byte BankItemStart = 63;
public const byte ChildEquipmentStart = 196; public const byte BankItemEnd = 91;
public const byte ChildEquipmentEnd = 199;
public const byte BankBagStart = 91;
public const byte BankBagEnd = 98;
public const byte BuyBackStart = 98;
public const byte BuyBackEnd = 110;
public const byte ReagentStart = 110;
public const byte ReagentEnd = 208;
public const byte ChildEquipmentStart = 208;
public const byte ChildEquipmentEnd = 211;
public const byte Bag0 = 255; public const byte Bag0 = 255;
public const byte DefaultSize = 16; public const byte DefaultSize = 16;
} }
enum EquipableSpellSlots
{
OffensiveSlot1 = 211,
OffensiveSlot2 = 212,
OffensiveSlot3 = 213,
OffensiveSlot4 = 214,
UtilitySlot1 = 215,
DefensiveSlot1 = 216,
MobilitySlot1 = 217
}
public struct EquipmentSlot public struct EquipmentSlot
{ {
public const byte Start = 0; public const byte Start = 0;
@@ -462,6 +498,20 @@ namespace Framework.Constants
RaidHeroicExtended = 84, RaidHeroicExtended = 84,
RaidMythicExtended = 85, RaidMythicExtended = 85,
CharacterTemplate91 = 86, CharacterTemplate91 = 86,
ChallengeMode4 = 87,
PvpRanked9 = 88,
RaidNormalExtended2 = 89,
RaidFinderExtended2 = 90,
RaidHeroicExtended2 = 91,
RaidMythicExtended2 = 92,
RaidNormalExtended3 = 93,
RaidFinderExtended3 = 94,
RaidHeroicExtended3 = 95,
RaidMythicExtended3 = 96,
TemplateCharacter1 = 97,
TemplateCharacter2 = 98,
TemplateCharacter3 = 99,
TemplateCharacter4 = 100,
Max Max
} }
@@ -537,7 +587,13 @@ namespace Framework.Constants
RangedRight = 26, RangedRight = 26,
Quiver = 27, Quiver = 27,
Relic = 28, Relic = 28,
Max = 29 ProfessionTool = 29,
ProfessionGear = 30,
EquipableSpellOffensive = 31,
EquipableSpellUtility = 32,
EquipableSpellDefensive = 33,
EquipableSpellMobility = 34,
Max
} }
public enum VisibleEquipmentSlot public enum VisibleEquipmentSlot
@@ -586,7 +642,8 @@ namespace Framework.Constants
Glyph = 16, Glyph = 16,
BattlePets = 17, BattlePets = 17,
WowToken = 18, WowToken = 18,
Max = 19 Profession = 19,
Max
} }
public enum ItemSubClassConsumable public enum ItemSubClassConsumable
@@ -601,7 +658,7 @@ namespace Framework.Constants
Bandage = 7, Bandage = 7,
ConsumableOther = 8, ConsumableOther = 8,
VantusRune = 9, VantusRune = 9,
Max = 10 Max
} }
public enum ItemSubClassContainer public enum ItemSubClassContainer
@@ -617,7 +674,8 @@ namespace Framework.Constants
InscriptionContainer = 8, InscriptionContainer = 8,
TackleContainer = 9, TackleContainer = 9,
CookingContainer = 10, CookingContainer = 10,
Max = 11 ReagentContainer = 11,
Max
} }
public enum ItemSubClassWeapon public enum ItemSubClassWeapon
@@ -664,7 +722,7 @@ namespace Framework.Constants
Other = 9, Other = 9,
MultipleStats = 10, MultipleStats = 10,
ArtifactRelic = 11, ArtifactRelic = 11,
Max = 12 Max
} }
public enum ItemSubClassArmor public enum ItemSubClassArmor
@@ -681,14 +739,15 @@ namespace Framework.Constants
Totem = 9, Totem = 9,
Sigil = 10, Sigil = 10,
Relic = 11, Relic = 11,
Max = 12 Max
} }
public enum ItemSubClassReagent public enum ItemSubClassReagent
{ {
Reagent = 0, Reagent = 0,
Keystone = 1, Keystone = 1,
Max = 2 ContextToken = 2,
Max
} }
public enum ItemSubClassProjectile public enum ItemSubClassProjectile
@@ -698,7 +757,7 @@ namespace Framework.Constants
Arrow = 2, Arrow = 2,
Bullet = 3, Bullet = 3,
Thrown = 4, // Obsolete Thrown = 4, // Obsolete
Max = 5 Max
} }
public enum ItemSubClassTradeGoods public enum ItemSubClassTradeGoods
@@ -721,7 +780,9 @@ namespace Framework.Constants
WeaponEnchantment = 15, WeaponEnchantment = 15,
Inscription = 16, Inscription = 16,
ExplosivesDevices = 17, ExplosivesDevices = 17,
Max = 18 OptionalReagent = 18,
FinishingReagent = 19,
Max
} }
public enum ItemSubclassItemEnhancement public enum ItemSubclassItemEnhancement
@@ -740,7 +801,8 @@ namespace Framework.Constants
Weapon = 11, Weapon = 11,
TwoHandedWeapon = 12, TwoHandedWeapon = 12,
ShieldOffHand = 13, ShieldOffHand = 13,
Max = 14 Misc = 14,
Max
} }
public enum ItemSubClassRecipe public enum ItemSubClassRecipe
@@ -804,7 +866,8 @@ namespace Framework.Constants
Holiday = 3, Holiday = 3,
Other = 4, Other = 4,
Mount = 5, Mount = 5,
Max = 6 MountEquipment = 6,
Max
} }
public enum ItemSubClassGlyph public enum ItemSubClassGlyph
@@ -836,6 +899,25 @@ namespace Framework.Constants
Max = 1 Max = 1
} }
public enum ItemSubclassPorfession
{
Blacksmithing = 0,
Leatherworking = 1,
Alchemy = 2,
Herbalism = 3,
Cooking = 4,
Mining = 5,
Tailoring = 6,
Engineering = 7,
Enchanting = 8,
Fishing = 9,
Skinning = 10,
Jewelcrafting = 11,
Inscription = 12,
Archaeology = 13,
Max
}
public enum ItemQuality public enum ItemQuality
{ {
Poor = 0, //Grey Poor = 0, //Grey
@@ -1144,6 +1226,11 @@ namespace Framework.Constants
NotInNPE = 110,// Not available during the tutorial NotInNPE = 110,// Not available during the tutorial
ItemCooldown = 111,// Item is not ready yet. ItemCooldown = 111,// Item is not ready yet.
NotInRatedBattleground = 112,// You can't do that in a rated battleground. NotInRatedBattleground = 112,// You can't do that in a rated battleground.
EquipableSpellsSlotsFull = 113,
CantBeRecrafted = 114,// You can't recraft that itemv
ReagentBagWrongSlot = 115,// Reagent Bags can only be placed in the reagent bag slot.
SlotOnlyReagentBag = 116,// Only Reagent Bags can be placed in the reagent bag slot.
ReagentBagItemType = 117,// Only Reagents can be placed in Reagent Bags.
} }
public enum BuyResult public enum BuyResult
+11
View File
@@ -111,4 +111,15 @@ namespace Framework.Constants
Master = 3, // Item Can Only Be Distributed By Group Loot Master. Master = 3, // Item Can Only Be Distributed By Group Loot Master.
Owner = 4 // Ignore Binding Confirmation And Etc, For Single Player Looting Owner = 4 // Ignore Binding Confirmation And Etc, For Single Player Looting
} }
public enum LootRollIneligibilityReason
{
None = 0,
UnusableByClass = 1, // Your class may not roll need on this item.
MaxUniqueItemCount = 2, // You already have the maximum amount of this item.
CannotBeDisenchanted = 3, // This item may not be disenchanted.
EnchantingSkillTooLow = 4, // You do not have an Enchanter of skill %d in your group.
NeedDisabled = 5, // Need rolls are disabled for this item.
OwnBetterItem = 6 // You already have a powerful version of this item.
}
} }
@@ -99,5 +99,7 @@ namespace Framework.Constants
{ {
None = 0x00, None = 0x00,
DisableInertia = 0x01, DisableInertia = 0x01,
CanAdvFly = 0x02,
AdvFlying = 0x04,
} }
} }
File diff suppressed because it is too large Load Diff
+9 -7
View File
@@ -21,7 +21,7 @@ namespace Framework.Constants
{ {
public struct PlayerConst public struct PlayerConst
{ {
public const Expansion CurrentExpansion = Expansion.ShadowLands; public const Expansion CurrentExpansion = Expansion.Dragonflight;
public const int MaxTalentTiers = 7; public const int MaxTalentTiers = 7;
public const int MaxTalentColumns = 3; public const int MaxTalentColumns = 3;
@@ -35,7 +35,7 @@ namespace Framework.Constants
public const int ReqPrimaryTreeTalents = 31; public const int ReqPrimaryTreeTalents = 31;
public const int ExploredZonesSize = 192; public const int ExploredZonesSize = 192;
public const ulong MaxMoneyAmount = 99999999999UL; public const ulong MaxMoneyAmount = 99999999999UL;
public const int MaxActionButtons = 132; public const int MaxActionButtons = 180;
public const int MaxActionButtonActionValue = 0x00FFFFFF + 1; public const int MaxActionButtonActionValue = 0x00FFFFFF + 1;
public const int MaxDailyQuests = 25; public const int MaxDailyQuests = 25;
@@ -55,8 +55,6 @@ namespace Framework.Constants
public const int MaxRunes = 7; public const int MaxRunes = 7;
public const int MaxRechargingRunes = 3; public const int MaxRechargingRunes = 3;
public const int CustomDisplaySize = 3;
public const int ArtifactsAllWeaponsGeneralWeaponEquippedPassive = 197886; public const int ArtifactsAllWeaponsGeneralWeaponEquippedPassive = 197886;
public const int MaxArtifactTier = 1; public const int MaxArtifactTier = 1;
@@ -152,7 +150,9 @@ namespace Framework.Constants
Com = 0x08, // Commentator Com = 0x08, // Commentator
Dev = 0x10, Dev = 0x10,
BossSound = 0x20, // Plays "RaidBossEmoteWarning" sound on raid boss emote/whisper BossSound = 0x20, // Plays "RaidBossEmoteWarning" sound on raid boss emote/whisper
Mobile = 0x40 Mobile = 0x40,
Guide = 0x1000,
Newcomer = 0x2000
} }
public enum DrunkenState public enum DrunkenState
@@ -558,7 +558,7 @@ namespace Framework.Constants
// first slot for item stored (in any way in player items data) // first slot for item stored (in any way in player items data)
Start = 0, Start = 0,
// last+1 slot for item stored (in any way in player items data) // last+1 slot for item stored (in any way in player items data)
End = 199, End = 218,
Count = (End - Start) Count = (End - Start)
} }
@@ -753,7 +753,9 @@ namespace Framework.Constants
FailedAffectingCombat = 5, FailedAffectingCombat = 5,
FailedCantRemoveTalent = 6, FailedCantRemoveTalent = 6,
FailedCantDoThatChallengeModeActive = 7, FailedCantDoThatChallengeModeActive = 7,
FailedRestArea = 8 FailedRestArea = 8,
UnspentTalentPoints = 9,
InPvpMatch = 10
} }
public enum TutorialsFlag public enum TutorialsFlag
File diff suppressed because it is too large Load Diff
@@ -528,10 +528,34 @@ namespace Framework.Constants
ModHealingTakenFromCaster = 504, ModHealingTakenFromCaster = 504,
ModPlayerChoiceRerolls = 505, // NYI ModPlayerChoiceRerolls = 505, // NYI
DisableInertia = 506, // NYI DisableInertia = 506, // NYI
Unk507 = 507, ModDamageTakenFromCasterByLabel = 507,
Unk508 = 508, Unk508 = 508,
Unk509 = 509, Unk509 = 509,
ModifiedRaidInstance = 510, // Related to "Fated" raid affixes ModifiedRaidInstance = 510, // NYI; Related to "Fated" raid affixes
ApplyProfessionEffect = 511, // Nyi; Miscvalue[0] = Professioneffectid
Unk512 = 512,
Unk513 = 513,
Unk514 = 514,
Unk515 = 515,
Unk516 = 516,
Unk517 = 517,
Unk518 = 518,
ModCooldownRecoveryRateAll = 519, // Nyi; Applies To All Spells, Not Filtered By Familyflags Or Label
Unk520 = 520,
Unk521 = 521,
Unk522 = 522,
Unk523 = 523,
Unk524 = 524,
DisplayProfessionEquipment = 525, // Nyi; Miscvalue[0] = Profession (Enum, Not Id)
Unk526 = 526,
Unk527 = 527,
AllowBlockingSpells = 528, // Nyi
ModSpellBlockChance = 529, // Nyi
Unk530 = 530,
Unk531 = 531,
Unk532 = 532,
DisableNavigation = 533, // Disables Map Pins
Unk534 = 534,
Total Total
} }
@@ -473,8 +473,8 @@ namespace Framework.Constants
BadTargets = 13, BadTargets = 13,
PvpTargetWhileUnflagged = 14, PvpTargetWhileUnflagged = 14,
CantBeCharmed = 15, CantBeCharmed = 15,
CantBeDisenchanted = 16, CantBeSalvaged = 16,
CantBeDisenchantedSkill = 17, CantBeSalvagedSkill = 17,
CantBeEnchanted = 18, CantBeEnchanted = 18,
CantBeMilled = 19, CantBeMilled = 19,
CantBeProspected = 20, CantBeProspected = 20,
@@ -767,13 +767,16 @@ namespace Framework.Constants
IneligibleWeaponAppearance = 307, IneligibleWeaponAppearance = 307,
PlayerCondition = 308, PlayerCondition = 308,
NotWhileChromieTimed = 309, NotWhileChromieTimed = 309,
OptionalReagents = 310, CraftingReagents = 310,
SpectatorOrCommentator = 311, SpectatorOrCommentator = 311,
SoulbindConduitLearnFailedInvalidCovenant = 312, SoulbindConduitLearnFailedInvalidCovenant = 312,
ShadowlandsRidingRequirement = 313, ShadowlandsRidingRequirement = 313,
NotInMageTower = 314, NotInMageTower = 314,
GarrisonFollowerAtMinLevel = 315, GarrisonFollowerAtMinLevel = 315,
Unknown = 316, CantBeRecrafted = 316,
PassiveReplaced = 317,
CantFlyHere = 318,
Unknown = 319,
// Ok Cast Value - Here In Case A Future Version Removes Success And We Need To Use A Custom Value (Not Sent To Client Either Way) // Ok Cast Value - Here In Case A Future Version Removes Success And We Need To Use A Custom Value (Not Sent To Client Either Way)
SpellCastOk = Success SpellCastOk = Success
@@ -1357,7 +1360,45 @@ namespace Framework.Constants
YouHaveOtherWaysToSummonPocopoc = 635, // You Have Other Ways To Summon Pocopoc While In Zereth Mortis. YouHaveOtherWaysToSummonPocopoc = 635, // You Have Other Ways To Summon Pocopoc While In Zereth Mortis.
RequiresMoreSyllabicRecall = 636, // Requires More Syllabic Recall. RequiresMoreSyllabicRecall = 636, // Requires More Syllabic Recall.
ThisBattlePetCannotRideOnMagicSaucer = 637, // This Battle Pet Is Unable To Ride On The Magic Saucer. ThisBattlePetCannotRideOnMagicSaucer = 637, // This Battle Pet Is Unable To Ride On The Magic Saucer.
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. PocopocIsUnavailableOnQuestline = 640, // Pocopoc Is Unavailable To Summon During The Questline A Means To An End.
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.
YouHaveNotLearnedBarrelRoll = 790, // You Have Not Learned Barrel Roll.
TargetMustBeAnEliteElemental = 791, // Target Must Be An Elite Elemental.
SkillCheckAlreadyFailed = 792, // Skill Check Already Failed.
YourTargetWasRecentlyFed = 793, // Your Target Was Recently Fed.
CannotLureElusiveCreatureTowardsTown = 794, // You Cannot Lure An Elusive Creature Towards A Town.
NoWorthwhileCreaturesInAreaToLureOut = 795, // There Are No Worthwhile Creatures In This Area To Lure Out.
CannotLureWildBeast = 796, // This Is A Daycare For Whelps. Why Would You Try To Lure A Wild Beast Here...?
YouHaveNoArcaneEssencesInYourInventory = 797, // You Have No Arcane Essences In Your Inventory.
ThatPlayerIsCurrentlyNotInterestedInEngagingWithYourShenanigans = 798, // That Player Is Currently Not Interested In Engaging With Your Shenanigans.
CantBeCastOnNonPlayerCharacters = 799, // Can'T Be Cast On Non Player Characters.
ASignalFlareWasRecentlyFiredAtThisLocation = 800, // A Signal Flare Was Recently Fired At This Location.
ThisTinkerIsTooComplicatedForYou = 801, // This Tinker Is Too Complicated For You.
TheDuckRefusesToPlayWhileAnotherMaestroIsNearby = 802, // The Duck Refuses To Play While Another Maestro Is Nearby.
YouHaveStudiedTheseNotesExtensivelyandThereIsNothingNewToLearnFromThem = 803, // You Have Studied These Notes Extensively And There Is Nothing New To Learn From Them.
YouDontHaveEnoughGold = 804, // You Don'T Have Enough Gold.
YouDoNotKnowHowToTameOttuk = 805, // You Do Not Know How To Tame Ottuk.
ClanAylaagIsCurrentlyTravellingandCannotBeTeleportedTo = 806, // Clan Aylaag Is Currently Travelling And Cannot Be Teleported To.
NotEnoughInsanity = 807, // Not Enough Insanity
YouMustWaitToAccessThisAgain = 808, // You Must Wait To Access This Again.
YouDoNotKnowHowToTameDragonkin = 809, // You Do Not Know How To Tame Dragonkin.
RequiresAnEmptySoulCage = 810, // Requires An Empty Soul Cage.
YouAlreadyHaveACagedSoulOfThatType = 811, // You Already Have A Caged Soul Of That Type.
YouCantDoThatHere = 812, // You Can'T Do That Here.
YouDoNotHaveAnyElementalGemsSocketed = 813, // You Do Not Have Any Elemental Gems Socketed.
YouMustBeInTheDragonIsles = 814, // You Must Be In The Dragon Isles.
YouCannotDoThatWhileUnderwater = 815, // You Cannot Do That While Underwater.
YouMustBeRidingAStolenTameMagmammoth = 816, // You Must Be Riding A Stolen Tame Magmammoth.
YouMustBeFlyingAboveWaterInsideAnActiveTuskarrFishingHole = 817, // You Must Be Flying Above Water Inside An Active Tuskarr Fishing Hole.
YouAreAlreadyBraveEnoughToContinueWithYourExperimentation = 818, // You Are Already Brave Enough To Continue With Your Experimentation.
YouDontKnowHowToRepairThisItem = 819, // You Don'T Know How To Repair This Item.
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.
} }
public enum SpellMissInfo public enum SpellMissInfo
@@ -1468,7 +1509,8 @@ namespace Framework.Constants
Unk78 = 78, Unk78 = 78,
Unk91 = 91, Unk91 = 91,
Unk100 = 100, Unk100 = 100,
DemonHunter = 107 DemonHunter = 107,
Evoker = 224
} }
[Flags] [Flags]
@@ -2434,8 +2476,23 @@ namespace Framework.Constants
ModifyKeystone2 = 285, ModifyKeystone2 = 285,
GrantBattlepetExperience = 286, GrantBattlepetExperience = 286,
SetGarrisonFollowerLevel = 287, SetGarrisonFollowerLevel = 287,
Unk288 = 288, CraftItem = 288, // Miscvalue[0] = Craftingdataid
Unk289 = 289, ModifyAuraStacks = 289, // Miscvalue[0] = 0 Means Add, = 1 Means Set
ModifyCooldown = 290,
ModifyCooldowns = 291, // Miscvalue[0] = Spellfamily, Miscvalue[1] = Maybe Bit Index For Family Flags? Off By 1 For The Only Spell Using This Effect
ModifyCooldownsByCategory = 292, // Miscvalue[0] = Category
ModifyCharges = 293, // Miscvalue[0] = Charge Category
CraftLoot = 294, // Miscvalue[0] = Craftingdataid
SalvageItem = 295, // Miscvalue[0] = Itemsalvageid
CraftSalvageItem = 296, // Miscvalue[0] = Itemsalvageid, Miscvalue[1] = Craftingdataid
RecraftItem = 297,
CancelAllPrivateConversations = 298,
Unk299 = 299, // Something With Items, As Of 10.0.2 All Spells Are Named "Downgrading"
Unk300 = 300,
CraftEnchant = 301, // Miscvalue[0] = Craftingdataid, Miscvalue[1] = ?
Gathering = 302,
CreateTraitTreeConfig = 303, // Miscvalue[0] = Traittreeid
ChangeActiveCombatTraitConfig = 304,
TotalSpellEffects TotalSpellEffects
} }
+2 -1
View File
@@ -164,6 +164,7 @@ namespace Framework.Constants
ArcaneCharges, ArcaneCharges,
Fury, Fury,
Pain, Pain,
Essence,
Armor, // ARMOR..RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum. Armor, // ARMOR..RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
ResistanceHoly, ResistanceHoly,
ResistanceFire, ResistanceFire,
@@ -183,7 +184,7 @@ namespace Framework.Constants
ResistanceStart = Armor, ResistanceStart = Armor,
ResistanceEnd = ResistanceArcane + 1, ResistanceEnd = ResistanceArcane + 1,
PowerStart = Mana, PowerStart = Mana,
PowerEnd = Pain + 1 PowerEnd = Essence + 1
} }
public enum UnitModifierFlatType public enum UnitModifierFlatType
{ {
@@ -165,7 +165,7 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_BARBER_SHOP_STYLE_LOCALE, "SELECT ID, DisplayName_lang, Description_lang FROM barber_shop_style_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_BARBER_SHOP_STYLE_LOCALE, "SELECT ID, DisplayName_lang, Description_lang FROM barber_shop_style_locale WHERE locale = ?");
// BattlePetBreedQuality.db2 // BattlePetBreedQuality.db2
PrepareStatement(HotfixStatements.SEL_BATTLE_PET_BREED_QUALITY, "SELECT ID, StateMultiplier, QualityEnum FROM battle_pet_breed_quality"); PrepareStatement(HotfixStatements.SEL_BATTLE_PET_BREED_QUALITY, "SELECT ID, MaxQualityRoll, StateMultiplier, QualityEnum FROM battle_pet_breed_quality");
// BattlePetBreedState.db2 // BattlePetBreedState.db2
PrepareStatement(HotfixStatements.SEL_BATTLE_PET_BREED_STATE, "SELECT ID, BattlePetStateID, Value, BattlePetBreedID FROM battle_pet_breed_state"); PrepareStatement(HotfixStatements.SEL_BATTLE_PET_BREED_STATE, "SELECT ID, BattlePetStateID, Value, BattlePetBreedID FROM battle_pet_breed_state");
@@ -202,7 +202,7 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_CHAR_TITLES_LOCALE, "SELECT ID, Name_lang, Name1_lang FROM char_titles_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_CHAR_TITLES_LOCALE, "SELECT ID, Name_lang, Name1_lang FROM char_titles_locale WHERE locale = ?");
// CharacterLoadout.db2 // CharacterLoadout.db2
PrepareStatement(HotfixStatements.SEL_CHARACTER_LOADOUT, "SELECT ID, RaceMask, ChrClassID, Purpose, Unused910 FROM character_loadout"); PrepareStatement(HotfixStatements.SEL_CHARACTER_LOADOUT, "SELECT ID, RaceMask, ChrClassID, Purpose, ItemContext FROM character_loadout");
// CharacterLoadoutItem.db2 // CharacterLoadoutItem.db2
PrepareStatement(HotfixStatements.SEL_CHARACTER_LOADOUT_ITEM, "SELECT ID, CharacterLoadoutID, ItemID FROM character_loadout_item"); PrepareStatement(HotfixStatements.SEL_CHARACTER_LOADOUT_ITEM, "SELECT ID, CharacterLoadoutID, ItemID FROM character_loadout_item");
@@ -229,8 +229,8 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_CHR_CLASSES_X_POWER_TYPES, "SELECT ID, PowerType, ClassID FROM chr_classes_x_power_types"); PrepareStatement(HotfixStatements.SEL_CHR_CLASSES_X_POWER_TYPES, "SELECT ID, PowerType, ClassID FROM chr_classes_x_power_types");
// ChrCustomizationChoice.db2 // ChrCustomizationChoice.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE, "SELECT Name, ID, ChrCustomizationOptionID, ChrCustomizationReqID, SortOrder, UiOrderIndex, " + PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE, "SELECT Name, ID, ChrCustomizationOptionID, ChrCustomizationReqID, " +
"Flags, AddedInPatch, SwatchColor1, SwatchColor2 FROM chr_customization_choice"); "ChrCustomizationVisReqID, SortOrder, UiOrderIndex, Flags, AddedInPatch, SwatchColor1, SwatchColor2 FROM chr_customization_choice");
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE_LOCALE, "SELECT ID, Name_lang FROM chr_customization_choice_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE_LOCALE, "SELECT ID, Name_lang FROM chr_customization_choice_locale WHERE locale = ?");
// ChrCustomizationDisplayInfo.db2 // ChrCustomizationDisplayInfo.db2
@@ -240,7 +240,7 @@ namespace Framework.Database
// ChrCustomizationElement.db2 // ChrCustomizationElement.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_ELEMENT, "SELECT ID, ChrCustomizationChoiceID, RelatedChrCustomizationChoiceID, " + PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_ELEMENT, "SELECT ID, ChrCustomizationChoiceID, RelatedChrCustomizationChoiceID, " +
"ChrCustomizationGeosetID, ChrCustomizationSkinnedModelID, ChrCustomizationMaterialID, ChrCustomizationBoneSetID, " + "ChrCustomizationGeosetID, ChrCustomizationSkinnedModelID, ChrCustomizationMaterialID, ChrCustomizationBoneSetID, " +
"ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID, ChrCustItemGeoModifyID FROM chr_customization_element"); "ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID, ChrCustItemGeoModifyID, ChrCustomizationVoiceID FROM chr_customization_element");
// ChrCustomizationOption.db2 // ChrCustomizationOption.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION, "SELECT Name, ID, SecondaryID, Flags, ChrModelID, SortIndex, ChrCustomizationCategoryID, " + PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION, "SELECT Name, ID, SecondaryID, Flags, ChrModelID, SortIndex, ChrCustomizationCategoryID, " +
@@ -248,7 +248,8 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION_LOCALE, "SELECT ID, Name_lang FROM chr_customization_option_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION_LOCALE, "SELECT ID, Name_lang FROM chr_customization_option_locale WHERE locale = ?");
// ChrCustomizationReq.db2 // ChrCustomizationReq.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ, "SELECT ID, Flags, ClassMask, AchievementID, OverrideArchive, ItemModifiedAppearanceID FROM chr_customization_req"); PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ, "SELECT ID, ReqSource, Flags, ClassMask, AchievementID, QuestID, OverrideArchive, ItemModifiedAppearanceID FROM chr_customization_req");
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ_LOCALE, "SELECT ID, ReqSource_lang FROM chr_customization_req_locale WHERE locale = ?");
// ChrCustomizationReqChoice.db2 // ChrCustomizationReqChoice.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ_CHOICE, "SELECT ID, ChrCustomizationChoiceID, ChrCustomizationReqID FROM chr_customization_req_choice"); PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ_CHOICE, "SELECT ID, ChrCustomizationChoiceID, ChrCustomizationReqID FROM chr_customization_req_choice");
@@ -260,7 +261,7 @@ namespace Framework.Database
"BarberShopCameraHeightOffsetScale, BarberShopCameraRotationOffset FROM chr_model"); "BarberShopCameraHeightOffsetScale, BarberShopCameraRotationOffset FROM chr_model");
// ChrRaceXChrModel.db2 // ChrRaceXChrModel.db2
PrepareStatement(HotfixStatements.SEL_CHR_RACE_X_CHR_MODEL, "SELECT ID, ChrRacesID, ChrModelID FROM chr_race_x_chr_model"); PrepareStatement(HotfixStatements.SEL_CHR_RACE_X_CHR_MODEL, "SELECT ID, ChrRacesID, ChrModelID, Sex, AllowedTransmogSlots FROM chr_race_x_chr_model");
// ChrRaces.db2 // ChrRaces.db2
PrepareStatement(HotfixStatements.SEL_CHR_RACES, "SELECT ID, ClientPrefix, ClientFileString, Name, NameFemale, NameLowercase, NameFemaleLowercase, " + PrepareStatement(HotfixStatements.SEL_CHR_RACES, "SELECT ID, ClientPrefix, ClientFileString, Name, NameFemale, NameLowercase, NameFemaleLowercase, " +
@@ -272,7 +273,7 @@ namespace Framework.Database
"MaleModelFallbackRaceID, FemaleModelFallbackRaceID, MaleTextureFallbackRaceID, FemaleTextureFallbackRaceID, PlayableRaceBit, " + "MaleModelFallbackRaceID, FemaleModelFallbackRaceID, MaleTextureFallbackRaceID, FemaleTextureFallbackRaceID, PlayableRaceBit, " +
"HelmetAnimScalingRaceID, TransmogrifyDisabledSlotMask, UnalteredVisualCustomizationRaceID, AlteredFormCustomizeOffsetFallback1, " + "HelmetAnimScalingRaceID, TransmogrifyDisabledSlotMask, UnalteredVisualCustomizationRaceID, AlteredFormCustomizeOffsetFallback1, " +
"AlteredFormCustomizeOffsetFallback2, AlteredFormCustomizeOffsetFallback3, AlteredFormCustomizeRotationFallback, Unknown910_11, " + "AlteredFormCustomizeOffsetFallback2, AlteredFormCustomizeOffsetFallback3, AlteredFormCustomizeRotationFallback, Unknown910_11, " +
"Unknown910_12, Unknown910_13, Unknown910_21, Unknown910_22, Unknown910_23, BaseLanguage, CreatureType, MaleModelFallbackSex, " + "Unknown910_12, Unknown910_13, Unknown910_21, Unknown910_22, Unknown910_23, Unknown1000, BaseLanguage, CreatureType, MaleModelFallbackSex, " +
"FemaleModelFallbackSex, MaleTextureFallbackSex, FemaleTextureFallbackSex FROM chr_races"); "FemaleModelFallbackSex, MaleTextureFallbackSex, FemaleTextureFallbackSex FROM chr_races");
PrepareStatement(HotfixStatements.SEL_CHR_RACES_LOCALE, "SELECT ID, Name_lang, NameFemale_lang, NameLowercase_lang, NameFemaleLowercase_lang, LoreName_lang, " + PrepareStatement(HotfixStatements.SEL_CHR_RACES_LOCALE, "SELECT ID, Name_lang, NameFemale_lang, NameLowercase_lang, NameFemaleLowercase_lang, LoreName_lang, " +
"LoreNameFemale_lang, LoreNameLower_lang, LoreNameLowerFemale_lang, LoreDescription_lang, ShortName_lang, ShortNameFemale_lang, " + "LoreNameFemale_lang, LoreNameLower_lang, LoreNameLowerFemale_lang, LoreDescription_lang, ShortName_lang, ShortNameFemale_lang, " +
@@ -285,7 +286,7 @@ namespace Framework.Database
" WHERE locale = ?"); " WHERE locale = ?");
// CinematicCamera.db2 // CinematicCamera.db2
PrepareStatement(HotfixStatements.SEL_CINEMATIC_CAMERA, "SELECT ID, OriginX, OriginY, OriginZ, SoundID, OriginFacing, FileDataID, Unknown915 FROM cinematic_camera"); PrepareStatement(HotfixStatements.SEL_CINEMATIC_CAMERA, "SELECT ID, OriginX, OriginY, OriginZ, SoundID, OriginFacing, FileDataID, ConversationID FROM cinematic_camera");
// CinematicSequences.db2 // CinematicSequences.db2
PrepareStatement(HotfixStatements.SEL_CINEMATIC_SEQUENCES, "SELECT ID, SoundID, Camera1, Camera2, Camera3, Camera4, Camera5, Camera6, Camera7, Camera8 FROM cinematic_sequences"); PrepareStatement(HotfixStatements.SEL_CINEMATIC_SEQUENCES, "SELECT ID, SoundID, Camera1, Camera2, Camera3, Camera4, Camera5, Camera6, Camera7, Camera8 FROM cinematic_sequences");
@@ -310,7 +311,7 @@ namespace Framework.Database
"ExtendedDisplayInfoID, NPCSoundID, ParticleColorID, PortraitCreatureDisplayInfoID, PortraitTextureFileDataID, ObjectEffectPackageID, " + "ExtendedDisplayInfoID, NPCSoundID, ParticleColorID, PortraitCreatureDisplayInfoID, PortraitTextureFileDataID, ObjectEffectPackageID, " +
"AnimReplacementSetID, Flags, StateSpellVisualKitID, PlayerOverrideScale, PetInstanceScale, UnarmedWeaponType, MountPoofSpellVisualKitID, " + "AnimReplacementSetID, Flags, StateSpellVisualKitID, PlayerOverrideScale, PetInstanceScale, UnarmedWeaponType, MountPoofSpellVisualKitID, " +
"DissolveEffectID, Gender, DissolveOutEffectID, CreatureModelMinLod, TextureVariationFileDataID1, TextureVariationFileDataID2, " + "DissolveEffectID, Gender, DissolveOutEffectID, CreatureModelMinLod, TextureVariationFileDataID1, TextureVariationFileDataID2, " +
"TextureVariationFileDataID3 FROM creature_display_info"); "TextureVariationFileDataID3, TextureVariationFileDataID4 FROM creature_display_info");
// CreatureDisplayInfoExtra.db2 // CreatureDisplayInfoExtra.db2
PrepareStatement(HotfixStatements.SEL_CREATURE_DISPLAY_INFO_EXTRA, "SELECT ID, DisplayRaceID, DisplaySexID, DisplayClassID, Flags, BakeMaterialResourcesID, " + PrepareStatement(HotfixStatements.SEL_CREATURE_DISPLAY_INFO_EXTRA, "SELECT ID, DisplayRaceID, DisplaySexID, DisplayClassID, Flags, BakeMaterialResourcesID, " +
@@ -348,14 +349,15 @@ namespace Framework.Database
// CurrencyTypes.db2 // CurrencyTypes.db2
PrepareStatement(HotfixStatements.SEL_CURRENCY_TYPES, "SELECT ID, Name, Description, CategoryID, InventoryIconFileID, SpellWeight, SpellCategory, MaxQty, " + PrepareStatement(HotfixStatements.SEL_CURRENCY_TYPES, "SELECT ID, Name, Description, CategoryID, InventoryIconFileID, SpellWeight, SpellCategory, MaxQty, " +
"MaxEarnablePerWeek, Quality, FactionID, ItemGroupSoundsID, XpQuestDifficulty, AwardConditionID, MaxQtyWorldStateID, Flags1, Flags2 FROM currency_types"); "MaxEarnablePerWeek, Quality, FactionID, ItemGroupSoundsID, XpQuestDifficulty, AwardConditionID, MaxQtyWorldStateID, " +
"RechargingAmountPerCycle, RechargingCycleDurationMS, Flags1, Flags2 FROM currency_types");
PrepareStatement(HotfixStatements.SEL_CURRENCY_TYPES_LOCALE, "SELECT ID, Name_lang, Description_lang FROM currency_types_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_CURRENCY_TYPES_LOCALE, "SELECT ID, Name_lang, Description_lang FROM currency_types_locale WHERE locale = ?");
// Curve.db2 // Curve.db2
PrepareStatement(HotfixStatements.SEL_CURVE, "SELECT ID, Type, Flags FROM curve"); PrepareStatement(HotfixStatements.SEL_CURVE, "SELECT ID, Type, Flags FROM curve");
// CurvePoint.db2 // CurvePoint.db2
PrepareStatement(HotfixStatements.SEL_CURVE_POINT, "SELECT ID, PosX, PosY, PreSLSquishPosX, PreSLSquishPosY, CurveID, OrderIndex FROM curve_point"); PrepareStatement(HotfixStatements.SEL_CURVE_POINT, "SELECT PosX, PosY, PreSLSquishPosX, PreSLSquishPosY, ID, CurveID, OrderIndex FROM curve_point");
// DestructibleModelData.db2 // DestructibleModelData.db2
PrepareStatement(HotfixStatements.SEL_DESTRUCTIBLE_MODEL_DATA, "SELECT ID, State0ImpactEffectDoodadSet, State0AmbientDoodadSet, State1Wmo, " + PrepareStatement(HotfixStatements.SEL_DESTRUCTIBLE_MODEL_DATA, "SELECT ID, State0ImpactEffectDoodadSet, State0AmbientDoodadSet, State1Wmo, " +
@@ -369,8 +371,8 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_DIFFICULTY_LOCALE, "SELECT ID, Name_lang FROM difficulty_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_DIFFICULTY_LOCALE, "SELECT ID, Name_lang FROM difficulty_locale WHERE locale = ?");
// DungeonEncounter.db2 // DungeonEncounter.db2
PrepareStatement(HotfixStatements.SEL_DUNGEON_ENCOUNTER, "SELECT Name, ID, MapID, DifficultyID, OrderIndex, CompleteWorldStateID, Bit, CreatureDisplayID, " + PrepareStatement(HotfixStatements.SEL_DUNGEON_ENCOUNTER, "SELECT Name, ID, MapID, DifficultyID, OrderIndex, CompleteWorldStateID, Bit, Flags, " +
"Flags, SpellIconFileID, Faction FROM dungeon_encounter"); "SpellIconFileID, Faction FROM dungeon_encounter");
PrepareStatement(HotfixStatements.SEL_DUNGEON_ENCOUNTER_LOCALE, "SELECT ID, Name_lang FROM dungeon_encounter_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_DUNGEON_ENCOUNTER_LOCALE, "SELECT ID, Name_lang FROM dungeon_encounter_locale WHERE locale = ?");
// DurabilityCosts.db2 // DurabilityCosts.db2
@@ -404,15 +406,15 @@ namespace Framework.Database
// Faction.db2 // Faction.db2
PrepareStatement(HotfixStatements.SEL_FACTION, "SELECT ID, ReputationRaceMask1, ReputationRaceMask2, ReputationRaceMask3, ReputationRaceMask4, Name, " + PrepareStatement(HotfixStatements.SEL_FACTION, "SELECT ID, ReputationRaceMask1, ReputationRaceMask2, ReputationRaceMask3, ReputationRaceMask4, Name, " +
"Description, ReputationIndex, ParentFactionID, Expansion, FriendshipRepID, Flags, ParagonFactionID, ReputationClassMask1, " + "Description, ReputationIndex, ParentFactionID, Expansion, FriendshipRepID, Flags, ParagonFactionID, RenownFactionID, RenownCurrencyID, " +
"ReputationClassMask2, ReputationClassMask3, ReputationClassMask4, ReputationFlags1, ReputationFlags2, ReputationFlags3, ReputationFlags4, " + "ReputationClassMask1, ReputationClassMask2, ReputationClassMask3, ReputationClassMask4, ReputationFlags1, ReputationFlags2, " +
"ReputationBase1, ReputationBase2, ReputationBase3, ReputationBase4, ReputationMax1, ReputationMax2, ReputationMax3, ReputationMax4, " + "ReputationFlags3, ReputationFlags4, ReputationBase1, ReputationBase2, ReputationBase3, ReputationBase4, ReputationMax1, ReputationMax2, " +
"ParentFactionMod1, ParentFactionMod2, ParentFactionCap1, ParentFactionCap2 FROM faction"); "ReputationMax3, ReputationMax4, ParentFactionMod1, ParentFactionMod2, ParentFactionCap1, ParentFactionCap2 FROM faction");
PrepareStatement(HotfixStatements.SEL_FACTION_LOCALE, "SELECT ID, Name_lang, Description_lang FROM faction_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_FACTION_LOCALE, "SELECT ID, Name_lang, Description_lang FROM faction_locale WHERE locale = ?");
// FactionTemplate.db2 // FactionTemplate.db2
PrepareStatement(HotfixStatements.SEL_FACTION_TEMPLATE, "SELECT ID, Faction, Flags, FactionGroup, FriendGroup, EnemyGroup, Enemies1, Enemies2, Enemies3, " + PrepareStatement(HotfixStatements.SEL_FACTION_TEMPLATE, "SELECT ID, Faction, Flags, FactionGroup, FriendGroup, EnemyGroup, Enemies1, Enemies2, Enemies3, " +
"Enemies4, Friend1, Friend2, Friend3, Friend4 FROM faction_template"); "Enemies4, Enemies5, Enemies6, Enemies7, Enemies8, Friend1, Friend2, Friend3, Friend4, Friend5, Friend6, Friend7, Friend8 FROM faction_template");
// FriendshipRepReaction.db2 // FriendshipRepReaction.db2
PrepareStatement(HotfixStatements.SEL_FRIENDSHIP_REP_REACTION, "SELECT ID, Reaction, FriendshipRepID, ReactionThreshold, OverrideColor FROM friendship_rep_reaction"); PrepareStatement(HotfixStatements.SEL_FRIENDSHIP_REP_REACTION, "SELECT ID, Reaction, FriendshipRepID, ReactionThreshold, OverrideColor FROM friendship_rep_reaction");
@@ -517,6 +519,11 @@ namespace Framework.Database
// GlyphRequiredSpec.db2 // GlyphRequiredSpec.db2
PrepareStatement(HotfixStatements.SEL_GLYPH_REQUIRED_SPEC, "SELECT ID, ChrSpecializationID, GlyphPropertiesID FROM glyph_required_spec"); PrepareStatement(HotfixStatements.SEL_GLYPH_REQUIRED_SPEC, "SELECT ID, ChrSpecializationID, GlyphPropertiesID FROM glyph_required_spec");
// GossipNpcOption.db2
PrepareStatement(HotfixStatements.SEL_GOSSIP_NPC_OPTION, "SELECT ID, GossipNpcOption, LFGDungeonsID, TrainerID, GarrFollowerTypeID, CharShipmentID, " +
"GarrTalentTreeID, UiMapID, UiItemInteractionID, Unknown_1000_8, Unknown_1000_9, CovenantID, GossipOptionID, TraitTreeID, ProfessionID, " +
"Unknown_1002_14 FROM gossip_npc_option");
// GuildColorBackground.db2 // GuildColorBackground.db2
PrepareStatement(HotfixStatements.SEL_GUILD_COLOR_BACKGROUND, "SELECT ID, Red, Blue, Green FROM guild_color_background"); PrepareStatement(HotfixStatements.SEL_GUILD_COLOR_BACKGROUND, "SELECT ID, Red, Blue, Green FROM guild_color_background");
@@ -556,7 +563,7 @@ namespace Framework.Database
// Item.db2 // Item.db2
PrepareStatement(HotfixStatements.SEL_ITEM, "SELECT ID, ClassID, SubclassID, Material, InventoryType, SheatheType, SoundOverrideSubclassID, IconFileDataID, " + PrepareStatement(HotfixStatements.SEL_ITEM, "SELECT ID, ClassID, SubclassID, Material, InventoryType, SheatheType, SoundOverrideSubclassID, IconFileDataID, " +
"ItemGroupSoundsID, ContentTuningID, ModifiedCraftingReagentItemID FROM item"); "ItemGroupSoundsID, ContentTuningID, ModifiedCraftingReagentItemID, CraftingQualityID FROM item");
// ItemAppearance.db2 // ItemAppearance.db2
PrepareStatement(HotfixStatements.SEL_ITEM_APPEARANCE, "SELECT ID, DisplayType, ItemDisplayInfoID, DefaultIconFileDataID, UiOrder, PlayerConditionID FROM item_appearance"); PrepareStatement(HotfixStatements.SEL_ITEM_APPEARANCE, "SELECT ID, DisplayType, ItemDisplayInfoID, DefaultIconFileDataID, UiOrder, PlayerConditionID FROM item_appearance");
@@ -684,15 +691,15 @@ namespace Framework.Database
"StatPercentageOfSocket2, StatPercentageOfSocket3, StatPercentageOfSocket4, StatPercentageOfSocket5, StatPercentageOfSocket6, " + "StatPercentageOfSocket2, StatPercentageOfSocket3, StatPercentageOfSocket4, StatPercentageOfSocket5, StatPercentageOfSocket6, " +
"StatPercentageOfSocket7, StatPercentageOfSocket8, StatPercentageOfSocket9, StatPercentageOfSocket10, StatPercentEditor1, StatPercentEditor2, " + "StatPercentageOfSocket7, StatPercentageOfSocket8, StatPercentageOfSocket9, StatPercentageOfSocket10, StatPercentEditor1, StatPercentEditor2, " +
"StatPercentEditor3, StatPercentEditor4, StatPercentEditor5, StatPercentEditor6, StatPercentEditor7, StatPercentEditor8, StatPercentEditor9, " + "StatPercentEditor3, StatPercentEditor4, StatPercentEditor5, StatPercentEditor6, StatPercentEditor7, StatPercentEditor8, StatPercentEditor9, " +
"StatPercentEditor10, Stackable, MaxCount, RequiredAbility, SellPrice, BuyPrice, VendorStackCount, PriceVariance, PriceRandomValue, Flags1, " + "StatPercentEditor10, Stackable, MaxCount, MinReputation, RequiredAbility, SellPrice, BuyPrice, VendorStackCount, PriceVariance, " +
"Flags2, Flags3, Flags4, FactionRelated, ModifiedCraftingReagentItemID, ContentTuningID, PlayerLevelToItemLevelCurveID, " + "PriceRandomValue, Flags1, Flags2, Flags3, Flags4, FactionRelated, ModifiedCraftingReagentItemID, ContentTuningID, " +
"ItemNameDescriptionID, RequiredTransmogHoliday, RequiredHoliday, GemProperties, SocketMatchEnchantmentId, TotemCategoryID, InstanceBound, " + "PlayerLevelToItemLevelCurveID, ItemNameDescriptionID, RequiredTransmogHoliday, RequiredHoliday, GemProperties, SocketMatchEnchantmentId, " +
"ZoneBound1, ZoneBound2, ItemSet, LockID, PageID, ItemDelay, MinFactionID, RequiredSkillRank, RequiredSkill, ItemLevel, AllowableClass, " + "TotemCategoryID, InstanceBound, ZoneBound1, ZoneBound2, ItemSet, LockID, PageID, ItemDelay, MinFactionID, RequiredSkillRank, RequiredSkill, " +
"ArtifactID, SpellWeight, SpellWeightCategory, SocketType1, SocketType2, SocketType3, SheatheType, Material, PageMaterialID, Bonding, " + "ItemLevel, AllowableClass, ArtifactID, SpellWeight, SpellWeightCategory, SocketType1, SocketType2, SocketType3, SheatheType, Material, " +
"DamageDamageType, StatModifierBonusStat1, StatModifierBonusStat2, StatModifierBonusStat3, StatModifierBonusStat4, StatModifierBonusStat5, " + "PageMaterialID, Bonding, DamageDamageType, StatModifierBonusStat1, StatModifierBonusStat2, StatModifierBonusStat3, StatModifierBonusStat4, " +
"StatModifierBonusStat6, StatModifierBonusStat7, StatModifierBonusStat8, StatModifierBonusStat9, StatModifierBonusStat10, ContainerSlots, " + "StatModifierBonusStat5, StatModifierBonusStat6, StatModifierBonusStat7, StatModifierBonusStat8, StatModifierBonusStat9, " +
"MinReputation, RequiredPVPMedal, RequiredPVPRank, RequiredLevel, InventoryType, OverallQualityID FROM item_sparse"); "StatModifierBonusStat10, ContainerSlots, RequiredPVPMedal, RequiredPVPRank, RequiredLevel, InventoryType, OverallQualityID FROM item_sparse");
PrepareStatement(HotfixStatements.SEL_ITEM_SPARSE_LOCALE, "SELECT ID, Description_lang, Display3_lang, Display2_lang, Display1_lang, Display_lang" + PrepareStatement(HotfixStatements.SEL_ITEM_SPARSE_LOCALE, "SELECT ID, Description_lang, Display3_lang, Display2_lang, Display1_lang, Display_lang" +
" FROM item_sparse_locale WHERE locale = ?"); " FROM item_sparse_locale WHERE locale = ?");
// ItemSpec.db2 // ItemSpec.db2
@@ -720,7 +727,7 @@ namespace Framework.Database
// JournalInstance.db2 // JournalInstance.db2
PrepareStatement(HotfixStatements.SEL_JOURNAL_INSTANCE, "SELECT ID, Name, Description, MapID, BackgroundFileDataID, ButtonFileDataID, " + PrepareStatement(HotfixStatements.SEL_JOURNAL_INSTANCE, "SELECT ID, Name, Description, MapID, BackgroundFileDataID, ButtonFileDataID, " +
"ButtonSmallFileDataID, LoreFileDataID, OrderIndex, Flags, AreaID FROM journal_instance"); "ButtonSmallFileDataID, LoreFileDataID, Flags, AreaID FROM journal_instance");
PrepareStatement(HotfixStatements.SEL_JOURNAL_INSTANCE_LOCALE, "SELECT ID, Name_lang, Description_lang FROM journal_instance_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_JOURNAL_INSTANCE_LOCALE, "SELECT ID, Name_lang, Description_lang FROM journal_instance_locale WHERE locale = ?");
// JournalTier.db2 // JournalTier.db2
@@ -774,7 +781,7 @@ namespace Framework.Database
// Map.db2 // Map.db2
PrepareStatement(HotfixStatements.SEL_MAP, "SELECT ID, Directory, MapName, MapDescription0, MapDescription1, PvpShortDescription, PvpLongDescription, " + PrepareStatement(HotfixStatements.SEL_MAP, "SELECT ID, Directory, MapName, MapDescription0, MapDescription1, PvpShortDescription, PvpLongDescription, " +
"CorpseX, CorpseY, MapType, InstanceType, ExpansionID, AreaTableID, LoadingScreenID, TimeOfDayOverride, ParentMapID, CosmeticParentMapID, " + "CorpseX, CorpseY, MapType, InstanceType, ExpansionID, AreaTableID, LoadingScreenID, TimeOfDayOverride, ParentMapID, CosmeticParentMapID, " +
"TimeOffset, MinimapIconScale, CorpseMapID, MaxPlayers, WindSettingsID, ZmpFileDataID, WdtFileDataID, Flags1, Flags2, Flags3 FROM map"); "TimeOffset, MinimapIconScale, CorpseMapID, MaxPlayers, WindSettingsID, ZmpFileDataID, WdtFileDataID, NavigationMaxDistance, Flags1, Flags2, Flags3 FROM map");
PrepareStatement(HotfixStatements.SEL_MAP_LOCALE, "SELECT ID, MapName_lang, MapDescription0_lang, MapDescription1_lang, PvpShortDescription_lang, " + PrepareStatement(HotfixStatements.SEL_MAP_LOCALE, "SELECT ID, MapName_lang, MapDescription0_lang, MapDescription1_lang, PvpShortDescription_lang, " +
"PvpLongDescription_lang FROM map_locale WHERE locale = ?"); "PvpLongDescription_lang FROM map_locale WHERE locale = ?");
@@ -805,7 +812,7 @@ namespace Framework.Database
// MountCapability.db2 // MountCapability.db2
PrepareStatement(HotfixStatements.SEL_MOUNT_CAPABILITY, "SELECT ID, Flags, ReqRidingSkill, ReqAreaID, ReqSpellAuraID, ReqSpellKnownID, ModSpellAuraID, " + PrepareStatement(HotfixStatements.SEL_MOUNT_CAPABILITY, "SELECT ID, Flags, ReqRidingSkill, ReqAreaID, ReqSpellAuraID, ReqSpellKnownID, ModSpellAuraID, " +
"ReqMapID, PlayerConditionID FROM mount_capability"); "ReqMapID, PlayerConditionID, FlightCapabilityID FROM mount_capability");
// MountTypeXCapability.db2 // MountTypeXCapability.db2
PrepareStatement(HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY, "SELECT ID, MountTypeID, MountCapabilityID, OrderIndex FROM mount_type_x_capability"); PrepareStatement(HotfixStatements.SEL_MOUNT_TYPE_X_CAPABILITY, "SELECT ID, MountTypeID, MountCapabilityID, OrderIndex FROM mount_type_x_capability");
@@ -852,16 +859,18 @@ namespace Framework.Database
"MinExpansionLevel, MaxExpansionLevel, MinAvgItemLevel, MaxAvgItemLevel, MinAvgEquippedItemLevel, MaxAvgEquippedItemLevel, PhaseUseFlags, " + "MinExpansionLevel, MaxExpansionLevel, MinAvgItemLevel, MaxAvgItemLevel, MinAvgEquippedItemLevel, MaxAvgEquippedItemLevel, PhaseUseFlags, " +
"PhaseID, PhaseGroupID, Flags, ChrSpecializationIndex, ChrSpecializationRole, ModifierTreeID, PowerType, PowerTypeComp, PowerTypeValue, " + "PhaseID, PhaseGroupID, Flags, ChrSpecializationIndex, ChrSpecializationRole, ModifierTreeID, PowerType, PowerTypeComp, PowerTypeValue, " +
"WeaponSubclassMask, MaxGuildLevel, MinGuildLevel, MaxExpansionTier, MinExpansionTier, MinPVPRank, MaxPVPRank, ContentTuningID, CovenantID, " + "WeaponSubclassMask, MaxGuildLevel, MinGuildLevel, MaxExpansionTier, MinExpansionTier, MinPVPRank, MaxPVPRank, ContentTuningID, CovenantID, " +
"SkillID1, SkillID2, SkillID3, SkillID4, MinSkill1, MinSkill2, MinSkill3, MinSkill4, MaxSkill1, MaxSkill2, MaxSkill3, MaxSkill4, " + "TraitNodeEntryLogic, SkillID1, SkillID2, SkillID3, SkillID4, MinSkill1, MinSkill2, MinSkill3, MinSkill4, MaxSkill1, MaxSkill2, MaxSkill3, " +
"MinFactionID1, MinFactionID2, MinFactionID3, MinReputation1, MinReputation2, MinReputation3, PrevQuestID1, PrevQuestID2, PrevQuestID3, " + "MaxSkill4, MinFactionID1, MinFactionID2, MinFactionID3, MinReputation1, MinReputation2, MinReputation3, PrevQuestID1, PrevQuestID2, " +
"PrevQuestID4, CurrQuestID1, CurrQuestID2, CurrQuestID3, CurrQuestID4, CurrentCompletedQuestID1, CurrentCompletedQuestID2, " + "PrevQuestID3, PrevQuestID4, CurrQuestID1, CurrQuestID2, CurrQuestID3, CurrQuestID4, CurrentCompletedQuestID1, CurrentCompletedQuestID2, " +
"CurrentCompletedQuestID3, CurrentCompletedQuestID4, SpellID1, SpellID2, SpellID3, SpellID4, ItemID1, ItemID2, ItemID3, ItemID4, ItemCount1, " + "CurrentCompletedQuestID3, CurrentCompletedQuestID4, SpellID1, SpellID2, SpellID3, SpellID4, ItemID1, ItemID2, ItemID3, ItemID4, ItemCount1, " +
"ItemCount2, ItemCount3, ItemCount4, Explored1, Explored2, Time1, Time2, AuraSpellID1, AuraSpellID2, AuraSpellID3, AuraSpellID4, AuraStacks1, " + "ItemCount2, ItemCount3, ItemCount4, Explored1, Explored2, Time1, Time2, AuraSpellID1, AuraSpellID2, AuraSpellID3, AuraSpellID4, AuraStacks1, " +
"AuraStacks2, AuraStacks3, AuraStacks4, Achievement1, Achievement2, Achievement3, Achievement4, AreaID1, AreaID2, AreaID3, AreaID4, " + "AuraStacks2, AuraStacks3, AuraStacks4, Achievement1, Achievement2, Achievement3, Achievement4, AreaID1, AreaID2, AreaID3, AreaID4, " +
"LfgStatus1, LfgStatus2, LfgStatus3, LfgStatus4, LfgCompare1, LfgCompare2, LfgCompare3, LfgCompare4, LfgValue1, LfgValue2, LfgValue3, " + "LfgStatus1, LfgStatus2, LfgStatus3, LfgStatus4, LfgCompare1, LfgCompare2, LfgCompare3, LfgCompare4, LfgValue1, LfgValue2, LfgValue3, " +
"LfgValue4, CurrencyID1, CurrencyID2, CurrencyID3, CurrencyID4, CurrencyCount1, CurrencyCount2, CurrencyCount3, CurrencyCount4, " + "LfgValue4, CurrencyID1, CurrencyID2, CurrencyID3, CurrencyID4, CurrencyCount1, CurrencyCount2, CurrencyCount3, CurrencyCount4, " +
"QuestKillMonster1, QuestKillMonster2, QuestKillMonster3, QuestKillMonster4, QuestKillMonster5, QuestKillMonster6, MovementFlags1, " + "QuestKillMonster1, QuestKillMonster2, QuestKillMonster3, QuestKillMonster4, QuestKillMonster5, QuestKillMonster6, MovementFlags1, " +
"MovementFlags2 FROM player_condition"); "MovementFlags2, TraitNodeEntryID1, TraitNodeEntryID2, TraitNodeEntryID3, TraitNodeEntryID4, TraitNodeEntryMinRank1, TraitNodeEntryMinRank2, " +
"TraitNodeEntryMinRank3, TraitNodeEntryMinRank4, TraitNodeEntryMaxRank1, TraitNodeEntryMaxRank2, TraitNodeEntryMaxRank3, " +
"TraitNodeEntryMaxRank4 FROM player_condition");
PrepareStatement(HotfixStatements.SEL_PLAYER_CONDITION_LOCALE, "SELECT ID, FailureDescription_lang FROM player_condition_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_PLAYER_CONDITION_LOCALE, "SELECT ID, FailureDescription_lang FROM player_condition_locale WHERE locale = ?");
// PowerDisplay.db2 // PowerDisplay.db2
@@ -884,7 +893,7 @@ namespace Framework.Database
// PvpTalent.db2 // PvpTalent.db2
PrepareStatement(HotfixStatements.SEL_PVP_TALENT, "SELECT Description, ID, SpecID, SpellID, OverridesSpellID, Flags, ActionBarSpellID, PvpTalentCategoryID, " + PrepareStatement(HotfixStatements.SEL_PVP_TALENT, "SELECT Description, ID, SpecID, SpellID, OverridesSpellID, Flags, ActionBarSpellID, PvpTalentCategoryID, " +
"LevelRequired FROM pvp_talent"); "LevelRequired, PlayerConditionID FROM pvp_talent");
PrepareStatement(HotfixStatements.SEL_PVP_TALENT_LOCALE, "SELECT ID, Description_lang FROM pvp_talent_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_PVP_TALENT_LOCALE, "SELECT ID, Description_lang FROM pvp_talent_locale WHERE locale = ?");
// PvpTalentCategory.db2 // PvpTalentCategory.db2
@@ -921,7 +930,7 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_QUEST_SORT_LOCALE, "SELECT ID, SortName_lang FROM quest_sort_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_QUEST_SORT_LOCALE, "SELECT ID, SortName_lang FROM quest_sort_locale WHERE locale = ?");
// QuestV2.db2 // QuestV2.db2
PrepareStatement(HotfixStatements.SEL_QUEST_V2, "SELECT ID, UniqueBitFlag FROM quest_v2"); PrepareStatement(HotfixStatements.SEL_QUEST_V2, "SELECT ID, UniqueBitFlag, UiQuestDetailsTheme FROM quest_v2");
// QuestXp.db2 // QuestXp.db2
PrepareStatement(HotfixStatements.SEL_QUEST_XP, "SELECT ID, Difficulty1, Difficulty2, Difficulty3, Difficulty4, Difficulty5, Difficulty6, Difficulty7, " + PrepareStatement(HotfixStatements.SEL_QUEST_XP, "SELECT ID, Difficulty1, Difficulty2, Difficulty3, Difficulty4, Difficulty5, Difficulty6, Difficulty7, " +
@@ -965,14 +974,17 @@ namespace Framework.Database
// SkillLine.db2 // SkillLine.db2
PrepareStatement(HotfixStatements.SEL_SKILL_LINE, "SELECT DisplayName, AlternateVerb, Description, HordeDisplayName, OverrideSourceInfoDisplayName, ID, " + PrepareStatement(HotfixStatements.SEL_SKILL_LINE, "SELECT DisplayName, AlternateVerb, Description, HordeDisplayName, OverrideSourceInfoDisplayName, ID, " +
"CategoryID, SpellIconFileID, CanLink, ParentSkillLineID, ParentTierIndex, Flags, SpellBookSpellID FROM skill_line"); "CategoryID, SpellIconFileID, CanLink, ParentSkillLineID, ParentTierIndex, Flags, SpellBookSpellID, ExpansionNameSharedStringID, " +
"HordeExpansionNameSharedStringID FROM skill_line");
PrepareStatement(HotfixStatements.SEL_SKILL_LINE_LOCALE, "SELECT ID, DisplayName_lang, AlternateVerb_lang, Description_lang, HordeDisplayName_lang" + PrepareStatement(HotfixStatements.SEL_SKILL_LINE_LOCALE, "SELECT ID, DisplayName_lang, AlternateVerb_lang, Description_lang, HordeDisplayName_lang" +
" FROM skill_line_locale WHERE locale = ?"); " FROM skill_line_locale WHERE locale = ?");
// SkillLineAbility.db2 // SkillLineAbility.db2
PrepareStatement(HotfixStatements.SEL_SKILL_LINE_ABILITY, "SELECT RaceMask, ID, SkillLine, Spell, MinSkillLineRank, ClassMask, SupercedesSpell, " + PrepareStatement(HotfixStatements.SEL_SKILL_LINE_ABILITY, "SELECT RaceMask, AbilityVerb, AbilityAllVerb, ID, SkillLine, Spell, MinSkillLineRank, ClassMask, " +
"AcquireMethod, TrivialSkillLineRankHigh, TrivialSkillLineRankLow, Flags, NumSkillUps, UniqueBit, TradeSkillCategoryID, SkillupSkillLineID" + "SupercedesSpell, AcquireMethod, TrivialSkillLineRankHigh, TrivialSkillLineRankLow, Flags, NumSkillUps, UniqueBit, TradeSkillCategoryID, " +
" FROM skill_line_ability"); "SkillupSkillLineID FROM skill_line_ability");
PrepareStatement(HotfixStatements.SEL_SKILL_LINE_ABILITY_LOCALE, "SELECT ID, AbilityVerb_lang, AbilityAllVerb_lang FROM skill_line_ability_locale" +
" WHERE locale = ?");
// SkillRaceClassInfo.db2 // SkillRaceClassInfo.db2
PrepareStatement(HotfixStatements.SEL_SKILL_RACE_CLASS_INFO, "SELECT ID, RaceMask, SkillID, ClassMask, Flags, Availability, MinLevel, SkillTierID" + PrepareStatement(HotfixStatements.SEL_SKILL_RACE_CLASS_INFO, "SELECT ID, RaceMask, SkillID, ClassMask, Flags, Availability, MinLevel, SkillTierID" +
@@ -983,8 +995,8 @@ namespace Framework.Database
// SoundKit.db2 // SoundKit.db2
PrepareStatement(HotfixStatements.SEL_SOUND_KIT, "SELECT ID, SoundType, VolumeFloat, Flags, MinDistance, DistanceCutoff, EAXDef, SoundKitAdvancedID, " + PrepareStatement(HotfixStatements.SEL_SOUND_KIT, "SELECT ID, SoundType, VolumeFloat, Flags, MinDistance, DistanceCutoff, EAXDef, SoundKitAdvancedID, " +
"VolumeVariationPlus, VolumeVariationMinus, PitchVariationPlus, PitchVariationMinus, DialogType, PitchAdjust, BusOverwriteID, MaxInstances" + "VolumeVariationPlus, VolumeVariationMinus, PitchVariationPlus, PitchVariationMinus, DialogType, PitchAdjust, BusOverwriteID, MaxInstances, " +
" FROM sound_kit"); "SoundMixGroupID FROM sound_kit");
// SpecializationSpells.db2 // SpecializationSpells.db2
PrepareStatement(HotfixStatements.SEL_SPECIALIZATION_SPELLS, "SELECT Description, ID, SpecID, SpellID, OverridesSpellID, DisplayOrder" + PrepareStatement(HotfixStatements.SEL_SPECIALIZATION_SPELLS, "SELECT Description, ID, SpecID, SpellID, OverridesSpellID, DisplayOrder" +
@@ -1000,8 +1012,8 @@ namespace Framework.Database
// SpellAuraRestrictions.db2 // SpellAuraRestrictions.db2
PrepareStatement(HotfixStatements.SEL_SPELL_AURA_RESTRICTIONS, "SELECT ID, DifficultyID, CasterAuraState, TargetAuraState, ExcludeCasterAuraState, " + PrepareStatement(HotfixStatements.SEL_SPELL_AURA_RESTRICTIONS, "SELECT ID, DifficultyID, CasterAuraState, TargetAuraState, ExcludeCasterAuraState, " +
"ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, SpellID" + "ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, CasterAuraType, TargetAuraType, " +
" FROM spell_aura_restrictions"); "ExcludeCasterAuraType, ExcludeTargetAuraType, SpellID FROM spell_aura_restrictions");
// SpellCastTimes.db2 // SpellCastTimes.db2
PrepareStatement(HotfixStatements.SEL_SPELL_CAST_TIMES, "SELECT ID, Base, Minimum FROM spell_cast_times"); PrepareStatement(HotfixStatements.SEL_SPELL_CAST_TIMES, "SELECT ID, Base, Minimum FROM spell_cast_times");
@@ -1023,8 +1035,8 @@ namespace Framework.Database
"SpellClassMask3, SpellClassMask4 FROM spell_class_options"); "SpellClassMask3, SpellClassMask4 FROM spell_class_options");
// SpellCooldowns.db2 // SpellCooldowns.db2
PrepareStatement(HotfixStatements.SEL_SPELL_COOLDOWNS, "SELECT ID, DifficultyID, CategoryRecoveryTime, RecoveryTime, StartRecoveryTime, SpellID" + PrepareStatement(HotfixStatements.SEL_SPELL_COOLDOWNS, "SELECT ID, DifficultyID, CategoryRecoveryTime, RecoveryTime, StartRecoveryTime, AuraSpellID, " +
" FROM spell_cooldowns"); "SpellID FROM spell_cooldowns");
// SpellDuration.db2 // SpellDuration.db2
PrepareStatement(HotfixStatements.SEL_SPELL_DURATION, "SELECT ID, Duration, MaxDuration FROM spell_duration"); PrepareStatement(HotfixStatements.SEL_SPELL_DURATION, "SELECT ID, Duration, MaxDuration FROM spell_duration");
@@ -1050,10 +1062,10 @@ namespace Framework.Database
"ChannelInterruptFlags1, ChannelInterruptFlags2, SpellID FROM spell_interrupts"); "ChannelInterruptFlags1, ChannelInterruptFlags2, SpellID FROM spell_interrupts");
// SpellItemEnchantment.db2 // SpellItemEnchantment.db2
PrepareStatement(HotfixStatements.SEL_SPELL_ITEM_ENCHANTMENT, "SELECT ID, Name, HordeName, EffectArg1, EffectArg2, EffectArg3, EffectScalingPoints1, " + PrepareStatement(HotfixStatements.SEL_SPELL_ITEM_ENCHANTMENT, "SELECT ID, Name, HordeName, Duration, EffectArg1, EffectArg2, EffectArg3, " +
"EffectScalingPoints2, EffectScalingPoints3, IconFileDataID, MinItemLevel, MaxItemLevel, TransmogUseConditionID, TransmogCost, " + "EffectScalingPoints1, EffectScalingPoints2, EffectScalingPoints3, IconFileDataID, MinItemLevel, MaxItemLevel, TransmogUseConditionID, " +
"EffectPointsMin1, EffectPointsMin2, EffectPointsMin3, ItemVisual, Flags, RequiredSkillID, RequiredSkillRank, ItemLevel, Charges, Effect1, " + "TransmogCost, EffectPointsMin1, EffectPointsMin2, EffectPointsMin3, ItemVisual, Flags, RequiredSkillID, RequiredSkillRank, ItemLevel, " +
"Effect2, Effect3, ScalingClass, ScalingClassRestricted, ConditionID, MinLevel, MaxLevel FROM spell_item_enchantment"); "Charges, Effect1, Effect2, Effect3, ScalingClass, ScalingClassRestricted, ConditionID, MinLevel, MaxLevel FROM spell_item_enchantment");
PrepareStatement(HotfixStatements.SEL_SPELL_ITEM_ENCHANTMENT_LOCALE, "SELECT ID, Name_lang, HordeName_lang FROM spell_item_enchantment_locale WHERE locale = ?"); PrepareStatement(HotfixStatements.SEL_SPELL_ITEM_ENCHANTMENT_LOCALE, "SELECT ID, Name_lang, HordeName_lang FROM spell_item_enchantment_locale WHERE locale = ?");
// SpellItemEnchantmentCondition.db2 // SpellItemEnchantmentCondition.db2
@@ -1083,7 +1095,7 @@ namespace Framework.Database
// SpellPower.db2 // SpellPower.db2
PrepareStatement(HotfixStatements.SEL_SPELL_POWER, "SELECT ID, OrderIndex, ManaCost, ManaCostPerLevel, ManaPerSecond, PowerDisplayID, AltPowerBarID, " + PrepareStatement(HotfixStatements.SEL_SPELL_POWER, "SELECT ID, OrderIndex, ManaCost, ManaCostPerLevel, ManaPerSecond, PowerDisplayID, AltPowerBarID, " +
"PowerCostPct, PowerCostMaxPct, PowerPctPerSecond, PowerType, RequiredAuraSpellID, OptionalCost, SpellID FROM spell_power"); "PowerCostPct, PowerCostMaxPct, OptionalCostPct, PowerPctPerSecond, PowerType, RequiredAuraSpellID, OptionalCost, SpellID FROM spell_power");
// SpellPowerDifficulty.db2 // SpellPowerDifficulty.db2
PrepareStatement(HotfixStatements.SEL_SPELL_POWER_DIFFICULTY, "SELECT ID, DifficultyID, OrderIndex FROM spell_power_difficulty"); PrepareStatement(HotfixStatements.SEL_SPELL_POWER_DIFFICULTY, "SELECT ID, DifficultyID, OrderIndex FROM spell_power_difficulty");
@@ -1104,7 +1116,10 @@ namespace Framework.Database
// SpellReagents.db2 // SpellReagents.db2
PrepareStatement(HotfixStatements.SEL_SPELL_REAGENTS, "SELECT ID, SpellID, Reagent1, Reagent2, Reagent3, Reagent4, Reagent5, Reagent6, Reagent7, Reagent8, " + PrepareStatement(HotfixStatements.SEL_SPELL_REAGENTS, "SELECT ID, SpellID, Reagent1, Reagent2, Reagent3, Reagent4, Reagent5, Reagent6, Reagent7, Reagent8, " +
"ReagentCount1, ReagentCount2, ReagentCount3, ReagentCount4, ReagentCount5, ReagentCount6, ReagentCount7, ReagentCount8 FROM spell_reagents"); "ReagentCount1, ReagentCount2, ReagentCount3, ReagentCount4, ReagentCount5, ReagentCount6, ReagentCount7, ReagentCount8, " +
"ReagentRecraftCount1, ReagentRecraftCount2, ReagentRecraftCount3, ReagentRecraftCount4, ReagentRecraftCount5, ReagentRecraftCount6, " +
"ReagentRecraftCount7, ReagentRecraftCount8, ReagentSource1, ReagentSource2, ReagentSource3, ReagentSource4, ReagentSource5, ReagentSource6, " +
"ReagentSource7, ReagentSource8 FROM spell_reagents");
// SpellReagentsCurrency.db2 // SpellReagentsCurrency.db2
PrepareStatement(HotfixStatements.SEL_SPELL_REAGENTS_CURRENCY, "SELECT ID, SpellID, CurrencyTypesID, CurrencyCount FROM spell_reagents_currency"); PrepareStatement(HotfixStatements.SEL_SPELL_REAGENTS_CURRENCY, "SELECT ID, SpellID, CurrencyTypesID, CurrencyCount FROM spell_reagents_currency");
@@ -1150,7 +1165,7 @@ namespace Framework.Database
" FROM spell_visual_kit"); " FROM spell_visual_kit");
// SpellXSpellVisual.db2 // SpellXSpellVisual.db2
PrepareStatement(HotfixStatements.SEL_SPELL_X_SPELL_VISUAL, "SELECT ID, DifficultyID, SpellVisualID, Probability, Priority, SpellIconFileID, " + PrepareStatement(HotfixStatements.SEL_SPELL_X_SPELL_VISUAL, "SELECT ID, DifficultyID, SpellVisualID, Probability, Flags, Priority, SpellIconFileID, " +
"ActiveIconFileID, ViewerUnitConditionID, ViewerPlayerConditionID, CasterUnitConditionID, CasterPlayerConditionID, SpellID" + "ActiveIconFileID, ViewerUnitConditionID, ViewerPlayerConditionID, CasterUnitConditionID, CasterPlayerConditionID, SpellID" +
" FROM spell_x_spell_visual"); " FROM spell_x_spell_visual");
@@ -1221,7 +1236,7 @@ namespace Framework.Database
"Region2Z, ID, UiMapID, OrderIndex, MapID, AreaID, WmoDoodadPlacementID, WmoGroupID FROM ui_map_assignment"); "Region2Z, ID, UiMapID, OrderIndex, MapID, AreaID, WmoDoodadPlacementID, WmoGroupID FROM ui_map_assignment");
// UiMapLink.db2 // UiMapLink.db2
PrepareStatement(HotfixStatements.SEL_UI_MAP_LINK, "SELECT UiMinX, UiMinY, UiMaxX, UiMaxY, ID, ParentUiMapID, OrderIndex, ChildUiMapID, " + PrepareStatement(HotfixStatements.SEL_UI_MAP_LINK, "SELECT UiMinX, UiMinY, UiMaxX, UiMaxY, ID, ParentUiMapID, OrderIndex, ChildUiMapID, PlayerConditionID, " +
"OverrideHighlightFileDataID, OverrideHighlightAtlasID, Flags FROM ui_map_link"); "OverrideHighlightFileDataID, OverrideHighlightAtlasID, Flags FROM ui_map_link");
// UiMapXMapArt.db2 // UiMapXMapArt.db2
@@ -1417,6 +1432,7 @@ namespace Framework.Database
SEL_CHR_CUSTOMIZATION_OPTION_LOCALE, SEL_CHR_CUSTOMIZATION_OPTION_LOCALE,
SEL_CHR_CUSTOMIZATION_REQ, SEL_CHR_CUSTOMIZATION_REQ,
SEL_CHR_CUSTOMIZATION_REQ_LOCALE,
SEL_CHR_CUSTOMIZATION_REQ_CHOICE, SEL_CHR_CUSTOMIZATION_REQ_CHOICE,
@@ -1551,6 +1567,8 @@ namespace Framework.Database
SEL_GLYPH_REQUIRED_SPEC, SEL_GLYPH_REQUIRED_SPEC,
SEL_GOSSIP_NPC_OPTION,
SEL_GUILD_COLOR_BACKGROUND, SEL_GUILD_COLOR_BACKGROUND,
SEL_GUILD_COLOR_BORDER, SEL_GUILD_COLOR_BORDER,
@@ -1800,6 +1818,7 @@ namespace Framework.Database
SEL_SKILL_LINE_LOCALE, SEL_SKILL_LINE_LOCALE,
SEL_SKILL_LINE_ABILITY, SEL_SKILL_LINE_ABILITY,
SEL_SKILL_LINE_ABILITY_LOCALE,
SEL_SKILL_RACE_CLASS_INFO, SEL_SKILL_RACE_CLASS_INFO,
+108 -5
View File
@@ -2758,7 +2758,7 @@ namespace Game.Achievements
bool bagScanReachedEnd = referencePlayer.ForEachItem(ItemSearchLocation.Everywhere, item => bool bagScanReachedEnd = referencePlayer.ForEachItem(ItemSearchLocation.Everywhere, item =>
{ {
bool hasBonus = item.m_itemData.BonusListIDs._value.Any(bonusListID => bonusListIDs.Contains(bonusListID)); bool hasBonus = item.GetBonusListIDs().Any(bonusListID => bonusListIDs.Contains(bonusListID));
return !hasBonus; return !hasBonus;
}); });
@@ -2880,7 +2880,7 @@ namespace Game.Achievements
if (pvpTier == null) if (pvpTier == null)
return false; return false;
if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.GetSize()) if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false; return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[pvpTier.BracketID]; var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[pvpTier.BracketID];
@@ -2918,7 +2918,7 @@ namespace Game.Achievements
} }
case ModifierTreeType.PlayerPvpTierInBracketEqualOrGreaterThan: // 239 case ModifierTreeType.PlayerPvpTierInBracketEqualOrGreaterThan: // 239
{ {
if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.GetSize()) if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false; return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[secondaryAsset]; var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[secondaryAsset];
@@ -3475,7 +3475,7 @@ namespace Game.Achievements
if (pvpTier == null) if (pvpTier == null)
return false; return false;
if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.GetSize()) if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false; return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[pvpTier.BracketID]; var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[pvpTier.BracketID];
@@ -3486,7 +3486,7 @@ namespace Game.Achievements
} }
case ModifierTreeType.PlayerBestWeeklyWinPvpTierInBracketEqualOrGreaterThan: // 325 case ModifierTreeType.PlayerBestWeeklyWinPvpTierInBracketEqualOrGreaterThan: // 325
{ {
if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.GetSize()) if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false; return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[secondaryAsset]; var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[secondaryAsset];
@@ -3518,6 +3518,109 @@ namespace Game.Achievements
break; break;
} }
case ModifierTreeType.PlayerAuraWithLabelStackCountEqualOrGreaterThan: // 335
{
uint count = 0;
referencePlayer.HasAura(aura =>
{
if (aura.GetSpellInfo().HasLabel((uint)secondaryAsset))
count += aura.GetStackAmount();
return false;
});
if (count < reqValue)
return false;
break;
}
case ModifierTreeType.PlayerAuraWithLabelStackCountEqual: // 336
{
uint count = 0;
referencePlayer.HasAura(aura =>
{
if (aura.GetSpellInfo().HasLabel((uint)secondaryAsset))
count += aura.GetStackAmount();
return false;
});
if (count != reqValue)
return false;
break;
}
case ModifierTreeType.PlayerAuraWithLabelStackCountEqualOrLessThan: // 337
{
uint count = 0;
referencePlayer.HasAura(aura =>
{
if (aura.GetSpellInfo().HasLabel((uint)secondaryAsset))
count += aura.GetStackAmount();
return false;
});
if (count > reqValue)
return false;
break;
}
case ModifierTreeType.PlayerIsInCrossFactionGroup: // 338
{
var group = referencePlayer.GetGroup();
if (!group.GetGroupFlags().HasFlag(GroupFlags.CrossFaction))
return false;
break;
}
case ModifierTreeType.PlayerHasTraitNodeEntryInActiveConfig: // 340
{
bool hasTraitNodeEntry()
{
foreach (var traitConfig in referencePlayer.m_activePlayerData.TraitConfigs)
{
if ((TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat)
{
if (referencePlayer.m_activePlayerData.ActiveCombatTraitConfigID != traitConfig.ID
|| !((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.ActiveForSpec))
continue;
}
foreach (var traitEntry in traitConfig.Entries)
if (traitEntry.TraitNodeEntryID == reqValue)
return true;
}
return false;
}
if (!hasTraitNodeEntry())
return false;
break;
}
case ModifierTreeType.PlayerHasTraitNodeEntryInActiveConfigRankGreaterOrEqualThan: // 341
{
var traitNodeEntryRank = new Func<short?>(() =>
{
foreach (var traitConfig in referencePlayer.m_activePlayerData.TraitConfigs)
{
if ((TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat)
{
if (referencePlayer.m_activePlayerData.ActiveCombatTraitConfigID != traitConfig.ID
|| !((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.ActiveForSpec))
continue;
}
foreach (var traitEntry in traitConfig.Entries)
if (traitEntry.TraitNodeEntryID == secondaryAsset)
return (short)traitEntry.Rank;
}
return null;
})();
if (!traitNodeEntryRank.HasValue || traitNodeEntryRank < reqValue)
return false;
break;
}
case ModifierTreeType.PlayerDaysSinceLogout: // 344
if (GameTime.GetGameTime() - referencePlayer.m_playerData.LogoutTime < reqValue * Time.Day)
return false;
break;
case ModifierTreeType.PlayerCanUseItem: // 351
{
ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(reqValue);
if (itemTemplate == null || referencePlayer.CanUseItem(itemTemplate) != InventoryResult.Ok)
return false;
break;
}
default: default:
return false; return false;
} }
+2 -2
View File
@@ -113,7 +113,7 @@ namespace Game
public string BuildItemAuctionMailSubject(AuctionMailType type, AuctionPosting auction) public string BuildItemAuctionMailSubject(AuctionMailType type, AuctionPosting auction)
{ {
return BuildAuctionMailSubject(auction.Items[0].GetEntry(), type, auction.Id, auction.GetTotalItemCount(), return BuildAuctionMailSubject(auction.Items[0].GetEntry(), type, auction.Id, auction.GetTotalItemCount(),
auction.Items[0].GetModifier(ItemModifier.BattlePetSpeciesId), auction.Items[0].GetContext(), auction.Items[0].m_itemData.BonusListIDs); auction.Items[0].GetModifier(ItemModifier.BattlePetSpeciesId), auction.Items[0].GetContext(), auction.Items[0].GetBonusListIDs());
} }
public string BuildCommodityAuctionMailSubject(AuctionMailType type, uint itemId, uint itemCount) public string BuildCommodityAuctionMailSubject(AuctionMailType type, uint itemId, uint itemCount)
@@ -1998,7 +1998,7 @@ namespace Game
public class SubclassFilter public class SubclassFilter
{ {
public FilterType SubclassMask; public FilterType SubclassMask;
public uint[] InvTypes = new uint[ItemConst.MaxItemSubclassTotal]; public ulong[] InvTypes = new ulong[ItemConst.MaxItemSubclassTotal];
} }
public enum FilterType : uint public enum FilterType : uint
@@ -860,12 +860,12 @@ namespace Game.BattleGrounds
public ushort GetMinPlayersPerTeam() public ushort GetMinPlayersPerTeam()
{ {
return BattlemasterEntry.MinPlayers; return (ushort)BattlemasterEntry.MinPlayers;
} }
public ushort GetMaxPlayersPerTeam() public ushort GetMaxPlayersPerTeam()
{ {
return BattlemasterEntry.MaxPlayers; return (ushort)BattlemasterEntry.MaxPlayers;
} }
public byte GetMinLevel() public byte GetMinLevel()
+40 -1
View File
@@ -656,7 +656,7 @@ namespace Game
var pMenuItemBounds = Global.ObjectMgr.GetGossipMenuItemsMapBounds(cond.SourceGroup); var pMenuItemBounds = Global.ObjectMgr.GetGossipMenuItemsMapBounds(cond.SourceGroup);
foreach (var gossipMenuItem in pMenuItemBounds) foreach (var gossipMenuItem in pMenuItemBounds)
{ {
if (gossipMenuItem.MenuId == cond.SourceGroup && gossipMenuItem.OptionId == cond.SourceEntry) if (gossipMenuItem.MenuID == cond.SourceGroup && gossipMenuItem.OrderIndex == cond.SourceEntry)
{ {
gossipMenuItem.Conditions.Add(cond); gossipMenuItem.Conditions.Add(cond);
return true; return true;
@@ -2442,6 +2442,45 @@ namespace Game
if (condition.CovenantID != 0 && player.m_playerData.CovenantID != condition.CovenantID) if (condition.CovenantID != 0 && player.m_playerData.CovenantID != condition.CovenantID)
return false; return false;
if (condition.TraitNodeEntryID.Any(traitNodeEntryId => traitNodeEntryId != 0))
{
var getTraitNodeEntryRank = ushort? (int traitNodeEntryId) =>
{
foreach (var traitConfig in player.m_activePlayerData.TraitConfigs)
{
if ((TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat)
{
if (player.m_activePlayerData.ActiveCombatTraitConfigID != traitConfig.ID
|| !((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.ActiveForSpec))
continue;
}
foreach (var traitEntry in traitConfig.Entries)
if (traitEntry.TraitNodeEntryID == traitNodeEntryId)
return (ushort)traitEntry.Rank;
}
return null;
};
results = new bool[condition.TraitNodeEntryID.Length];
Array.Fill(results, true);
for (var i = 0; i < condition.TraitNodeEntryID.Count(); ++i)
{
if (condition.TraitNodeEntryID[i] == 0)
continue;
var rank = getTraitNodeEntryRank(condition.TraitNodeEntryID[i]);
if (!rank.HasValue)
results[i] = false;
else if (condition.TraitNodeEntryMinRank[i] != 0 && rank < condition.TraitNodeEntryMinRank[i])
results[i] = false;
else if (condition.TraitNodeEntryMaxRank[i] != 0 && rank > condition.TraitNodeEntryMaxRank[i])
results[i] = false;
}
if (!PlayerConditionLogic(condition.TraitNodeEntryLogic, results))
return false;
}
return true; return true;
} }
+19 -7
View File
@@ -164,6 +164,7 @@ namespace Game.DataStorage
GlyphBindableSpellStorage = ReadDB2<GlyphBindableSpellRecord>("GlyphBindableSpell.db2", HotfixStatements.SEL_GLYPH_BINDABLE_SPELL); GlyphBindableSpellStorage = ReadDB2<GlyphBindableSpellRecord>("GlyphBindableSpell.db2", HotfixStatements.SEL_GLYPH_BINDABLE_SPELL);
GlyphPropertiesStorage = ReadDB2<GlyphPropertiesRecord>("GlyphProperties.db2", HotfixStatements.SEL_GLYPH_PROPERTIES); GlyphPropertiesStorage = ReadDB2<GlyphPropertiesRecord>("GlyphProperties.db2", HotfixStatements.SEL_GLYPH_PROPERTIES);
GlyphRequiredSpecStorage = ReadDB2<GlyphRequiredSpecRecord>("GlyphRequiredSpec.db2", HotfixStatements.SEL_GLYPH_REQUIRED_SPEC); GlyphRequiredSpecStorage = ReadDB2<GlyphRequiredSpecRecord>("GlyphRequiredSpec.db2", HotfixStatements.SEL_GLYPH_REQUIRED_SPEC);
GossipNPCOptionStorage = ReadDB2<GossipNPCOptionRecord>("GossipNPCOption.db2", HotfixStatements.SEL_GOSSIP_NPC_OPTION);
GuildColorBackgroundStorage = ReadDB2<GuildColorBackgroundRecord>("GuildColorBackground.db2", HotfixStatements.SEL_GUILD_COLOR_BACKGROUND); GuildColorBackgroundStorage = ReadDB2<GuildColorBackgroundRecord>("GuildColorBackground.db2", HotfixStatements.SEL_GUILD_COLOR_BACKGROUND);
GuildColorBorderStorage = ReadDB2<GuildColorBorderRecord>("GuildColorBorder.db2", HotfixStatements.SEL_GUILD_COLOR_BORDER); GuildColorBorderStorage = ReadDB2<GuildColorBorderRecord>("GuildColorBorder.db2", HotfixStatements.SEL_GUILD_COLOR_BORDER);
GuildColorEmblemStorage = ReadDB2<GuildColorEmblemRecord>("GuildColorEmblem.db2", HotfixStatements.SEL_GUILD_COLOR_EMBLEM); GuildColorEmblemStorage = ReadDB2<GuildColorEmblemRecord>("GuildColorEmblem.db2", HotfixStatements.SEL_GUILD_COLOR_EMBLEM);
@@ -401,13 +402,13 @@ namespace Game.DataStorage
} }
// Check loaded DB2 files proper version // Check loaded DB2 files proper version
if (!AreaTableStorage.ContainsKey(14083) || // last area added in 9.2.7 (45114) if (!CliDB.AreaTableStorage.ContainsKey(14618) || // last area added in 10.0.2 (46741)
!CharTitlesStorage.ContainsKey(727) || // last char title added in 9.2.7 (45114) !CliDB.CharTitlesStorage.ContainsKey(749) || // last char title added in 10.0.2 (46741)
!GemPropertiesStorage.ContainsKey(3922) || // last gem property added in 9.2.7 (45114) !CliDB.GemPropertiesStorage.ContainsKey(4028) || // last gem property added in 10.0.2 (46741)
!ItemStorage.ContainsKey(199202) || // last item added in 9.2.7 (45114) !CliDB.ItemStorage.ContainsKey(202712) || // last item added in 10.0.2 (46741)
!ItemExtendedCostStorage.ContainsKey(7316) || // last item extended cost added in 9.2.7 (45114) !CliDB.ItemExtendedCostStorage.ContainsKey(7862) || // last item extended cost added in 10.0.2 (46741)
!MapStorage.ContainsKey(2559) || // last map added in 9.2.7 (45114) !CliDB.MapStorage.ContainsKey(2582) || // last map added in 10.0.2 (46741)
!SpellNameStorage.ContainsKey(387936)) // last spell added in 9.2.7 (45114) !CliDB.SpellNameStorage.ContainsKey(399311)) // last spell added in 10.0.2 (46741)
{ {
Log.outError(LogFilter.Misc, "You have _outdated_ DB2 files. Please extract correct versions from current using client."); Log.outError(LogFilter.Misc, "You have _outdated_ DB2 files. Please extract correct versions from current using client.");
Global.WorldMgr.ShutdownServ(10, ShutdownMask.Force, ShutdownExitCode.Error); Global.WorldMgr.ShutdownServ(10, ShutdownMask.Force, ShutdownExitCode.Error);
@@ -562,6 +563,7 @@ namespace Game.DataStorage
public static DB6Storage<GlyphBindableSpellRecord> GlyphBindableSpellStorage; public static DB6Storage<GlyphBindableSpellRecord> GlyphBindableSpellStorage;
public static DB6Storage<GlyphPropertiesRecord> GlyphPropertiesStorage; public static DB6Storage<GlyphPropertiesRecord> GlyphPropertiesStorage;
public static DB6Storage<GlyphRequiredSpecRecord> GlyphRequiredSpecStorage; public static DB6Storage<GlyphRequiredSpecRecord> GlyphRequiredSpecStorage;
public static DB6Storage<GossipNPCOptionRecord> GossipNPCOptionStorage;
public static DB6Storage<GuildColorBackgroundRecord> GuildColorBackgroundStorage; public static DB6Storage<GuildColorBackgroundRecord> GuildColorBackgroundStorage;
public static DB6Storage<GuildColorBorderRecord> GuildColorBorderStorage; public static DB6Storage<GuildColorBorderRecord> GuildColorBorderStorage;
public static DB6Storage<GuildColorEmblemRecord> GuildColorEmblemStorage; public static DB6Storage<GuildColorEmblemRecord> GuildColorEmblemStorage;
@@ -799,6 +801,10 @@ namespace Game.DataStorage
return row.Druid; return row.Druid;
case Class.DemonHunter: case Class.DemonHunter:
return row.DemonHunter; return row.DemonHunter;
case Class.Evoker:
return row.Evoker;
case Class.Adventurer:
return row.Adventurer;
default: default:
break; break;
} }
@@ -834,6 +840,10 @@ namespace Game.DataStorage
return row.Druid; return row.Druid;
case (int)Class.DemonHunter: case (int)Class.DemonHunter:
return row.DemonHunter; return row.DemonHunter;
case (int)Class.Evoker:
return row.Evoker;
case (int)Class.Adventurer:
return row.Adventurer;
case -1: case -1:
case -7: case -7:
return row.Item; return row.Item;
@@ -851,6 +861,8 @@ namespace Game.DataStorage
return row.DamageReplaceStat; return row.DamageReplaceStat;
case -9: case -9:
return row.DamageSecondary; return row.DamageSecondary;
case -10:
return row.ManaConsumable;
default: default:
break; break;
} }
+8 -6
View File
@@ -118,7 +118,9 @@ namespace Game.DataStorage
if (battlemaster.MaxPlayers < battlemaster.MinPlayers) if (battlemaster.MaxPlayers < battlemaster.MinPlayers)
{ {
Log.outError(LogFilter.ServerLoading, $"Battlemaster ({battlemaster.Id}) contains bad values for MinPlayers ({battlemaster.MinPlayers}) and MaxPlayers ({battlemaster.MaxPlayers}). Swapping values."); Log.outError(LogFilter.ServerLoading, $"Battlemaster ({battlemaster.Id}) contains bad values for MinPlayers ({battlemaster.MinPlayers}) and MaxPlayers ({battlemaster.MaxPlayers}). Swapping values.");
MathFunctions.Swap(ref battlemaster.MaxPlayers, ref battlemaster.MinPlayers); sbyte minPlayers = battlemaster.MinPlayers;
battlemaster.MinPlayers = (sbyte)battlemaster.MaxPlayers;
battlemaster.MaxPlayers = minPlayers;
} }
} }
@@ -196,16 +198,16 @@ namespace Game.DataStorage
ChrModelRecord model = ChrModelStorage.LookupByKey(raceModel.ChrModelID); ChrModelRecord model = ChrModelStorage.LookupByKey(raceModel.ChrModelID);
if (model != null) if (model != null)
{ {
_chrModelsByRaceAndGender[Tuple.Create((byte)raceModel.ChrRacesID, (byte)model.Sex)] = model; _chrModelsByRaceAndGender[Tuple.Create((byte)raceModel.ChrRacesID, (byte)raceModel.Sex)] = model;
var customizationOptionsForModel = customizationOptionsByModel.LookupByKey(model.Id); var customizationOptionsForModel = customizationOptionsByModel.LookupByKey(model.Id);
if (customizationOptionsForModel != null) if (customizationOptionsForModel != null)
{ {
_chrCustomizationOptionsByRaceAndGender.AddRange(Tuple.Create((byte)raceModel.ChrRacesID, (byte)model.Sex), customizationOptionsForModel); _chrCustomizationOptionsByRaceAndGender.AddRange(Tuple.Create((byte)raceModel.ChrRacesID, (byte)raceModel.Sex), customizationOptionsForModel);
uint parentRace = parentRaces.LookupByKey(raceModel.ChrRacesID); uint parentRace = parentRaces.LookupByKey(raceModel.ChrRacesID);
if (parentRace != 0) if (parentRace != 0)
_chrCustomizationOptionsByRaceAndGender.AddRange(Tuple.Create((byte)parentRace, (byte)model.Sex), customizationOptionsForModel); _chrCustomizationOptionsByRaceAndGender.AddRange(Tuple.Create((byte)parentRace, (byte)raceModel.Sex), customizationOptionsForModel);
} }
// link shapeshift displays to race/gender/form // link shapeshift displays to race/gender/form
@@ -220,7 +222,7 @@ namespace Game.DataStorage
data.Displays.Add(displayInfoByCustomizationChoice.LookupByKey(data.Choices[i].Id)); data.Displays.Add(displayInfoByCustomizationChoice.LookupByKey(data.Choices[i].Id));
} }
_chrCustomizationChoicesForShapeshifts[Tuple.Create((byte)raceModel.ChrRacesID, (byte)model.Sex, shapeshiftOptionsForModel.Item2)] = data; _chrCustomizationChoicesForShapeshifts[Tuple.Create((byte)raceModel.ChrRacesID, (byte)raceModel.Sex, shapeshiftOptionsForModel.Item2)] = data;
} }
} }
} }
@@ -2396,7 +2398,7 @@ namespace Game.DataStorage
Dictionary<short, uint> _itemLevelDeltaToBonusListContainer = new(); Dictionary<short, uint> _itemLevelDeltaToBonusListContainer = new();
MultiMap<uint, ItemBonusTreeNodeRecord> _itemBonusTrees = new(); MultiMap<uint, ItemBonusTreeNodeRecord> _itemBonusTrees = new();
Dictionary<uint, ItemChildEquipmentRecord> _itemChildEquipment = new(); Dictionary<uint, ItemChildEquipmentRecord> _itemChildEquipment = new();
ItemClassRecord[] _itemClassByOldEnum = new ItemClassRecord[19]; ItemClassRecord[] _itemClassByOldEnum = new ItemClassRecord[20];
List<uint> _itemsWithCurrencyCost = new(); List<uint> _itemsWithCurrencyCost = new();
MultiMap<uint, ItemLimitCategoryConditionRecord> _itemCategoryConditions = new(); MultiMap<uint, ItemLimitCategoryConditionRecord> _itemCategoryConditions = new();
MultiMap<uint, ItemLevelSelectorQualityRecord> _itemLevelQualitySelectorQualities = new(); MultiMap<uint, ItemLevelSelectorQualityRecord> _itemLevelQualitySelectorQualities = new();
+4 -3
View File
@@ -47,6 +47,7 @@ namespace Game.DataStorage
public sealed class BattlePetBreedQualityRecord public sealed class BattlePetBreedQualityRecord
{ {
public uint Id; public uint Id;
public int MaxQualityRoll;
public float StateMultiplier; public float StateMultiplier;
public sbyte QualityEnum; public sbyte QualityEnum;
} }
@@ -68,7 +69,7 @@ namespace Game.DataStorage
public uint SummonSpellID; public uint SummonSpellID;
public int IconFileDataID; public int IconFileDataID;
public sbyte PetTypeEnum; public sbyte PetTypeEnum;
public ushort Flags; public int Flags;
public sbyte SourceTypeEnum; public sbyte SourceTypeEnum;
public int CardUIModelSceneID; public int CardUIModelSceneID;
public int LoadoutUIModelSceneID; public int LoadoutUIModelSceneID;
@@ -96,8 +97,8 @@ namespace Game.DataStorage
public byte MinLevel; public byte MinLevel;
public byte MaxLevel; public byte MaxLevel;
public sbyte RatedPlayers; public sbyte RatedPlayers;
public byte MinPlayers; public sbyte MinPlayers;
public byte MaxPlayers; public int MaxPlayers;
public sbyte GroupsAllowed; public sbyte GroupsAllowed;
public sbyte MaxGroupSize; public sbyte MaxGroupSize;
public ushort HolidayWorldState; public ushort HolidayWorldState;
+14 -5
View File
@@ -44,8 +44,8 @@ namespace Game.DataStorage
public uint Id; public uint Id;
public long RaceMask; public long RaceMask;
public sbyte ChrClassID; public sbyte ChrClassID;
public sbyte Purpose; public int Purpose;
public sbyte Unused910; public sbyte ItemContext;
public bool IsForNewCharacter() { return Purpose == 9; } public bool IsForNewCharacter() { return Purpose == 9; }
} }
@@ -131,6 +131,7 @@ namespace Game.DataStorage
public uint Id; public uint Id;
public uint ChrCustomizationOptionID; public uint ChrCustomizationOptionID;
public uint ChrCustomizationReqID; public uint ChrCustomizationReqID;
public int ChrCustomizationVisReqID;
public ushort SortOrder; public ushort SortOrder;
public ushort UiOrderIndex; public ushort UiOrderIndex;
public int Flags; public int Flags;
@@ -159,6 +160,7 @@ namespace Game.DataStorage
public int ChrCustomizationCondModelID; public int ChrCustomizationCondModelID;
public int ChrCustomizationDisplayInfoID; public int ChrCustomizationDisplayInfoID;
public int ChrCustItemGeoModifyID; public int ChrCustItemGeoModifyID;
public int ChrCustomizationVoiceID;
} }
public sealed class ChrCustomizationOptionRecord public sealed class ChrCustomizationOptionRecord
@@ -181,9 +183,11 @@ namespace Game.DataStorage
public sealed class ChrCustomizationReqRecord public sealed class ChrCustomizationReqRecord
{ {
public uint Id; public uint Id;
public string ReqSource;
public int Flags; public int Flags;
public int ClassMask; public int ClassMask;
public int AchievementID; public int AchievementID;
public int QuestID;
public int OverrideArchive; // -1: allow any, otherwise must match OverrideArchive cvar public int OverrideArchive; // -1: allow any, otherwise must match OverrideArchive cvar
public uint ItemModifiedAppearanceID; public uint ItemModifiedAppearanceID;
@@ -223,6 +227,8 @@ namespace Game.DataStorage
public uint Id; public uint Id;
public int ChrRacesID; public int ChrRacesID;
public int ChrModelID; public int ChrModelID;
public int Sex;
public int AllowedTransmogSlots;
} }
public sealed class ChrRacesRecord public sealed class ChrRacesRecord
@@ -273,6 +279,7 @@ namespace Game.DataStorage
public float AlteredFormCustomizeRotationFallback; public float AlteredFormCustomizeRotationFallback;
public float[] Unknown910_1 = new float[3]; public float[] Unknown910_1 = new float[3];
public float[] Unknown910_2 = new float[3]; public float[] Unknown910_2 = new float[3];
public int Unknown1000;
public sbyte BaseLanguage; public sbyte BaseLanguage;
public sbyte CreatureType; public sbyte CreatureType;
public sbyte MaleModelFallbackSex; public sbyte MaleModelFallbackSex;
@@ -312,7 +319,7 @@ namespace Game.DataStorage
public uint SoundID; // Sound ID (voiceover for cinematic) public uint SoundID; // Sound ID (voiceover for cinematic)
public float OriginFacing; // Orientation in map used for basis for M2 co public float OriginFacing; // Orientation in map used for basis for M2 co
public uint FileDataID; // Model public uint FileDataID; // Model
public int Unknown915; public uint ConversationID;
} }
public sealed class CinematicSequencesRecord public sealed class CinematicSequencesRecord
@@ -409,7 +416,7 @@ namespace Game.DataStorage
public sbyte Gender; public sbyte Gender;
public int DissolveOutEffectID; public int DissolveOutEffectID;
public sbyte CreatureModelMinLod; public sbyte CreatureModelMinLod;
public int[] TextureVariationFileDataID = new int[3]; public int[] TextureVariationFileDataID = new int[4];
} }
public sealed class CreatureDisplayInfoExtraRecord public sealed class CreatureDisplayInfoExtraRecord
@@ -542,6 +549,8 @@ namespace Game.DataStorage
public int XpQuestDifficulty; public int XpQuestDifficulty;
public int AwardConditionID; public int AwardConditionID;
public int MaxQtyWorldStateID; public int MaxQtyWorldStateID;
public uint RechargingAmountPerCycle;
public uint RechargingCycleDurationMS;
public int[] Flags = new int[2]; public int[] Flags = new int[2];
} }
@@ -554,9 +563,9 @@ namespace Game.DataStorage
public sealed class CurvePointRecord public sealed class CurvePointRecord
{ {
public uint Id;
public Vector2 Pos; public Vector2 Pos;
public Vector2 PreSLSquishPos; public Vector2 PreSLSquishPos;
public uint Id;
public ushort CurveID; public ushort CurveID;
public byte OrderIndex; public byte OrderIndex;
} }
@@ -73,7 +73,6 @@ namespace Game.DataStorage
public int OrderIndex; public int OrderIndex;
public int CompleteWorldStateID; public int CompleteWorldStateID;
public sbyte Bit; public sbyte Bit;
public int CreatureDisplayID;
public int Flags; public int Flags;
public int SpellIconFileID; public int SpellIconFileID;
public int Faction; public int Faction;
+12 -8
View File
@@ -29,8 +29,10 @@ namespace Game.DataStorage
public ushort ParentFactionID; public ushort ParentFactionID;
public byte Expansion; public byte Expansion;
public uint FriendshipRepID; public uint FriendshipRepID;
public byte Flags; public int Flags;
public ushort ParagonFactionID; public ushort ParagonFactionID;
public int RenownFactionID;
public int RenownCurrencyID;
public short[] ReputationClassMask = new short[4]; public short[] ReputationClassMask = new short[4];
public ushort[] ReputationFlags = new ushort[4]; public ushort[] ReputationFlags = new ushort[4];
public int[] ReputationBase = new int[4]; public int[] ReputationBase = new int[4];
@@ -47,14 +49,16 @@ namespace Game.DataStorage
public sealed class FactionTemplateRecord public sealed class FactionTemplateRecord
{ {
static int MAX_FACTION_RELATIONS = 8;
public uint Id; public uint Id;
public ushort Faction; public ushort Faction;
public ushort Flags; public ushort Flags;
public byte FactionGroup; public byte FactionGroup;
public byte FriendGroup; public byte FriendGroup;
public byte EnemyGroup; public byte EnemyGroup;
public ushort[] Enemies = new ushort[4]; public ushort[] Enemies = new ushort[MAX_FACTION_RELATIONS];
public ushort[] Friend = new ushort[4]; public ushort[] Friend = new ushort[MAX_FACTION_RELATIONS];
// helpers // helpers
public bool IsFriendlyTo(FactionTemplateRecord entry) public bool IsFriendlyTo(FactionTemplateRecord entry)
@@ -64,10 +68,10 @@ namespace Game.DataStorage
if (entry.Faction != 0) if (entry.Faction != 0)
{ {
for (int i = 0; i < 4; ++i) for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Enemies[i] == entry.Faction) if (Enemies[i] == entry.Faction)
return false; return false;
for (int i = 0; i < 4; ++i) for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Friend[i] == entry.Faction) if (Friend[i] == entry.Faction)
return true; return true;
} }
@@ -80,10 +84,10 @@ namespace Game.DataStorage
if (entry.Faction != 0) if (entry.Faction != 0)
{ {
for (int i = 0; i < 4; ++i) for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Enemies[i] == entry.Faction) if (Enemies[i] == entry.Faction)
return true; return true;
for (int i = 0; i < 4; ++i) for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Friend[i] == entry.Faction) if (Friend[i] == entry.Faction)
return false; return false;
} }
@@ -92,7 +96,7 @@ namespace Game.DataStorage
public bool IsHostileToPlayers() { return (EnemyGroup & (byte)FactionMasks.Player) != 0; } public bool IsHostileToPlayers() { return (EnemyGroup & (byte)FactionMasks.Player) != 0; }
public bool IsNeutralToAll() public bool IsNeutralToAll()
{ {
for (int i = 0; i < 4; ++i) for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Enemies[i] != 0) if (Enemies[i] != 0)
return false; return false;
return EnemyGroup == 0 && FriendGroup == 0; return EnemyGroup == 0 && FriendGroup == 0;
+21 -1
View File
@@ -270,7 +270,7 @@ namespace Game.DataStorage
public ushort UiTextureKitID; public ushort UiTextureKitID;
public int GarrTalentTreeType; public int GarrTalentTreeType;
public int PlayerConditionID; public int PlayerConditionID;
public sbyte FeatureTypeIndex; public byte FeatureTypeIndex;
public sbyte FeatureSubtypeIndex; public sbyte FeatureSubtypeIndex;
public int CurrencyID; public int CurrencyID;
} }
@@ -312,6 +312,26 @@ namespace Game.DataStorage
public uint GlyphPropertiesID; public uint GlyphPropertiesID;
} }
public sealed class GossipNPCOptionRecord
{
public uint Id;
public int GossipNpcOption;
public int LFGDungeonsID;
public int TrainerID;
public int GarrFollowerTypeID;
public int CharShipmentID;
public int GarrTalentTreeID;
public int UiMapID;
public int UiItemInteractionID;
public int Unknown_1000_8;
public int Unknown_1000_9;
public int CovenantID;
public int GossipOptionID;
public int TraitTreeID;
public int ProfessionID;
public int Unknown_1002_14;
}
public sealed class GuildColorBackgroundRecord public sealed class GuildColorBackgroundRecord
{ {
public uint Id; public uint Id;
@@ -47,6 +47,8 @@ namespace Game.DataStorage
public float DeathKnight; public float DeathKnight;
public float Monk; public float Monk;
public float DemonHunter; public float DemonHunter;
public float Evoker;
public float Adventurer;
} }
public sealed class GtBattlePetXPRecord public sealed class GtBattlePetXPRecord
@@ -128,6 +130,8 @@ namespace Game.DataStorage
public float DeathKnight; public float DeathKnight;
public float Monk; public float Monk;
public float DemonHunter; public float DemonHunter;
public float Evoker;
public float Adventurer;
public float Item; public float Item;
public float Consumable; public float Consumable;
public float Gem1; public float Gem1;
@@ -136,6 +140,7 @@ namespace Game.DataStorage
public float Health; public float Health;
public float DamageReplaceStat; public float DamageReplaceStat;
public float DamageSecondary; public float DamageSecondary;
public float ManaConsumable;
} }
public sealed class GtXpRecord public sealed class GtXpRecord
+4 -3
View File
@@ -59,6 +59,7 @@ namespace Game.DataStorage
public byte ItemGroupSoundsID; public byte ItemGroupSoundsID;
public int ContentTuningID; public int ContentTuningID;
public int ModifiedCraftingReagentItemID; public int ModifiedCraftingReagentItemID;
public int CraftingQualityID;
} }
public sealed class ItemAppearanceRecord public sealed class ItemAppearanceRecord
@@ -215,7 +216,7 @@ namespace Game.DataStorage
public byte ArenaBracket; // arena slot restrictions (min slot value) public byte ArenaBracket; // arena slot restrictions (min slot value)
public byte Flags; public byte Flags;
public byte MinFactionID; public byte MinFactionID;
public byte MinReputation; public int MinReputation;
public byte RequiredAchievement; // required personal arena rating public byte RequiredAchievement; // required personal arena rating
public uint[] ItemID = new uint[ItemConst.MaxItemExtCostItems]; // required item id public uint[] ItemID = new uint[ItemConst.MaxItemExtCostItems]; // required item id
public ushort[] ItemCount = new ushort[ItemConst.MaxItemExtCostItems]; // required count of 1st item public ushort[] ItemCount = new ushort[ItemConst.MaxItemExtCostItems]; // required count of 1st item
@@ -305,7 +306,7 @@ namespace Game.DataStorage
public byte OverallQualityID; public byte OverallQualityID;
public int ExpansionID; public int ExpansionID;
public ushort MinFactionID; public ushort MinFactionID;
public byte MinReputation; public int MinReputation;
public int AllowableClass; public int AllowableClass;
public sbyte RequiredLevel; public sbyte RequiredLevel;
public ushort RequiredSkill; public ushort RequiredSkill;
@@ -356,6 +357,7 @@ namespace Game.DataStorage
public int[] StatPercentEditor = new int[ItemConst.MaxStats]; public int[] StatPercentEditor = new int[ItemConst.MaxStats];
public uint Stackable; public uint Stackable;
public uint MaxCount; public uint MaxCount;
public uint MinReputation;
public uint RequiredAbility; public uint RequiredAbility;
public uint SellPrice; public uint SellPrice;
public uint BuyPrice; public uint BuyPrice;
@@ -395,7 +397,6 @@ namespace Game.DataStorage
public byte DamageType; public byte DamageType;
public sbyte[] StatModifierBonusStat = new sbyte[ItemConst.MaxStats]; public sbyte[] StatModifierBonusStat = new sbyte[ItemConst.MaxStats];
public byte ContainerSlots; public byte ContainerSlots;
public byte MinReputation;
public byte RequiredPVPMedal; public byte RequiredPVPMedal;
public byte RequiredPVPRank; public byte RequiredPVPRank;
public sbyte RequiredLevel; public sbyte RequiredLevel;
@@ -65,7 +65,6 @@ namespace Game.DataStorage
public int ButtonFileDataID; public int ButtonFileDataID;
public int ButtonSmallFileDataID; public int ButtonSmallFileDataID;
public int LoreFileDataID; public int LoreFileDataID;
public byte OrderIndex;
public int Flags; public int Flags;
public ushort AreaID; public ushort AreaID;
} }
+4 -1
View File
@@ -51,6 +51,7 @@ namespace Game.DataStorage
public short WindSettingsID; public short WindSettingsID;
public int ZmpFileDataID; public int ZmpFileDataID;
public int WdtFileDataID; public int WdtFileDataID;
public int NavigationMaxDistance;
public uint[] Flags = new uint[3]; public uint[] Flags = new uint[3];
// Helpers // Helpers
@@ -98,6 +99,7 @@ namespace Game.DataStorage
case 1642: case 1642:
case 1643: case 1643:
case 2222: case 2222:
case 2444:
return true; return true;
default: default:
return false; return false;
@@ -107,7 +109,7 @@ namespace Game.DataStorage
public bool IsDynamicDifficultyMap() { return GetFlags().HasFlag(MapFlags.DynamicDifficulty); } public bool IsDynamicDifficultyMap() { return GetFlags().HasFlag(MapFlags.DynamicDifficulty); }
public bool IsFlexLocking() { return GetFlags().HasFlag(MapFlags.FlexibleRaidLocking); } public bool IsFlexLocking() { return GetFlags().HasFlag(MapFlags.FlexibleRaidLocking); }
public bool IsGarrison() { return GetFlags().HasFlag(MapFlags.Garrison); } public bool IsGarrison() { return GetFlags().HasFlag(MapFlags.Garrison); }
public bool IsSplitByFaction() { return Id == 609 || Id == 2175; } public bool IsSplitByFaction() { return Id == 609 || Id == 2175 || Id == 2570; }
public MapFlags GetFlags() { return (MapFlags)Flags[0]; } public MapFlags GetFlags() { return (MapFlags)Flags[0]; }
public MapFlags2 GetFlags2() { return (MapFlags2)Flags[1]; } public MapFlags2 GetFlags2() { return (MapFlags2)Flags[1]; }
@@ -213,6 +215,7 @@ namespace Game.DataStorage
public uint ModSpellAuraID; public uint ModSpellAuraID;
public short ReqMapID; public short ReqMapID;
public int PlayerConditionID; public int PlayerConditionID;
public int FlightCapabilityID;
} }
public sealed class MountTypeXCapabilityRecord public sealed class MountTypeXCapabilityRecord
+11 -6
View File
@@ -99,6 +99,7 @@ namespace Game.DataStorage
public byte MaxPVPRank; public byte MaxPVPRank;
public uint ContentTuningID; public uint ContentTuningID;
public int CovenantID; public int CovenantID;
public uint TraitNodeEntryLogic;
public ushort[] SkillID = new ushort[4]; public ushort[] SkillID = new ushort[4];
public ushort[] MinSkill = new ushort[4]; public ushort[] MinSkill = new ushort[4];
public ushort[] MaxSkill = new ushort[4]; public ushort[] MaxSkill = new ushort[4];
@@ -123,6 +124,9 @@ namespace Game.DataStorage
public uint[] CurrencyCount = new uint[4]; public uint[] CurrencyCount = new uint[4];
public uint[] QuestKillMonster = new uint[6]; public uint[] QuestKillMonster = new uint[6];
public int[] MovementFlags = new int[2]; public int[] MovementFlags = new int[2];
public int[]TraitNodeEntryID = new int[4];
public ushort[]TraitNodeEntryMinRank = new ushort[4];
public ushort[]TraitNodeEntryMaxRank = new ushort[4];
} }
public sealed class PowerDisplayRecord public sealed class PowerDisplayRecord
@@ -141,12 +145,12 @@ namespace Game.DataStorage
public string CostGlobalStringTag; public string CostGlobalStringTag;
public uint Id; public uint Id;
public PowerType PowerTypeEnum; public PowerType PowerTypeEnum;
public sbyte MinPower; public int MinPower;
public short MaxBasePower; public int MaxBasePower;
public sbyte CenterPower; public int CenterPower;
public sbyte DefaultPower; public int DefaultPower;
public sbyte DisplayModifier; public int DisplayModifier;
public short RegenInterruptTimeMS; public int RegenInterruptTimeMS;
public float RegenPeace; public float RegenPeace;
public float RegenCombat; public float RegenCombat;
public short Flags; public short Flags;
@@ -197,6 +201,7 @@ namespace Game.DataStorage
public int ActionBarSpellID; public int ActionBarSpellID;
public int PvpTalentCategoryID; public int PvpTalentCategoryID;
public int LevelRequired; public int LevelRequired;
public int PlayerConditionID;
} }
public sealed class PvpTalentCategoryRecord public sealed class PvpTalentCategoryRecord
+2 -1
View File
@@ -31,7 +31,7 @@ namespace Game.DataStorage
public LocalizedString InfoName; public LocalizedString InfoName;
public sbyte Type; public sbyte Type;
public int Modifiers; public int Modifiers;
public ushort Profession; public int Profession;
} }
public sealed class QuestLineXQuestRecord public sealed class QuestLineXQuestRecord
@@ -69,6 +69,7 @@ namespace Game.DataStorage
{ {
public uint Id; public uint Id;
public ushort UniqueBitFlag; public ushort UniqueBitFlag;
public int UiQuestDetailsTheme;
} }
public sealed class QuestXPRecord public sealed class QuestXPRecord
+22 -7
View File
@@ -97,6 +97,8 @@ namespace Game.DataStorage
public int ParentTierIndex; public int ParentTierIndex;
public ushort Flags; public ushort Flags;
public int SpellBookSpellID; public int SpellBookSpellID;
public int ExpansionNameSharedStringID;
public int HordeExpansionNameSharedStringID;
public SkillLineFlags GetFlags() => (SkillLineFlags)Flags; public SkillLineFlags GetFlags() => (SkillLineFlags)Flags;
} }
@@ -104,6 +106,8 @@ namespace Game.DataStorage
public sealed class SkillLineAbilityRecord public sealed class SkillLineAbilityRecord
{ {
public long RaceMask; public long RaceMask;
public string AbilityVerb;
public string AbilityAllVerb;
public uint Id; public uint Id;
public ushort SkillLine; public ushort SkillLine;
public uint Spell; public uint Spell;
@@ -146,7 +150,7 @@ namespace Game.DataStorage
public uint Id; public uint Id;
public uint SoundType; public uint SoundType;
public float VolumeFloat; public float VolumeFloat;
public ushort Flags; public int Flags;
public float MinDistance; public float MinDistance;
public float DistanceCutoff; public float DistanceCutoff;
public byte EAXDef; public byte EAXDef;
@@ -159,6 +163,7 @@ namespace Game.DataStorage
public float PitchAdjust; public float PitchAdjust;
public ushort BusOverwriteID; public ushort BusOverwriteID;
public byte MaxInstances; public byte MaxInstances;
public uint SoundMixGroupID;
} }
public sealed class SpecializationSpellsRecord public sealed class SpecializationSpellsRecord
@@ -194,15 +199,19 @@ namespace Game.DataStorage
public sealed class SpellAuraRestrictionsRecord public sealed class SpellAuraRestrictionsRecord
{ {
public uint Id; public uint Id;
public byte DifficultyID; public uint DifficultyID;
public byte CasterAuraState; public int CasterAuraState;
public byte TargetAuraState; public int TargetAuraState;
public byte ExcludeCasterAuraState; public int ExcludeCasterAuraState;
public byte ExcludeTargetAuraState; public int ExcludeTargetAuraState;
public uint CasterAuraSpell; public uint CasterAuraSpell;
public uint TargetAuraSpell; public uint TargetAuraSpell;
public uint ExcludeCasterAuraSpell; public uint ExcludeCasterAuraSpell;
public uint ExcludeTargetAuraSpell; public uint ExcludeTargetAuraSpell;
public int CasterAuraType;
public int TargetAuraType;
public int ExcludeCasterAuraType;
public int ExcludeTargetAuraType;
public uint SpellID; public uint SpellID;
} }
@@ -219,7 +228,7 @@ namespace Game.DataStorage
public uint SpellID; public uint SpellID;
public byte FacingCasterFlags; public byte FacingCasterFlags;
public ushort MinFactionID; public ushort MinFactionID;
public sbyte MinReputation; public int MinReputation;
public ushort RequiredAreasID; public ushort RequiredAreasID;
public byte RequiredAuraVision; public byte RequiredAuraVision;
public ushort RequiresSpellFocus; public ushort RequiresSpellFocus;
@@ -266,6 +275,7 @@ namespace Game.DataStorage
public uint CategoryRecoveryTime; public uint CategoryRecoveryTime;
public uint RecoveryTime; public uint RecoveryTime;
public uint StartRecoveryTime; public uint StartRecoveryTime;
public uint AuraSpellID;
public uint SpellID; public uint SpellID;
} }
@@ -340,6 +350,7 @@ namespace Game.DataStorage
public uint Id; public uint Id;
public string Name; public string Name;
public string HordeName; public string HordeName;
public int Duration;
public uint[] EffectArg = new uint[ItemConst.MaxItemEnchantmentEffects]; public uint[] EffectArg = new uint[ItemConst.MaxItemEnchantmentEffects];
public float[] EffectScalingPoints = new float[ItemConst.MaxItemEnchantmentEffects]; public float[] EffectScalingPoints = new float[ItemConst.MaxItemEnchantmentEffects];
public uint IconFileDataID; public uint IconFileDataID;
@@ -439,6 +450,7 @@ namespace Game.DataStorage
public int AltPowerBarID; public int AltPowerBarID;
public float PowerCostPct; public float PowerCostPct;
public float PowerCostMaxPct; public float PowerCostMaxPct;
public float OptionalCostPct;
public float PowerPctPerSecond; public float PowerPctPerSecond;
public PowerType PowerType; public PowerType PowerType;
public uint RequiredAuraSpellID; public uint RequiredAuraSpellID;
@@ -495,6 +507,8 @@ namespace Game.DataStorage
public uint SpellID; public uint SpellID;
public int[] Reagent = new int[SpellConst.MaxReagents]; public int[] Reagent = new int[SpellConst.MaxReagents];
public ushort[] ReagentCount = new ushort[SpellConst.MaxReagents]; public ushort[] ReagentCount = new ushort[SpellConst.MaxReagents];
public short[] ReagentRecraftCount = new short[SpellConst.MaxReagents];
public byte[] ReagentSource = new byte[SpellConst.MaxReagents];
} }
public sealed class SpellReagentsCurrencyRecord public sealed class SpellReagentsCurrencyRecord
@@ -638,6 +652,7 @@ namespace Game.DataStorage
public byte DifficultyID; public byte DifficultyID;
public uint SpellVisualID; public uint SpellVisualID;
public float Probability; public float Probability;
public int Flags;
public int Priority; public int Priority;
public int SpellIconFileID; public int SpellIconFileID;
public int ActiveIconFileID; public int ActiveIconFileID;
@@ -61,6 +61,7 @@ namespace Game.DataStorage
public int ParentUiMapID; public int ParentUiMapID;
public int OrderIndex; public int OrderIndex;
public int ChildUiMapID; public int ChildUiMapID;
public int PlayerConditionID;
public int OverrideHighlightFileDataID; public int OverrideHighlightFileDataID;
public int OverrideHighlightAtlasID; public int OverrideHighlightAtlasID;
public int Flags; public int Flags;
+4 -3
View File
@@ -106,7 +106,7 @@ namespace Game.Entities
DeleteFromDB(trans); DeleteFromDB(trans);
StringBuilder items = new(); StringBuilder items = new();
for (var i = 0; i < EquipmentSlot.End; ++i) for (var i = 0; i < m_corpseData.Items.GetSize(); ++i)
items.Append($"{m_corpseData.Items[i]} "); items.Append($"{m_corpseData.Items[i]} ");
byte index = 0; byte index = 0;
@@ -187,8 +187,9 @@ namespace Game.Entities
SetObjectScale(1.0f); SetObjectScale(1.0f);
SetDisplayId(field.Read<uint>(5)); SetDisplayId(field.Read<uint>(5));
StringArray items = new(field.Read<string>(6), ' '); StringArray items = new(field.Read<string>(6), ' ');
for (uint index = 0; index < EquipmentSlot.End; ++index) if (items.Length == m_corpseData.Items.GetSize())
SetItem(index, uint.Parse(items[(int)index])); for (uint index = 0; index < m_corpseData.Items.GetSize(); ++index)
SetItem(index, uint.Parse(items[(int)index]));
SetRace(field.Read<byte>(7)); SetRace(field.Read<byte>(7));
SetClass(field.Read<byte>(8)); SetClass(field.Read<byte>(8));
+154 -91
View File
@@ -30,47 +30,58 @@ namespace Game.Misc
{ {
public class GossipMenu public class GossipMenu
{ {
public uint AddMenuItem(int menuItemId, GossipOptionNpc optionNpc, string message, uint sender, uint action, string boxMessage, uint boxMoney, bool coded = false) public uint AddMenuItem(int gossipOptionId, int orderIndex, GossipOptionNpc optionNpc, string optionText, uint language,
GossipOptionFlags flags, int? gossipNpcOptionId, bool boxCoded, uint boxMoney, string boxText, int? spellId,
int? overrideIconId, uint sender, uint action)
{ {
Cypher.Assert(_menuItems.Count <= SharedConst.MaxGossipMenuItems); Cypher.Assert(_menuItems.Count <= SharedConst.MaxGossipMenuItems);
// Find a free new id - script case // Find a free new id - script case
if (menuItemId == -1) if (orderIndex == -1)
{ {
menuItemId = 0; orderIndex = 0;
if (_menuId != 0) if (_menuId != 0)
{ {
// set baseline menuItemId as higher than whatever exists in db // set baseline orderIndex as higher than whatever exists in db
var bounds = Global.ObjectMgr.GetGossipMenuItemsMapBounds(_menuId); var bounds = Global.ObjectMgr.GetGossipMenuItemsMapBounds(_menuId);
var itr = bounds.MaxBy(a => a.OptionId); var itr = bounds.MaxBy(a => a.OrderIndex);
if (itr != null) if (itr != null)
menuItemId = (int)(itr.OptionId + 1); orderIndex = (int)(itr.OrderIndex + 1);
} }
if (!_menuItems.Empty()) if (!_menuItems.Empty())
{ {
foreach (var item in _menuItems) foreach (var pair in _menuItems)
{ {
if (item.Key > menuItemId) if (pair.Value.OrderIndex > orderIndex)
break; break;
menuItemId = (int)item.Key + 1; orderIndex = (int)pair.Value.OrderIndex + 1;
} }
} }
} }
GossipMenuItem menuItem = new(); if (gossipOptionId == 0)
gossipOptionId = -((int)_menuId * 100 + orderIndex);
GossipMenuItem menuItem = new();
menuItem.GossipOptionID = gossipOptionId;
menuItem.OrderIndex = (uint)orderIndex;
menuItem.OptionNpc = optionNpc; menuItem.OptionNpc = optionNpc;
menuItem.Message = message; menuItem.OptionText = optionText;
menuItem.IsCoded = coded; menuItem.Language = language;
menuItem.Flags = flags;
menuItem.GossipNpcOptionID = gossipNpcOptionId;
menuItem.BoxCoded = boxCoded;
menuItem.BoxMoney = boxMoney;
menuItem.BoxText = boxText;
menuItem.SpellID = spellId;
menuItem.OverrideIconID = overrideIconId;
menuItem.Sender = sender; menuItem.Sender = sender;
menuItem.Action = action; menuItem.Action = action;
menuItem.BoxMessage = boxMessage;
menuItem.BoxMoney = boxMoney;
_menuItems[(uint)menuItemId] = menuItem; _menuItems.Add((uint)orderIndex, menuItem);
return (uint)menuItemId; return (uint)orderIndex;
} }
/// <summary> /// <summary>
@@ -89,79 +100,104 @@ namespace Game.Misc
return; return;
/// Find the one with the given menu item id. /// Find the one with the given menu item id.
var gossipMenuItems = bounds.Find(menuItem => menuItem.OptionId == menuItemId); var gossipMenuItems = bounds.Find(menuItem => menuItem.OrderIndex == menuItemId);
if (gossipMenuItems == null) if (gossipMenuItems == null)
return; return;
AddMenuItem(gossipMenuItems, sender, action);
}
public void AddMenuItem(GossipMenuItems menuItem, uint sender, uint action)
{
// Store texts for localization. // Store texts for localization.
string strOptionText, strBoxText; string strOptionText, strBoxText;
BroadcastTextRecord optionBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItems.OptionBroadcastTextId); BroadcastTextRecord optionBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(menuItem.OptionBroadcastTextId);
BroadcastTextRecord boxBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItems.BoxBroadcastTextId); BroadcastTextRecord boxBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(menuItem.BoxBroadcastTextId);
// OptionText // OptionText
if (optionBroadcastText != null) if (optionBroadcastText != null)
strOptionText = Global.DB2Mgr.GetBroadcastTextValue(optionBroadcastText, GetLocale()); strOptionText = Global.DB2Mgr.GetBroadcastTextValue(optionBroadcastText, GetLocale());
else else
strOptionText = gossipMenuItems.OptionText; {
strOptionText = menuItem.OptionText;
/// Find localizations from database.
if (GetLocale() != Locale.enUS)
{
GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuItem.MenuID, menuItem.OrderIndex);
if (gossipMenuLocale != null)
ObjectManager.GetLocaleString(gossipMenuLocale.OptionText, GetLocale(), ref strOptionText);
}
}
// BoxText // BoxText
if (boxBroadcastText != null) if (boxBroadcastText != null)
strBoxText = Global.DB2Mgr.GetBroadcastTextValue(boxBroadcastText, GetLocale()); strBoxText = Global.DB2Mgr.GetBroadcastTextValue(boxBroadcastText, GetLocale());
else else
strBoxText = gossipMenuItems.BoxText;
// Check need of localization.
if (boxBroadcastText == null)
{ {
strBoxText = menuItem.BoxText;
// Find localizations from database. // Find localizations from database.
GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuId, menuItemId); if (GetLocale() != Locale.enUS)
if (gossipMenuLocale != null) {
ObjectManager.GetLocaleString(gossipMenuLocale.BoxText, GetLocale(), ref strBoxText); GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuItem.MenuID, menuItem.OrderIndex);
if (gossipMenuLocale != null)
ObjectManager.GetLocaleString(gossipMenuLocale.BoxText, GetLocale(), ref strBoxText);
}
} }
// Add menu item with existing method. Menu item id -1 is also used in ADD_GOSSIP_ITEM macro. AddMenuItem(menuItem.GossipOptionID, (int)menuItem.OrderIndex, menuItem.OptionNpc, strOptionText, menuItem.Language, menuItem.Flags,
AddMenuItem((int)gossipMenuItems.OptionId, gossipMenuItems.OptionNpc, strOptionText, sender, action, strBoxText, gossipMenuItems.BoxMoney, gossipMenuItems.BoxCoded); menuItem.GossipNpcOptionID, menuItem.BoxCoded, menuItem.BoxMoney, strBoxText, menuItem.SpellID, (int)menuItem.OverrideIconID, sender, action);
AddGossipMenuItemData(gossipMenuItems.OptionId, gossipMenuItems.ActionMenuId, gossipMenuItems.ActionPoiId); AddGossipMenuItemData(menuItem.OrderIndex, menuItem.ActionMenuID, menuItem.ActionPoiID);
} }
public void AddGossipMenuItemData(uint menuItemId, uint gossipActionMenuId, uint gossipActionPoi) public void AddGossipMenuItemData(uint menuItemId, uint gossipActionMenuId, uint gossipActionPoi)
{ {
GossipMenuItemData itemData = new(); GossipMenuItem menuItem = _menuItems[menuItemId];
menuItem.ActionMenuID = gossipActionMenuId;
itemData.GossipActionMenuId = gossipActionMenuId; menuItem.ActionPoiID = gossipActionPoi;
itemData.GossipActionPoi = gossipActionPoi;
_menuItemData[menuItemId] = itemData;
} }
public uint GetMenuItemSender(uint menuItemId) public GossipMenuItem GetItem(int gossipOptionId)
{ {
if (_menuItems.ContainsKey(menuItemId)) return _menuItems.Values.FirstOrDefault(item => item.GossipOptionID == gossipOptionId);
return _menuItems.LookupByKey(menuItemId).Sender;
else
return 0;
} }
public uint GetMenuItemAction(uint menuItemId) GossipMenuItem GetItemByIndex(uint orderIndex)
{ {
if (_menuItems.ContainsKey(menuItemId)) return _menuItems.LookupByKey(orderIndex);
return _menuItems.LookupByKey(menuItemId).Action;
else
return 0;
} }
public bool IsMenuItemCoded(uint menuItemId) public uint GetMenuItemSender(uint orderIndex)
{ {
if (_menuItems.ContainsKey(menuItemId)) GossipMenuItem item = GetItemByIndex(orderIndex);
return _menuItems.LookupByKey(menuItemId).IsCoded; if (item != null)
else return item.Sender;
return false;
return 0;
}
public uint GetMenuItemAction(uint orderIndex)
{
GossipMenuItem item = GetItemByIndex(orderIndex);
if (item != null)
return item.Action;
return 0;
}
public bool IsMenuItemCoded(uint orderIndex)
{
GossipMenuItem item = GetItemByIndex(orderIndex);
if (item != null)
return item.BoxCoded;
return false;
} }
public void ClearMenu() public void ClearMenu()
{ {
_menuItems.Clear(); _menuItems.Clear();
_menuItemData.Clear();
} }
public void SetMenuId(uint menu_id) { _menuId = menu_id; } public void SetMenuId(uint menu_id) { _menuId = menu_id; }
@@ -179,23 +215,12 @@ namespace Game.Misc
return _menuItems.Empty(); return _menuItems.Empty();
} }
public GossipMenuItem GetItem(uint id) public SortedDictionary<uint, GossipMenuItem> GetMenuItems()
{
return _menuItems.LookupByKey(id);
}
public GossipMenuItemData GetItemData(uint indexId)
{
return _menuItemData.LookupByKey(indexId);
}
public Dictionary<uint, GossipMenuItem> GetMenuItems()
{ {
return _menuItems; return _menuItems;
} }
Dictionary<uint, GossipMenuItem> _menuItems = new(); SortedDictionary<uint, GossipMenuItem> _menuItems = new();
Dictionary<uint, GossipMenuItemData> _menuItemData = new();
uint _menuId; uint _menuId;
Locale _locale; Locale _locale;
} }
@@ -245,18 +270,21 @@ namespace Game.Misc
if (text != null) if (text != null)
packet.TextID = (int)text.Data.SelectRandomElementByWeight(data => data.Probability).BroadcastTextID; packet.TextID = (int)text.Data.SelectRandomElementByWeight(data => data.Probability).BroadcastTextID;
foreach (var pair in _gossipMenu.GetMenuItems()) foreach (var (index, item) in _gossipMenu.GetMenuItems())
{ {
ClientGossipOptions opt = new(); ClientGossipOptions opt = new();
GossipMenuItem item = pair.Value; opt.GossipOptionID = item.GossipOptionID;
opt.ClientOption = (int)pair.Key;
opt.OptionNPC = item.OptionNpc; opt.OptionNPC = item.OptionNpc;
opt.OptionFlags = (byte)(item.IsCoded ? 1 : 0); // makes pop up box password opt.OptionFlags = (byte)(item.BoxCoded ? 1 : 0); // makes pop up box password
opt.OptionCost = (int)item.BoxMoney; // money required to open menu, 2.0.3 opt.OptionCost = (int)item.BoxMoney; // money required to open menu, 2.0.3
opt.OptionLanguage = item.Language; opt.OptionLanguage = item.Language;
opt.Text = item.Message; // text for gossip item opt.Flags = item.Flags;
opt.Confirm = item.BoxMessage; // accept text (related to money) pop up box, 2.0.3 opt.OrderIndex = (int)item.OrderIndex;
opt.Text = item.OptionText; // text for gossip item
opt.Confirm = item.BoxText; // accept text (related to money) pop up box, 2.0.3
opt.Status = GossipOptionStatus.Available; opt.Status = GossipOptionStatus.Available;
opt.SpellID = item.SpellID;
opt.OverrideIconID = item.OverrideIconID;
packet.GossipOptions.Add(opt); packet.GossipOptions.Add(opt);
} }
@@ -404,6 +432,14 @@ namespace Game.Misc
packet.PortraitTurnInName = quest.PortraitTurnInName; packet.PortraitTurnInName = quest.PortraitTurnInName;
Locale locale = _session.GetSessionDbLocaleIndex(); Locale locale = _session.GetSessionDbLocaleIndex();
packet.ConditionalDescriptionText = quest.ConditionalQuestDescription.Select(text =>
{
string content = text.Text[(int)Locale.enUS];
ObjectManager.GetLocaleString(text.Text, locale, ref content);
return new ConditionalQuestText(text.PlayerConditionId, text.QuestgiverCreatureId, content);
}).ToList();
if (locale != Locale.enUS) if (locale != Locale.enUS)
{ {
QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id); QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id);
@@ -432,6 +468,7 @@ namespace Game.Misc
packet.DisplayPopup = displayPopup; packet.DisplayPopup = displayPopup;
packet.QuestFlags[0] = (uint)(quest.Flags & (WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoAccept) ? ~QuestFlags.AutoAccept : ~QuestFlags.None)); packet.QuestFlags[0] = (uint)(quest.Flags & (WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoAccept) ? ~QuestFlags.AutoAccept : ~QuestFlags.None));
packet.QuestFlags[1] = (uint)quest.FlagsEx; packet.QuestFlags[1] = (uint)quest.FlagsEx;
packet.QuestFlags[2] = (uint)quest.FlagsEx2;
packet.SuggestedPartyMembers = quest.SuggestedPlayers; packet.SuggestedPartyMembers = quest.SuggestedPlayers;
// RewardSpell can teach multiple spells in trigger spell effects. But not all effects must be SPELL_EFFECT_LEARN_SPELL. See example spell 33950 // RewardSpell can teach multiple spells in trigger spell effects. But not all effects must be SPELL_EFFECT_LEARN_SPELL. See example spell 33950
@@ -488,6 +525,14 @@ namespace Game.Misc
packet.PortraitTurnInName = quest.PortraitTurnInName; packet.PortraitTurnInName = quest.PortraitTurnInName;
Locale locale = _session.GetSessionDbLocaleIndex(); Locale locale = _session.GetSessionDbLocaleIndex();
packet.ConditionalRewardText = quest.ConditionalOfferRewardText.Select(text =>
{
string content = text.Text[(int)Locale.enUS];
ObjectManager.GetLocaleString(text.Text, locale, ref content);
return new ConditionalQuestText(text.PlayerConditionId, text.QuestgiverCreatureId, content);
}).ToList();
if (locale != Locale.enUS) if (locale != Locale.enUS)
{ {
QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id); QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id);
@@ -513,7 +558,10 @@ namespace Game.Misc
// Is there a better way? what about game objects? // Is there a better way? what about game objects?
Creature creature = ObjectAccessor.GetCreature(_session.GetPlayer(), npcGUID); Creature creature = ObjectAccessor.GetCreature(_session.GetPlayer(), npcGUID);
if (creature) if (creature)
{
packet.QuestGiverCreatureID = creature.GetEntry();
offer.QuestGiverCreatureID = creature.GetCreatureTemplate().Entry; offer.QuestGiverCreatureID = creature.GetCreatureTemplate().Entry;
}
offer.QuestID = quest.Id; offer.QuestID = quest.Id;
offer.AutoLaunched = autoLaunched; offer.AutoLaunched = autoLaunched;
@@ -524,6 +572,7 @@ namespace Game.Misc
offer.QuestFlags[0] = (uint)quest.Flags; offer.QuestFlags[0] = (uint)quest.Flags;
offer.QuestFlags[1] = (uint)quest.FlagsEx; offer.QuestFlags[1] = (uint)quest.FlagsEx;
offer.QuestFlags[2] = (uint)quest.FlagsEx2;
packet.PortraitTurnIn = quest.QuestTurnInPortrait; packet.PortraitTurnIn = quest.QuestTurnInPortrait;
packet.PortraitGiver = quest.QuestGiverPortrait; packet.PortraitGiver = quest.QuestGiverPortrait;
@@ -553,6 +602,13 @@ namespace Game.Misc
packet.CompletionText = quest.RequestItemsText; packet.CompletionText = quest.RequestItemsText;
Locale locale = _session.GetSessionDbLocaleIndex(); Locale locale = _session.GetSessionDbLocaleIndex();
packet.ConditionalCompletionText = quest.ConditionalRequestItemsText.Select(text =>
{
string content = text.Text[(int)Locale.enUS];
ObjectManager.GetLocaleString(text.Text, locale, ref content);
return new ConditionalQuestText(text.PlayerConditionId, text.QuestgiverCreatureId, content);
}).ToList();
if (locale != Locale.enUS) if (locale != Locale.enUS)
{ {
QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id); QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id);
@@ -586,6 +642,7 @@ namespace Game.Misc
packet.QuestFlags[0] = (uint)quest.Flags; packet.QuestFlags[0] = (uint)quest.Flags;
packet.QuestFlags[1] = (uint)quest.FlagsEx; packet.QuestFlags[1] = (uint)quest.FlagsEx;
packet.QuestFlags[2] = (uint)quest.FlagsEx2;
packet.SuggestPartyMembers = quest.SuggestedPlayers; packet.SuggestPartyMembers = quest.SuggestedPlayers;
// incomplete: FD // incomplete: FD
@@ -687,20 +744,26 @@ namespace Game.Misc
public class GossipMenuItem public class GossipMenuItem
{ {
public int GossipOptionID;
public uint OrderIndex;
public GossipOptionNpc OptionNpc; public GossipOptionNpc OptionNpc;
public bool IsCoded; public string OptionText;
public string Message; public uint Language;
public GossipOptionFlags Flags;
public int? GossipNpcOptionID;
public bool BoxCoded;
public uint BoxMoney;
public string BoxText;
public int? SpellID;
public int? OverrideIconID;
// action data
public uint ActionMenuID;
public uint ActionPoiID;
// additional scripting identifiers
public uint Sender; public uint Sender;
public uint Action; public uint Action;
public string BoxMessage;
public uint BoxMoney;
public uint Language;
}
public class GossipMenuItemData
{
public uint GossipActionMenuId; // MenuId of the gossip triggered by this action
public uint GossipActionPoi;
} }
public struct NpcTextData public struct NpcTextData
@@ -721,18 +784,23 @@ namespace Game.Misc
public class GossipMenuItems public class GossipMenuItems
{ {
public uint MenuId; public uint MenuID;
public uint OptionId; public int GossipOptionID;
public uint OrderIndex;
public GossipOptionNpc OptionNpc; public GossipOptionNpc OptionNpc;
public string OptionText; public string OptionText;
public uint OptionBroadcastTextId; public uint OptionBroadcastTextId;
public uint Language; public uint Language;
public uint ActionMenuId; public GossipOptionFlags Flags;
public uint ActionPoiId; public uint ActionMenuID;
public uint ActionPoiID;
public int? GossipNpcOptionID;
public bool BoxCoded; public bool BoxCoded;
public uint BoxMoney; public uint BoxMoney;
public string BoxText; public string BoxText;
public uint BoxBroadcastTextId; public uint BoxBroadcastTextId;
public int? SpellID;
public int? OverrideIconID;
public List<Condition> Conditions = new(); public List<Condition> Conditions = new();
} }
@@ -741,11 +809,6 @@ namespace Game.Misc
public int FriendshipFactionID; public int FriendshipFactionID;
} }
public class GossipMenuItemAddon
{
public int? GarrTalentTreeID;
}
public class PointOfInterest public class PointOfInterest
{ {
public uint Id; public uint Id;
+21 -4
View File
@@ -2422,8 +2422,9 @@ namespace Game.Entities
if (!item) if (!item)
return; return;
OpenHeartForge openHeartForge = new(); GameObjectInteraction openHeartForge = new();
openHeartForge.ForgeGUID = GetGUID(); openHeartForge.ObjectGUID = GetGUID();
openHeartForge.InteractionType = PlayerInteractionType.AzeriteForge;
player.SendPacket(openHeartForge); player.SendPacket(openHeartForge);
break; break;
} }
@@ -2438,9 +2439,25 @@ namespace Game.Entities
if (!player) if (!player)
return; return;
GameObjectUILink gameObjectUILink = new(); GameObjectInteraction gameObjectUILink = new();
gameObjectUILink.ObjectGUID = GetGUID(); gameObjectUILink.ObjectGUID = GetGUID();
gameObjectUILink.UILink = (int)GetGoInfo().UILink.UILinkType; switch (GetGoInfo().UILink.UILinkType)
{
case 0:
gameObjectUILink.InteractionType = PlayerInteractionType.AdventureJournal;
break;
case 1:
gameObjectUILink.InteractionType = PlayerInteractionType.ObliterumForge;
break;
case 2:
gameObjectUILink.InteractionType = PlayerInteractionType.ScrappingMachine;
break;
case 3:
gameObjectUILink.InteractionType = PlayerInteractionType.ItemInteraction;
break;
default:
break;
}
player.SendPacket(gameObjectUILink); player.SendPacket(gameObjectUILink);
return; return;
} }
@@ -231,6 +231,9 @@ namespace Game.Entities
[FieldOffset(68)] [FieldOffset(68)]
public clientmodel ClientModel; public clientmodel ClientModel;
[FieldOffset(68)]
public craftingTable CraftingTable;
[FieldOffset(68)] [FieldOffset(68)]
public raw Raw; public raw Raw;
@@ -768,6 +771,7 @@ namespace Game.Entities
public uint InfiniteAOI; // 10 Infinite AOI, enum { false, true, }; Default: false public uint InfiniteAOI; // 10 Infinite AOI, enum { false, true, }; Default: false
public uint NotLOSBlocking; // 11 Not LOS Blocking, enum { false, true, }; Default: false public uint NotLOSBlocking; // 11 Not LOS Blocking, enum { false, true, }; Default: false
public uint InteractRadiusOverride; // 12 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0 public uint InteractRadiusOverride; // 12 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0
public uint Collisionupdatedelayafteropen; // 13 Collision update delay(ms) after open, int, Min value: 0, Max value: 2147483647, Default value: 0
} }
public struct button public struct button
@@ -909,6 +913,13 @@ namespace Game.Entities
public uint floatOnWater; // 7 floatOnWater, enum { false, true, }; Default: false public uint floatOnWater; // 7 floatOnWater, enum { false, true, }; Default: false
public uint conditionID1; // 8 conditionID1, References: PlayerCondition, NoValue = 0 public uint conditionID1; // 8 conditionID1, References: PlayerCondition, NoValue = 0
public uint InteractRadiusOverride; // 9 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0 public uint InteractRadiusOverride; // 9 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0
public uint gossipID; // 10 gossipID, References: Gossip, NoValue = 0
public uint spellFocusType2; // 11 spellFocusType 2, References: SpellFocusObject, NoValue = 0
public uint spellFocusType3; // 12 spellFocusType 3, References: SpellFocusObject, NoValue = 0
public uint spellFocusType4; // 13 spellFocusType 4, References: SpellFocusObject, NoValue = 0
public uint Profession; // 14 Profession, enum { First Aid, Blacksmithing, Leatherworking, Alchemy, Herbalism, Cooking, Mining, Tailoring, Engineering, Enchanting, Fishing, Skinning, Jewelcrafting, Inscription, Archaeology, }; Default: Blacksmithing
public uint Profession2; // 15 Profession 2, enum { First Aid, Blacksmithing, Leatherworking, Alchemy, Herbalism, Cooking, Mining, Tailoring, Engineering, Enchanting, Fishing, Skinning, Jewelcrafting, Inscription, Archaeology, }; Default: Blacksmithing
public uint Profession3; // 16 Profession 3, enum { First Aid, Blacksmithing, Leatherworking, Alchemy, Herbalism, Cooking, Mining, Tailoring, Engineering, Enchanting, Fishing, Skinning, Jewelcrafting, Inscription, Archaeology, }; Default: Blacksmithing
} }
public struct text public struct text
@@ -1179,7 +1190,7 @@ namespace Game.Entities
public struct dungeonDifficulty public struct dungeonDifficulty
{ {
public uint InstanceType; // 0 Instance Type, enum { Not Instanced, Party Dungeon, Raid Dungeon, PVP Battlefield, Arena Battlefield, Scenario, }; Default: Party Dungeon public uint InstanceType; // 0 Instance Type, enum { Not Instanced, Party Dungeon, Raid Dungeon, PVP Battlefield, Arena Battlefield, Scenario, WoWLabs }; Default: Party Dungeon
public uint DifficultyNormal; // 1 Difficulty Normal, References: animationdata, NoValue = 0 public uint DifficultyNormal; // 1 Difficulty Normal, References: animationdata, NoValue = 0
public uint DifficultyHeroic; // 2 Difficulty Heroic, References: animationdata, NoValue = 0 public uint DifficultyHeroic; // 2 Difficulty Heroic, References: animationdata, NoValue = 0
public uint DifficultyEpic; // 3 Difficulty Epic, References: animationdata, NoValue = 0 public uint DifficultyEpic; // 3 Difficulty Epic, References: animationdata, NoValue = 0
@@ -1199,6 +1210,7 @@ namespace Game.Entities
public int HeightOffset; // 1 Height Offset (inches), int, Min value: -100, Max value: 100, Default value: 0 public int HeightOffset; // 1 Height Offset (inches), int, Min value: -100, Max value: 100, Default value: 0
public uint SitAnimKit; // 2 Sit Anim Kit, References: AnimKit, NoValue = 0 public uint SitAnimKit; // 2 Sit Anim Kit, References: AnimKit, NoValue = 0
public uint InteractRadiusOverride; // 3 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0 public uint InteractRadiusOverride; // 3 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0
public uint CustomizationScope; // 4 Customization Scope, int, Min value: 0, Max value: 2147483647, Default value: 0
} }
public struct destructiblebuilding public struct destructiblebuilding
@@ -1490,6 +1502,7 @@ namespace Game.Entities
public uint WhenAvailable; // 0 When Available, References: GameObjectDisplayInfo, NoValue = 0 public uint WhenAvailable; // 0 When Available, References: GameObjectDisplayInfo, NoValue = 0
public uint open; // 1 open, References: Lock_, NoValue = 0 public uint open; // 1 open, References: Lock_, NoValue = 0
public uint InteractRadiusOverride; // 2 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0 public uint InteractRadiusOverride; // 2 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0
public uint ExpansionLevel; // 3 Expansion Level, int, Min value: 0, Max value: 2147483647, Default value: 0
} }
public struct clientmodel public struct clientmodel
@@ -1499,6 +1512,11 @@ namespace Game.Entities
public uint InfiniteAOI; // 2 Infinite AOI, enum { false, true, }; Default: false public uint InfiniteAOI; // 2 Infinite AOI, enum { false, true, }; Default: false
public uint TrueInfiniteAOI; // 3 True Infinite AOI (programmer only!), enum { false, true, }; Default: false public uint TrueInfiniteAOI; // 3 True Infinite AOI (programmer only!), enum { false, true, }; Default: false
} }
public struct craftingTable
{
public uint Profession; // 0 Profession, enum { First Aid, Blacksmithing, Leatherworking, Alchemy, Herbalism, Cooking, Mining, Tailoring, Engineering, Enchanting, Fishing, Skinning, Jewelcrafting, Inscription, Archaeology, }; Default: Blacksmithing
}
#endregion #endregion
} }
@@ -147,7 +147,7 @@ namespace Game.Entities
SetUpdateFieldValue(ref m_values.ModifyValue(m_azeriteEmpoweredItemData).ModifyValue(m_azeriteEmpoweredItemData.Selections, i), 0); SetUpdateFieldValue(ref m_values.ModifyValue(m_azeriteEmpoweredItemData).ModifyValue(m_azeriteEmpoweredItemData.Selections, i), 0);
_bonusData = new BonusData(GetTemplate()); _bonusData = new BonusData(GetTemplate());
foreach (uint bonusListID in (List<uint>)m_itemData.BonusListIDs) foreach (uint bonusListID in GetBonusListIDs())
_bonusData.AddBonusList(bonusListID); _bonusData.AddBonusList(bonusListID);
} }
+32 -10
View File
@@ -187,7 +187,7 @@ namespace Game.Entities
ss.Clear(); ss.Clear();
foreach (int bonusListID in (List<uint>)m_itemData.BonusListIDs) foreach (int bonusListID in GetBonusListIDs())
ss.Append($"{bonusListID} "); ss.Append($"{bonusListID} ");
stmt.AddValue(++index, ss.ToString()); stmt.AddValue(++index, ss.ToString());
@@ -802,9 +802,13 @@ namespace Game.Entities
return m_container != null ? m_container.GetSlot() : InventorySlots.Bag0; return m_container != null ? m_container.GetSlot() : InventorySlots.Bag0;
} }
public bool IsEquipped() { return !IsInBag() && m_slot < EquipmentSlot.End; } public bool IsEquipped()
{
return !IsInBag() && ((m_slot >= EquipmentSlot.Start && m_slot < EquipmentSlot.End)
|| (m_slot >= ProfessionSlots.Start && m_slot < ProfessionSlots.End));
}
public bool CanBeTraded(bool mail = false, bool trade = false) public bool CanBeTraded(bool mail = false, bool trade = false)
{ {
if (m_lootGenerated) if (m_lootGenerated)
return false; return false;
@@ -1603,7 +1607,13 @@ namespace Game.Entities
-1, // INVTYPE_THROWN -1, // INVTYPE_THROWN
EquipmentSlot.MainHand, // INVTYPE_RANGEDRIGHT EquipmentSlot.MainHand, // INVTYPE_RANGEDRIGHT
-1, // INVTYPE_QUIVER -1, // INVTYPE_QUIVER
-1 // INVTYPE_RELIC -1, // INVTYPE_RELIC
-1, // INVTYPE_PROFESSION_TOOL
-1, // INVTYPE_PROFESSION_GEAR
-1, // INVTYPE_EQUIPABLE_SPELL_OFFENSIVE
-1, // INVTYPE_EQUIPABLE_SPELL_UTILITY
-1, // INVTYPE_EQUIPABLE_SPELL_DEFENSIVE
-1 // INVTYPE_EQUIPABLE_SPELL_MOBILITY
}; };
public static bool CanTransmogrifyItemWithItem(Item item, ItemModifiedAppearanceRecord itemModifiedAppearance) public static bool CanTransmogrifyItemWithItem(Item item, ItemModifiedAppearanceRecord itemModifiedAppearance)
@@ -2075,17 +2085,22 @@ namespace Game.Entities
return 0; return 0;
} }
public List<uint> GetBonusListIDs() { return m_itemData.ItemBonusKey.GetValue().BonusListIDs; }
public void AddBonuses(uint bonusListID) public void AddBonuses(uint bonusListID)
{ {
var bonusListIDs = (List<uint>)m_itemData.BonusListIDs; var bonusListIDs = GetBonusListIDs();
if (bonusListIDs.Contains(bonusListID)) if (bonusListIDs.Contains(bonusListID))
return; return;
var bonuses = Global.DB2Mgr.GetItemBonusList(bonusListID); var bonuses = Global.DB2Mgr.GetItemBonusList(bonusListID);
if (bonuses != null) if (bonuses != null)
{ {
bonusListIDs.Add(bonusListID); ItemBonusKey itemBonusKey = new();
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.BonusListIDs), bonusListIDs); itemBonusKey.ItemID = GetEntry();
itemBonusKey.BonusListIDs = GetBonusListIDs();
itemBonusKey.BonusListIDs.Add(bonusListID);
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemBonusKey), itemBonusKey);
foreach (ItemBonusRecord bonus in bonuses) foreach (ItemBonusRecord bonus in bonuses)
_bonusData.AddBonus(bonus.BonusType, bonus.Value); _bonusData.AddBonus(bonus.BonusType, bonus.Value);
@@ -2098,9 +2113,12 @@ namespace Game.Entities
if (bonusListIDs == null) if (bonusListIDs == null)
bonusListIDs = new List<uint>(); bonusListIDs = new List<uint>();
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.BonusListIDs), bonusListIDs); ItemBonusKey itemBonusKey = new();
itemBonusKey.ItemID = GetEntry();
itemBonusKey.BonusListIDs = bonusListIDs;
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemBonusKey), itemBonusKey);
foreach (uint bonusListID in (List<uint>)m_itemData.BonusListIDs) foreach (uint bonusListID in GetBonusListIDs())
_bonusData.AddBonusList(bonusListID); _bonusData.AddBonusList(bonusListID);
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)_bonusData.AppearanceModID); SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)_bonusData.AppearanceModID);
@@ -2108,7 +2126,9 @@ namespace Game.Entities
public void ClearBonuses() public void ClearBonuses()
{ {
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.BonusListIDs), new List<uint>()); ItemBonusKey itemBonusKey = new();
itemBonusKey.ItemID = GetEntry();
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemBonusKey), itemBonusKey);
_bonusData = new BonusData(GetTemplate()); _bonusData = new BonusData(GetTemplate());
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)_bonusData.AppearanceModID); SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)_bonusData.AppearanceModID);
} }
@@ -2721,6 +2741,8 @@ namespace Game.Entities
if (!pProto.GetBagFamily().HasAnyFlag(BagFamilyMask.CookingSupp)) if (!pProto.GetBagFamily().HasAnyFlag(BagFamilyMask.CookingSupp))
return false; return false;
return true; return true;
case ItemSubClassContainer.ReagentContainer:
return pProto.IsCraftingReagent();
default: default:
return false; return false;
} }
@@ -67,6 +67,29 @@ namespace Game.Entities
T GetValue(); T GetValue();
} }
public class UpdateFieldString : IUpdateField<string>
{
public string _value;
public int BlockBit;
public int Bit;
public UpdateFieldString(int blockBit, int bit)
{
BlockBit = blockBit;
Bit = bit;
_value = "";
}
public static implicit operator string(UpdateFieldString updateField)
{
return updateField._value;
}
public void SetValue(string value) { _value = value; }
public string GetValue() { return _value; }
}
public class UpdateField<T> : IUpdateField<T> where T : new() public class UpdateField<T> : IUpdateField<T> where T : new()
{ {
public T _value; public T _value;
@@ -380,6 +403,8 @@ namespace Game.Entities
((IHasChangesMask)updateField._value).ClearChangesMask(); ((IHasChangesMask)updateField._value).ClearChangesMask();
} }
public void ClearChangesMask(UpdateFieldString updateField) { }
public void ClearChangesMask<U>(OptionalUpdateField<U> updateField) where U : new() public void ClearChangesMask<U>(OptionalUpdateField<U> updateField) where U : new()
{ {
if (typeof(IHasChangesMask).IsAssignableFrom(typeof(U)) && updateField.HasValue()) if (typeof(IHasChangesMask).IsAssignableFrom(typeof(U)) && updateField.HasValue())
File diff suppressed because it is too large Load Diff
+49 -2
View File
@@ -278,6 +278,7 @@ namespace Game.Entities
bool HasFall = HasFallDirection || unit.m_movementInfo.jump.fallTime != 0; bool HasFall = HasFallDirection || unit.m_movementInfo.jump.fallTime != 0;
bool HasSpline = unit.IsSplineEnabled(); bool HasSpline = unit.IsSplineEnabled();
bool HasInertia = unit.m_movementInfo.inertia.HasValue; bool HasInertia = unit.m_movementInfo.inertia.HasValue;
bool HasAdvFlying = unit.m_movementInfo.advFlying.HasValue;
data.WritePackedGuid(GetGUID()); // MoverGUID data.WritePackedGuid(GetGUID()); // MoverGUID
@@ -312,11 +313,17 @@ namespace Game.Entities
if (HasInertia) if (HasInertia)
{ {
data.WritePackedGuid(unit.m_movementInfo.inertia.Value.guid); data.WriteInt32(unit.m_movementInfo.inertia.Value.id);
data.WriteXYZ(unit.m_movementInfo.inertia.Value.force); data.WriteXYZ(unit.m_movementInfo.inertia.Value.force);
data.WriteUInt32(unit.m_movementInfo.inertia.Value.lifetime); data.WriteUInt32(unit.m_movementInfo.inertia.Value.lifetime);
} }
if (HasAdvFlying)
{
data.WriteFloat(unit.m_movementInfo.advFlying.Value.forwardVelocity);
data.WriteFloat(unit.m_movementInfo.advFlying.Value.upVelocity);
}
if (HasFall) if (HasFall)
{ {
data.WriteUInt32(unit.m_movementInfo.jump.fallTime); // Time data.WriteUInt32(unit.m_movementInfo.jump.fallTime); // Time
@@ -352,6 +359,24 @@ namespace Game.Entities
data.WriteFloat(1.0f); // MovementForcesModMagnitude data.WriteFloat(1.0f); // MovementForcesModMagnitude
} }
data.WriteFloat(2.0f); // advFlyingAirFriction
data.WriteFloat(65.0f); // advFlyingMaxVel
data.WriteFloat(1.0f); // advFlyingLiftCoefficient
data.WriteFloat(3.0f); // advFlyingDoubleJumpVelMod
data.WriteFloat(10.0f); // advFlyingGlideStartMinHeight
data.WriteFloat(100.0f); // advFlyingAddImpulseMaxSpeed
data.WriteFloat(90.0f); // advFlyingMinBankingRate
data.WriteFloat(140.0f); // advFlyingMaxBankingRate
data.WriteFloat(180.0f); // advFlyingMinPitchingRateDown
data.WriteFloat(360.0f); // advFlyingMaxPitchingRateDown
data.WriteFloat(90.0f); // advFlyingMinPitchingRateUp
data.WriteFloat(270.0f); // advFlyingMaxPitchingRateUp
data.WriteFloat(30.0f); // advFlyingMinTurnVelocityThreshold
data.WriteFloat(80.0f); // advFlyingMaxTurnVelocityThreshold
data.WriteFloat(2.75f); // advFlyingSurfaceFriction
data.WriteFloat(7.0f); // advFlyingOverMaxDeceleration
data.WriteFloat(0.4f); // advFlyingLaunchSpeedCoefficient
data.WriteBit(HasSpline); data.WriteBit(HasSpline);
data.FlushBits(); data.FlushBits();
@@ -425,6 +450,7 @@ namespace Game.Entities
bool hasFaceMovementDir = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasFaceMovementDir); bool hasFaceMovementDir = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasFaceMovementDir);
bool hasFollowsTerrain = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasFollowsTerrain); bool hasFollowsTerrain = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasFollowsTerrain);
bool hasUnk1 = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk1); bool hasUnk1 = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk1);
bool hasUnk2 = false;
bool hasTargetRollPitchYaw = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasTargetRollPitchYaw); bool hasTargetRollPitchYaw = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasTargetRollPitchYaw);
bool hasScaleCurveID = createProperties != null && createProperties.ScaleCurveId != 0; bool hasScaleCurveID = createProperties != null && createProperties.ScaleCurveId != 0;
bool hasMorphCurveID = createProperties != null && createProperties.MorphCurveId != 0; bool hasMorphCurveID = createProperties != null && createProperties.MorphCurveId != 0;
@@ -435,6 +461,7 @@ namespace Game.Entities
bool hasAreaTriggerPolygon = createProperties != null && shape.IsPolygon(); bool hasAreaTriggerPolygon = createProperties != null && shape.IsPolygon();
bool hasAreaTriggerCylinder = shape.IsCylinder(); bool hasAreaTriggerCylinder = shape.IsCylinder();
bool hasDisk = shape.IsDisk(); bool hasDisk = shape.IsDisk();
bool hasBoundedPlane = shape.IsBoudedPlane();
bool hasAreaTriggerSpline = areaTrigger.HasSplines(); bool hasAreaTriggerSpline = areaTrigger.HasSplines();
bool hasOrbit = areaTrigger.HasOrbit(); bool hasOrbit = areaTrigger.HasOrbit();
bool hasMovementScript = false; bool hasMovementScript = false;
@@ -445,6 +472,7 @@ namespace Game.Entities
data.WriteBit(hasFaceMovementDir); data.WriteBit(hasFaceMovementDir);
data.WriteBit(hasFollowsTerrain); data.WriteBit(hasFollowsTerrain);
data.WriteBit(hasUnk1); data.WriteBit(hasUnk1);
data.WriteBit(hasUnk2);
data.WriteBit(hasTargetRollPitchYaw); data.WriteBit(hasTargetRollPitchYaw);
data.WriteBit(hasScaleCurveID); data.WriteBit(hasScaleCurveID);
data.WriteBit(hasMorphCurveID); data.WriteBit(hasMorphCurveID);
@@ -455,6 +483,7 @@ namespace Game.Entities
data.WriteBit(hasAreaTriggerPolygon); data.WriteBit(hasAreaTriggerPolygon);
data.WriteBit(hasAreaTriggerCylinder); data.WriteBit(hasAreaTriggerCylinder);
data.WriteBit(hasDisk); data.WriteBit(hasDisk);
data.WriteBit(hasBoundedPlane);
data.WriteBit(hasAreaTriggerSpline); data.WriteBit(hasAreaTriggerSpline);
data.WriteBit(hasOrbit); data.WriteBit(hasOrbit);
data.WriteBit(hasMovementScript); data.WriteBit(hasMovementScript);
@@ -540,6 +569,17 @@ namespace Game.Entities
data.WriteFloat(shape.DiskDatas.LocationZOffsetTarget); data.WriteFloat(shape.DiskDatas.LocationZOffsetTarget);
} }
if (hasBoundedPlane)
{
unsafe
{
data.WriteFloat(shape.BoundedPlaneDatas.Extents[0]);
data.WriteFloat(shape.BoundedPlaneDatas.Extents[1]);
data.WriteFloat(shape.BoundedPlaneDatas.ExtentsTarget[0]);
data.WriteFloat(shape.BoundedPlaneDatas.ExtentsTarget[1]);
}
}
//if (hasMovementScript) //if (hasMovementScript)
// *data << *areaTrigger.GetMovementScript(); // AreaTriggerMovementScriptInfo // *data << *areaTrigger.GetMovementScript(); // AreaTriggerMovementScriptInfo
@@ -3745,6 +3785,7 @@ namespace Game.Entities
public Inertia? inertia; public Inertia? inertia;
public JumpInfo jump; public JumpInfo jump;
public float stepUpStartElevation { get; set; } public float stepUpStartElevation { get; set; }
public AdvFlying? advFlying;
public MovementInfo() public MovementInfo()
{ {
@@ -3810,7 +3851,7 @@ namespace Game.Entities
} }
public struct Inertia public struct Inertia
{ {
public ObjectGuid guid; public int id;
public Position force; public Position force;
public uint lifetime; public uint lifetime;
} }
@@ -3828,6 +3869,12 @@ namespace Game.Entities
public float cosAngle; public float cosAngle;
public float xyspeed; public float xyspeed;
} }
// advflying
public struct AdvFlying
{
public float forwardVelocity;
public float upVelocity;
}
} }
public class MovementForce public class MovementForce
@@ -328,7 +328,7 @@ namespace Game.Entities
return; return;
} }
List<uint> bonusListIDs = item.m_itemData.BonusListIDs; List<uint> bonusListIDs = item.GetBonusListIDs();
foreach (uint bonusId in bonusListIDs) foreach (uint bonusId in bonusListIDs)
{ {
if (bonusId != data.bonusId) if (bonusId != data.bonusId)
+10 -17
View File
@@ -1363,7 +1363,7 @@ namespace Game.Entities
eqSet.Data.AssignedSpecIndex = result.Read<int>(5); eqSet.Data.AssignedSpecIndex = result.Read<int>(5);
eqSet.state = EquipmentSetUpdateState.Unchanged; eqSet.state = EquipmentSetUpdateState.Unchanged;
for (int i = 0; i < EquipmentSlot.End; ++i) for (int i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
{ {
ulong guid = result.Read<uint>(6 + i); ulong guid = result.Read<uint>(6 + i);
if (guid != 0) if (guid != 0)
@@ -1400,7 +1400,7 @@ namespace Game.Entities
eqSet.Data.IgnoreMask = result.Read<uint>(4); eqSet.Data.IgnoreMask = result.Read<uint>(4);
eqSet.state = EquipmentSetUpdateState.Unchanged; eqSet.state = EquipmentSetUpdateState.Unchanged;
for (int i = 0; i < EquipmentSlot.End; ++i) for (int i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
eqSet.Data.Appearances[i] = result.Read<int>(5 + i); eqSet.Data.Appearances[i] = result.Read<int>(5 + i);
for (int i = 0; i < eqSet.Data.Enchants.Length; ++i) for (int i = 0; i < eqSet.Data.Enchants.Length; ++i)
@@ -2298,7 +2298,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.IgnoreMask); stmt.AddValue(j++, eqSet.Data.IgnoreMask);
stmt.AddValue(j++, eqSet.Data.AssignedSpecIndex); stmt.AddValue(j++, eqSet.Data.AssignedSpecIndex);
for (byte i = 0; i < EquipmentSlot.End; ++i) for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Pieces[i].GetCounter()); stmt.AddValue(j++, eqSet.Data.Pieces[i].GetCounter());
stmt.AddValue(j++, GetGUID().GetCounter()); stmt.AddValue(j++, GetGUID().GetCounter());
@@ -2312,7 +2312,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.SetIcon); stmt.AddValue(j++, eqSet.Data.SetIcon);
stmt.AddValue(j++, eqSet.Data.IgnoreMask); stmt.AddValue(j++, eqSet.Data.IgnoreMask);
for (byte i = 0; i < EquipmentSlot.End; ++i) for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Appearances[i]); stmt.AddValue(j++, eqSet.Data.Appearances[i]);
for (int i = 0; i < eqSet.Data.Enchants.Length; ++i) for (int i = 0; i < eqSet.Data.Enchants.Length; ++i)
@@ -2338,7 +2338,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.IgnoreMask); stmt.AddValue(j++, eqSet.Data.IgnoreMask);
stmt.AddValue(j++, eqSet.Data.AssignedSpecIndex); stmt.AddValue(j++, eqSet.Data.AssignedSpecIndex);
for (byte i = 0; i < EquipmentSlot.End; ++i) for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Pieces[i].GetCounter()); stmt.AddValue(j++, eqSet.Data.Pieces[i].GetCounter());
} }
else else
@@ -2351,7 +2351,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.SetIcon); stmt.AddValue(j++, eqSet.Data.SetIcon);
stmt.AddValue(j++, eqSet.Data.IgnoreMask); stmt.AddValue(j++, eqSet.Data.IgnoreMask);
for (byte i = 0; i < EquipmentSlot.End; ++i) for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
stmt.AddValue(j++, eqSet.Data.Appearances[i]); stmt.AddValue(j++, eqSet.Data.Appearances[i]);
for (int i = 0; i < eqSet.Data.Enchants.Length; ++i) for (int i = 0; i < eqSet.Data.Enchants.Length; ++i)
@@ -2680,15 +2680,6 @@ namespace Game.Entities
InitDisplayIds(); InitDisplayIds();
// cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)
for (byte slot = EquipmentSlot.Start; slot < EquipmentSlot.End; ++slot)
{
SetInvSlot(slot, ObjectGuid.Empty);
SetVisibleItemSlot(slot, null);
m_items[slot] = null;
}
//Need to call it to initialize m_team (m_team can be calculated from race) //Need to call it to initialize m_team (m_team can be calculated from race)
//Other way is to saves m_team into characters table. //Other way is to saves m_team into characters table.
SetFactionForRace(GetRace()); SetFactionForRace(GetRace());
@@ -2982,6 +2973,8 @@ namespace Game.Entities
long now = GameTime.GetGameTime(); long now = GameTime.GetGameTime();
long logoutTime = logout_time; long logoutTime = logout_time;
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.LogoutTime), logoutTime);
// since last logout (in seconds) // since last logout (in seconds)
uint time_diff = (uint)(now - logoutTime); uint time_diff = (uint)(now - logoutTime);
@@ -3431,7 +3424,7 @@ namespace Game.Entities
ss.Clear(); ss.Clear();
// cache equipment... // cache equipment...
for (byte i = 0; i < InventorySlots.BagEnd; ++i) for (byte i = 0; i < InventorySlots.ReagentBagEnd; ++i)
{ {
Item item = GetItemByPos(InventorySlots.Bag0, i); Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null) if (item != null)
@@ -3577,7 +3570,7 @@ namespace Game.Entities
ss.Clear(); ss.Clear();
// cache equipment... // cache equipment...
for (byte i = 0; i < InventorySlots.BagEnd; ++i) for (byte i = 0; i < InventorySlots.ReagentBagEnd; ++i)
{ {
Item item = GetItemByPos(InventorySlots.Bag0, i); Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null) if (item != null)
@@ -294,6 +294,7 @@ namespace Game.Entities
public CreatePosition createPosition; public CreatePosition createPosition;
public CreatePosition? createPositionNPE; public CreatePosition? createPositionNPE;
public ItemContext itemContext;
public List<PlayerCreateInfoItem> item = new(); public List<PlayerCreateInfoItem> item = new();
public List<uint> customSpells = new(); public List<uint> customSpells = new();
public List<uint>[] castSpells = new List<uint>[(int)PlayerCreateMode.Max]; public List<uint>[] castSpells = new List<uint>[(int)PlayerCreateMode.Max];
+75 -19
View File
@@ -1219,42 +1219,41 @@ namespace Game.Entities
return lastItem; return lastItem;
} }
bool StoreNewItemInBestSlots(uint titem_id, uint titem_amount) bool StoreNewItemInBestSlots(uint itemId, uint amount, ItemContext context)
{ {
Log.outDebug(LogFilter.Player, "STORAGE: Creating initial item, itemId = {0}, count = {1}", titem_id, titem_amount); Log.outDebug(LogFilter.Player, "STORAGE: Creating initial item, itemId = {0}, count = {1}", itemId, amount);
ItemContext itemContext = ItemContext.NewCharacter; var bonusListIDs = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, context);
var bonusListIDs = Global.DB2Mgr.GetDefaultItemBonusTree(titem_id, itemContext);
InventoryResult msg; InventoryResult msg;
// attempt equip by one // attempt equip by one
while (titem_amount > 0) while (amount > 0)
{ {
msg = CanEquipNewItem(ItemConst.NullSlot, out ushort eDest, titem_id, false); msg = CanEquipNewItem(ItemConst.NullSlot, out ushort eDest, itemId, false);
if (msg != InventoryResult.Ok) if (msg != InventoryResult.Ok)
break; break;
Item item = EquipNewItem(eDest, titem_id, itemContext, true); Item item = EquipNewItem(eDest, itemId, context, true);
item.SetBonuses(bonusListIDs); item.SetBonuses(bonusListIDs);
AutoUnequipOffhandIfNeed(); AutoUnequipOffhandIfNeed();
titem_amount--; --amount;
} }
if (titem_amount == 0) if (amount == 0)
return true; // equipped return true; // equipped
// attempt store // attempt store
List<ItemPosCount> sDest = new(); List<ItemPosCount> sDest = new();
// store in main bag to simplify second pass (special bags can be not equipped yet at this moment) // store in main bag to simplify second pass (special bags can be not equipped yet at this moment)
msg = CanStoreNewItem(InventorySlots.Bag0, ItemConst.NullSlot, sDest, titem_id, titem_amount); msg = CanStoreNewItem(InventorySlots.Bag0, ItemConst.NullSlot, sDest, itemId, amount);
if (msg == InventoryResult.Ok) if (msg == InventoryResult.Ok)
{ {
StoreNewItem(sDest, titem_id, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(titem_id), null, itemContext, bonusListIDs); StoreNewItem(sDest, itemId, true, ItemEnchantmentManager.GenerateItemRandomBonusListId(itemId), null, context, bonusListIDs);
return true; // stored return true; // stored
} }
// item can't be added // item can't be added
Log.outError(LogFilter.Player, "STORAGE: Can't equip or store initial item {0} for race {1} class {2}, error msg = {3}", titem_id, GetRace(), GetClass(), msg); Log.outError(LogFilter.Player, "STORAGE: Can't equip or store initial item {0} for race {1} class {2}, error msg = {3}", itemId, GetRace(), GetClass(), msg);
return false; return false;
} }
public Item StoreNewItem(List<ItemPosCount> pos, uint itemId, bool update, uint randomBonusListId = 0, List<ObjectGuid> allowedLooters = null, ItemContext context = 0, List<uint> bonusListIDs = null, bool addToCollection = true) public Item StoreNewItem(List<ItemPosCount> pos, uint itemId, bool update, uint randomBonusListId = 0, List<ObjectGuid> allowedLooters = null, ItemContext context = 0, List<uint> bonusListIDs = null, bool addToCollection = true)
@@ -1878,7 +1877,7 @@ namespace Game.Entities
pItem.RemoveItemFlag2(ItemFieldFlags2.Equipped); pItem.RemoveItemFlag2(ItemFieldFlags2.Equipped);
// remove item dependent auras and casts (only weapon and armor slots) // remove item dependent auras and casts (only weapon and armor slots)
if (slot < EquipmentSlot.End) if (slot < ProfessionSlots.End)
{ {
// update expertise // update expertise
if (slot == EquipmentSlot.MainHand) if (slot == EquipmentSlot.MainHand)
@@ -2789,10 +2788,18 @@ namespace Game.Entities
if (slot < EquipmentSlot.End) if (slot < EquipmentSlot.End)
return true; return true;
// profession equipment
if (slot >= ProfessionSlots.Start && slot < ProfessionSlots.End)
return true;
// bag equip slots // bag equip slots
if (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd) if (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd)
return true; return true;
// reagent bag equip slots
if (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd)
return true;
// backpack slots // backpack slots
if (slot >= InventorySlots.ItemStart && slot < InventorySlots.ItemStart + GetInventorySlotCount()) if (slot >= InventorySlots.ItemStart && slot < InventorySlots.ItemStart + GetInventorySlotCount())
return true; return true;
@@ -3010,7 +3017,7 @@ namespace Game.Entities
// if current back slot non-empty search oldest or free // if current back slot non-empty search oldest or free
if (m_items[slot] != null) if (m_items[slot] != null)
{ {
long oldest_time = m_activePlayerData.BuybackTimestamp[0]; ulong oldest_time = m_activePlayerData.BuybackTimestamp[0];
uint oldest_slot = InventorySlots.BuyBackStart; uint oldest_slot = InventorySlots.BuyBackStart;
for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i) for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i)
@@ -3022,7 +3029,7 @@ namespace Game.Entities
break; break;
} }
long i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart]; ulong i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
if (oldest_time > i_time) if (oldest_time > i_time)
{ {
oldest_time = i_time; oldest_time = i_time;
@@ -3473,7 +3480,7 @@ namespace Game.Entities
DB.Characters.CommitTransaction(trans); DB.Characters.CommitTransaction(trans);
} }
public void SetBuybackPrice(uint slot, uint price) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackPrice, (int)slot), price); } public void SetBuybackPrice(uint slot, uint price) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackPrice, (int)slot), price); }
public void SetBuybackTimestamp(uint slot, long timestamp) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackTimestamp, (int)slot), timestamp); } public void SetBuybackTimestamp(uint slot, ulong timestamp) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackTimestamp, (int)slot), timestamp); }
public Item GetItemFromBuyBackSlot(uint slot) public Item GetItemFromBuyBackSlot(uint slot)
{ {
@@ -4523,10 +4530,16 @@ namespace Game.Entities
uint freeSlotCount = 0; uint freeSlotCount = 0;
if (location.HasFlag(ItemSearchLocation.Equipment)) if (location.HasFlag(ItemSearchLocation.Equipment))
{
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i) for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
if (GetItemByPos(InventorySlots.Bag0, i) == null) if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount; ++freeSlotCount;
for (byte i = ProfessionSlots.Start; i < ProfessionSlots.End; ++i)
if (!GetItemByPos(InventorySlots.Bag0, i))
++freeSlotCount;
}
if (location.HasFlag(ItemSearchLocation.Inventory)) if (location.HasFlag(ItemSearchLocation.Inventory))
{ {
int inventoryEnd = InventorySlots.ItemStart + GetInventorySlotCount(); int inventoryEnd = InventorySlots.ItemStart + GetInventorySlotCount();
@@ -4565,9 +4578,20 @@ namespace Game.Entities
} }
if (location.HasFlag(ItemSearchLocation.ReagentBank)) if (location.HasFlag(ItemSearchLocation.ReagentBank))
{
for (byte i = InventorySlots.ReagentBagStart; i < InventorySlots.ReagentBagEnd; ++i)
{
Bag bag = GetBagByPos(i);
if (bag != null)
for (byte j = 0; j < bag.GetBagSize(); ++j)
if (bag.GetItemByPos(j) == null)
++freeSlotCount;
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i) for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
if (GetItemByPos(InventorySlots.Bag0, i) == null) if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount; ++freeSlotCount;
}
return freeSlotCount; return freeSlotCount;
} }
@@ -4608,7 +4632,8 @@ namespace Game.Entities
public Bag GetBagByPos(byte bag) public Bag GetBagByPos(byte bag)
{ {
if ((bag >= InventorySlots.BagStart && bag < InventorySlots.BagEnd) if ((bag >= InventorySlots.BagStart && bag < InventorySlots.BagEnd)
|| (bag >= InventorySlots.BankBagStart && bag < InventorySlots.BankBagEnd)) || (bag >= InventorySlots.BankBagStart && bag < InventorySlots.BankBagEnd)
|| (bag >= InventorySlots.ReagentBagStart && bag < InventorySlots.ReagentBagEnd))
{ {
Item item = GetItemByPos(InventorySlots.Bag0, bag); Item item = GetItemByPos(InventorySlots.Bag0, bag);
if (item != null) if (item != null)
@@ -4624,6 +4649,8 @@ namespace Game.Entities
return true; return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BankBagStart && slot < InventorySlots.BankBagEnd)) if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BankBagStart && slot < InventorySlots.BankBagEnd))
return true; return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd))
return true;
return false; return false;
} }
InventoryResult CanStoreItem_InBag(byte bag, List<ItemPosCount> dest, ItemTemplate pProto, ref uint count, bool merge, bool non_specialized, Item pSrcItem, byte skip_bag, byte skip_slot) InventoryResult CanStoreItem_InBag(byte bag, List<ItemPosCount> dest, ItemTemplate pProto, ref uint count, bool merge, bool non_specialized, Item pSrcItem, byte skip_bag, byte skip_slot)
@@ -4712,8 +4739,12 @@ namespace Game.Entities
{ {
if (bag == InventorySlots.Bag0 && (slot < EquipmentSlot.End)) if (bag == InventorySlots.Bag0 && (slot < EquipmentSlot.End))
return true; return true;
if (bag == InventorySlots.Bag0 && (slot >= ProfessionSlots.Start && slot < ProfessionSlots.End))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd)) if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd))
return true; return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd))
return true;
return false; return false;
} }
byte FindEquipSlot(Item item, uint slot, bool swap) byte FindEquipSlot(Item item, uint slot, bool swap)
@@ -5246,8 +5277,10 @@ namespace Game.Entities
{ {
AddTemporarySpell(artifactPowerRank.SpellID); AddTemporarySpell(artifactPowerRank.SpellID);
LearnedSpells learnedSpells = new(); LearnedSpells learnedSpells = new();
LearnedSpellInfo learnedSpellInfo = new();
learnedSpellInfo.SpellID = artifactPowerRank.SpellID;
learnedSpells.SuppressMessaging = true; learnedSpells.SuppressMessaging = true;
learnedSpells.SpellID.Add(artifactPowerRank.SpellID); learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(learnedSpells); SendPacket(learnedSpells);
} }
else if (!apply) else if (!apply)
@@ -6314,6 +6347,14 @@ namespace Game.Entities
if (!callback(item)) if (!callback(item))
return false; return false;
} }
for (byte i = ProfessionSlots.Start; i < ProfessionSlots.End; ++i)
{
Item pItem = GetItemByPos(InventorySlots.Bag0, i);
if (pItem != null)
if (!callback(pItem))
return false;
}
} }
if (location.HasAnyFlag(ItemSearchLocation.Inventory)) if (location.HasAnyFlag(ItemSearchLocation.Inventory))
@@ -6379,6 +6420,21 @@ namespace Game.Entities
if (location.HasAnyFlag(ItemSearchLocation.ReagentBank)) if (location.HasAnyFlag(ItemSearchLocation.ReagentBank))
{ {
for (byte i = InventorySlots.ReagentBagStart; i < InventorySlots.ReagentBagEnd; ++i)
{
Bag bag = GetBagByPos(i);
if (bag != null)
{
for (byte j = 0; j < bag.GetBagSize(); ++j)
{
Item pItem = bag.GetItemByPos(j);
if (pItem != null)
if (!callback(pItem))
return false;
}
}
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i) for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{ {
Item item = GetItemByPos(InventorySlots.Bag0, i); Item item = GetItemByPos(InventorySlots.Bag0, i);
@@ -6471,7 +6527,7 @@ namespace Game.Entities
ForEachItem(ItemSearchLocation.Everywhere, item => ForEachItem(ItemSearchLocation.Everywhere, item =>
{ {
ItemTemplate itemTemplate = item.GetTemplate(); ItemTemplate itemTemplate = item.GetTemplate();
if (itemTemplate != null) if (itemTemplate != null && itemTemplate.GetInventoryType() < InventoryType.ProfessionTool)
{ {
ushort dest; ushort dest;
if (item.IsEquipped()) if (item.IsEquipped())
@@ -3114,14 +3114,5 @@ namespace Game.Entities
SendPacket(displayToast); SendPacket(displayToast);
} }
void SendGarrisonOpenTalentNpc(ObjectGuid guid, int garrTalentTreeId, int friendshipFactionId)
{
GarrisonOpenTalentNpc openTalentNpc = new();
openTalentNpc.NpcGUID = guid;
openTalentNpc.GarrTalentTreeID = garrTalentTreeId;
openTalentNpc.FriendshipFactionID = friendshipFactionId;
SendPacket(openTalentNpc);
}
} }
} }
+10 -6
View File
@@ -2058,10 +2058,12 @@ namespace Game.Entities
// prevent duplicated entires in spell book, also not send if not in world (loading) // prevent duplicated entires in spell book, also not send if not in world (loading)
if (learning && IsInWorld) if (learning && IsInWorld)
{ {
LearnedSpells packet = new(); LearnedSpells learnedSpells = new();
packet.SpellID.Add(spellId); LearnedSpellInfo learnedSpellInfo = new();
packet.SuppressMessaging = suppressMessaging; learnedSpellInfo.SpellID = spellId;
SendPacket(packet); learnedSpells.SuppressMessaging = suppressMessaging;
learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(learnedSpells);
} }
// learn all disabled higher ranks and required spells (recursive) // learn all disabled higher ranks and required spells (recursive)
@@ -3046,8 +3048,10 @@ namespace Game.Entities
void SendSupercededSpell(uint oldSpell, uint newSpell) void SendSupercededSpell(uint oldSpell, uint newSpell)
{ {
SupercededSpells supercededSpells = new(); SupercededSpells supercededSpells = new();
supercededSpells.SpellID.Add(newSpell); LearnedSpellInfo learnedSpellInfo = new();
supercededSpells.Superceded.Add(oldSpell); learnedSpellInfo.SpellID = newSpell;
learnedSpellInfo.Superceded = (int)oldSpell;
supercededSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(supercededSpells); SendPacket(supercededSpells);
} }
@@ -698,6 +698,11 @@ namespace Game.Entities
if (HasPvpTalent(talentID, GetActiveTalentGroup())) if (HasPvpTalent(talentID, GetActiveTalentGroup()))
return TalentLearnResult.FailedUnknown; return TalentLearnResult.FailedUnknown;
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(talentInfo.PlayerConditionID);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
return TalentLearnResult.FailedCantDoThatRightNow;
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]); PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
if (talent != null) if (talent != null)
{ {
+132 -148
View File
@@ -296,7 +296,7 @@ namespace Game.Entities
// original items // original items
foreach (PlayerCreateInfoItem initialItem in info.item) foreach (PlayerCreateInfoItem initialItem in info.item)
StoreNewItemInBestSlots(initialItem.item_id, initialItem.item_amount); StoreNewItemInBestSlots(initialItem.item_id, initialItem.item_amount, info.itemContext);
// bags and main-hand weapon must equipped at this moment // bags and main-hand weapon must equipped at this moment
// now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon) // now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon)
@@ -685,7 +685,7 @@ namespace Game.Entities
if (target == this) if (target == this)
{ {
for (byte i = 0; i < EquipmentSlot.End; ++i) for (byte i = EquipmentSlot.Start; i < InventorySlots.BankBagEnd; ++i)
{ {
if (m_items[i] == null) if (m_items[i] == null)
continue; continue;
@@ -693,23 +693,7 @@ namespace Game.Entities
m_items[i].DestroyForPlayer(target); m_items[i].DestroyForPlayer(target);
} }
for (byte i = InventorySlots.BagStart; i < InventorySlots.BagEnd; ++i) for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].DestroyForPlayer(target);
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].DestroyForPlayer(target);
}
for (byte i = InventorySlots.ChildEquipmentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{ {
if (m_items[i] == null) if (m_items[i] == null)
continue; continue;
@@ -2329,7 +2313,7 @@ namespace Game.Entities
{ {
switch (gossipMenuItem.OptionNpc) switch (gossipMenuItem.OptionNpc)
{ {
case GossipOptionNpc.TaxiNode: case GossipOptionNpc.Taxinode:
if (GetSession().SendLearnNewTaxiNode(creature)) if (GetSession().SendLearnNewTaxiNode(creature))
return; return;
break; break;
@@ -2337,7 +2321,7 @@ namespace Game.Entities
if (!IsDead()) if (!IsDead())
canTalk = false; canTalk = false;
break; break;
case GossipOptionNpc.BattleMaster: case GossipOptionNpc.Battlemaster:
if (!creature.CanInteractWithBattleMaster(this, false)) if (!creature.CanInteractWithBattleMaster(this, false))
canTalk = false; canTalk = false;
break; break;
@@ -2347,7 +2331,7 @@ namespace Game.Entities
if (!creature.CanResetTalents(this)) if (!creature.CanResetTalents(this))
canTalk = false; canTalk = false;
break; break;
case GossipOptionNpc.StableMaster: case GossipOptionNpc.Stablemaster:
case GossipOptionNpc.PetSpecializationMaster: case GossipOptionNpc.PetSpecializationMaster:
if (GetClass() != Class.Hunter) if (GetClass() != Class.Hunter)
canTalk = false; canTalk = false;
@@ -2376,32 +2360,32 @@ namespace Game.Entities
canTalk = false; // Deprecated canTalk = false; // Deprecated
break; break;
case GossipOptionNpc.GuildBanker: case GossipOptionNpc.GuildBanker:
case GossipOptionNpc.SpellClick: case GossipOptionNpc.Spellclick:
case GossipOptionNpc.WorldPVPQueue: case GossipOptionNpc.WorldPvPQueue:
case GossipOptionNpc.LFGDungeon: case GossipOptionNpc.LFGDungeon:
case GossipOptionNpc.ArtifactRespec: case GossipOptionNpc.ArtifactRespec:
case GossipOptionNpc.QueueScenario: case GossipOptionNpc.QueueScenario:
case GossipOptionNpc.GarrisonArchitect: case GossipOptionNpc.GarrisonArchitect:
case GossipOptionNpc.GarrisonMission: case GossipOptionNpc.GarrisonMissionNpc:
case GossipOptionNpc.ShipmentCrafter: case GossipOptionNpc.ShipmentCrafter:
case GossipOptionNpc.GarrisonTradeskill: case GossipOptionNpc.GarrisonTradeskillNpc:
case GossipOptionNpc.GarrisonRecruitment: case GossipOptionNpc.GarrisonRecruitment:
case GossipOptionNpc.AdventureMap: case GossipOptionNpc.AdventureMap:
case GossipOptionNpc.GarrisonTalent: case GossipOptionNpc.GarrisonTalent:
case GossipOptionNpc.ContributionCollector: case GossipOptionNpc.ContributionCollector:
case GossipOptionNpc.IslandsMission: case GossipOptionNpc.IslandsMissionNpc:
case GossipOptionNpc.UIItemInteraction: case GossipOptionNpc.UIItemInteraction:
case GossipOptionNpc.WorldMap: case GossipOptionNpc.WorldMap:
case GossipOptionNpc.Soulbind: case GossipOptionNpc.Soulbind:
case GossipOptionNpc.ChromieTime: case GossipOptionNpc.ChromieTimeNpc:
case GossipOptionNpc.CovenantPreview: case GossipOptionNpc.CovenantPreviewNpc:
case GossipOptionNpc.RuneforgeLegendaryCrafting: case GossipOptionNpc.RuneforgeLegendaryCrafting:
case GossipOptionNpc.NewPlayerGuide: case GossipOptionNpc.NewPlayerGuide:
case GossipOptionNpc.RuneforgeLegendaryUpgrade: case GossipOptionNpc.RuneforgeLegendaryUpgrade:
case GossipOptionNpc.CovenantRenown: case GossipOptionNpc.CovenantRenownNpc:
break; // NYI break; // NYI
default: default:
Log.outError(LogFilter.Sql, $"Creature entry {creature.GetEntry()} has an unknown gossip option icon {gossipMenuItem.OptionNpc} for menu {gossipMenuItem.MenuId}."); Log.outError(LogFilter.Sql, $"Creature entry {creature.GetEntry()} has an unknown gossip option icon {gossipMenuItem.OptionNpc} for menu {gossipMenuItem.MenuID}.");
canTalk = false; canTalk = false;
break; break;
} }
@@ -2421,45 +2405,7 @@ namespace Game.Entities
} }
if (canTalk) if (canTalk)
{ menu.GetGossipMenu().AddMenuItem(gossipMenuItem, gossipMenuItem.MenuID, gossipMenuItem.OrderIndex);
string strOptionText;
string strBoxText;
BroadcastTextRecord optionBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItem.OptionBroadcastTextId);
BroadcastTextRecord boxBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItem.BoxBroadcastTextId);
Locale locale = GetSession().GetSessionDbLocaleIndex();
if (optionBroadcastText != null)
strOptionText = Global.DB2Mgr.GetBroadcastTextValue(optionBroadcastText, locale, GetGender());
else
strOptionText = gossipMenuItem.OptionText;
if (boxBroadcastText != null)
strBoxText = Global.DB2Mgr.GetBroadcastTextValue(boxBroadcastText, locale, GetGender());
else
strBoxText = gossipMenuItem.BoxText;
if (locale != Locale.enUS)
{
if (optionBroadcastText == null)
{
// Find localizations from database.
GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuId, gossipMenuItem.OptionId);
if (gossipMenuLocale != null)
ObjectManager.GetLocaleString(gossipMenuLocale.OptionText, locale, ref strOptionText);
}
if (boxBroadcastText == null)
{
// Find localizations from database.
GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuId, gossipMenuItem.OptionId);
if (gossipMenuLocale != null)
ObjectManager.GetLocaleString(gossipMenuLocale.BoxText, locale, ref strBoxText);
}
}
menu.GetGossipMenu().AddMenuItem((int)gossipMenuItem.OptionId, gossipMenuItem.OptionNpc, strOptionText, 0, (uint)gossipMenuItem.OptionNpc, strBoxText, gossipMenuItem.BoxMoney, gossipMenuItem.BoxCoded);
menu.GetGossipMenu().AddGossipMenuItemData(gossipMenuItem.OptionId, gossipMenuItem.ActionMenuId, gossipMenuItem.ActionPoiId);
}
} }
} }
public void SendPreparedGossip(WorldObject source) public void SendPreparedGossip(WorldObject source)
@@ -2486,7 +2432,7 @@ namespace Game.Entities
PlayerTalkClass.SendGossipMenu(textId, source.GetGUID()); PlayerTalkClass.SendGossipMenu(textId, source.GetGUID());
} }
public void OnGossipSelect(WorldObject source, uint gossipListId, uint menuId) public void OnGossipSelect(WorldObject source, int gossipOptionId, uint menuId)
{ {
GossipMenu gossipMenu = PlayerTalkClass.GetGossipMenu(); GossipMenu gossipMenu = PlayerTalkClass.GetGossipMenu();
@@ -2494,7 +2440,7 @@ namespace Game.Entities
if (menuId != gossipMenu.GetMenuId()) if (menuId != gossipMenu.GetMenuId())
return; return;
GossipMenuItem item = gossipMenu.GetItem(gossipListId); GossipMenuItem item = gossipMenu.GetItem(gossipOptionId);
if (item == null) if (item == null)
return; return;
@@ -2510,10 +2456,6 @@ namespace Game.Entities
} }
} }
GossipMenuItemData menuItemData = gossipMenu.GetItemData(gossipListId);
if (menuItemData == null)
return;
long cost = item.BoxMoney; long cost = item.BoxMoney;
if (!HasEnoughMoney(cost)) if (!HasEnoughMoney(cost))
{ {
@@ -2522,51 +2464,37 @@ namespace Game.Entities
return; return;
} }
if (item.ActionPoiID != 0)
PlayerTalkClass.SendPointOfInterest(item.ActionPoiID);
if (item.ActionMenuID != 0)
{
PrepareGossipMenu(source, item.ActionMenuID);
SendPreparedGossip(source);
}
// types that have their dedicated open opcode dont send WorldPackets::NPC::GossipOptionNPCInteraction
bool handled = true;
switch (gossipOptionNpc) switch (gossipOptionNpc)
{ {
case GossipOptionNpc.None:
{
if (menuItemData.GossipActionPoi != 0)
PlayerTalkClass.SendPointOfInterest(menuItemData.GossipActionPoi);
if (menuItemData.GossipActionMenuId != 0)
{
PrepareGossipMenu(source, menuItemData.GossipActionMenuId);
SendPreparedGossip(source);
}
break;
}
case GossipOptionNpc.Vendor: case GossipOptionNpc.Vendor:
GetSession().SendListInventory(guid); GetSession().SendListInventory(guid);
break; break;
case GossipOptionNpc.TaxiNode: case GossipOptionNpc.Taxinode:
GetSession().SendTaxiMenu(source.ToCreature()); GetSession().SendTaxiMenu(source.ToCreature());
break; break;
case GossipOptionNpc.Trainer: case GossipOptionNpc.Trainer:
GetSession().SendTrainerList(source.ToCreature(), Global.ObjectMgr.GetCreatureTrainerForGossipOption(source.GetEntry(), menuId, gossipListId)); GetSession().SendTrainerList(source.ToCreature(), Global.ObjectMgr.GetCreatureTrainerForGossipOption(source.GetEntry(), menuId, (uint)gossipOptionId));
break; break;
case GossipOptionNpc.SpiritHealer: case GossipOptionNpc.SpiritHealer:
if (IsDead()) source.CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCaster(GetGUID()));
source.ToCreature().CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask) handled = false;
.SetOriginalCaster(GetGUID()));
break;
case GossipOptionNpc.Binder:
PlayerTalkClass.SendCloseGossip();
SetBindPoint(guid);
break;
case GossipOptionNpc.Banker:
GetSession().SendShowBank(guid);
break; break;
case GossipOptionNpc.PetitionVendor: case GossipOptionNpc.PetitionVendor:
PlayerTalkClass.SendCloseGossip(); PlayerTalkClass.SendCloseGossip();
GetSession().SendPetitionShowList(guid); GetSession().SendPetitionShowList(guid);
break; break;
case GossipOptionNpc.TabardVendor: case GossipOptionNpc.Battlemaster:
PlayerTalkClass.SendCloseGossip();
GetSession().SendTabardVendorActivate(guid);
break;
case GossipOptionNpc.BattleMaster:
{ {
BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.GetBattleMasterBG(source.GetEntry()); BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.GetBattleMasterBG(source.GetEntry());
@@ -2586,13 +2514,25 @@ namespace Game.Entities
PlayerTalkClass.SendCloseGossip(); PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.Talents); SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.Talents);
break; break;
case GossipOptionNpc.StableMaster: case GossipOptionNpc.Stablemaster:
GetSession().SendStablePet(guid); GetSession().SendStablePet(guid);
break; break;
case GossipOptionNpc.PetSpecializationMaster: case GossipOptionNpc.PetSpecializationMaster:
PlayerTalkClass.SendCloseGossip(); PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.PetTalents); SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.PetTalents);
break; break;
case GossipOptionNpc.GuildBanker:
Guild guild = GetGuild();
if (guild != null)
guild.SendBankList(GetSession(), 0, true);
else
Guild.SendCommandResult(GetSession(), GuildCommandType.ViewTab, GuildCommandError.PlayerNotInGuild);
break;
case GossipOptionNpc.Spellclick:
Unit sourceUnit = source.ToUnit();
if (sourceUnit != null)
sourceUnit.HandleSpellClick(this);
break;
case GossipOptionNpc.DisableXPGain: case GossipOptionNpc.DisableXPGain:
PlayerTalkClass.SendCloseGossip(); PlayerTalkClass.SendCloseGossip();
CastSpell(null, PlayerConst.SpellExperienceEliminated, true); CastSpell(null, PlayerConst.SpellExperienceEliminated, true);
@@ -2603,9 +2543,6 @@ namespace Game.Entities
RemoveAurasDueToSpell(PlayerConst.SpellExperienceEliminated); RemoveAurasDueToSpell(PlayerConst.SpellExperienceEliminated);
RemovePlayerFlag(PlayerFlags.NoXPGain); RemovePlayerFlag(PlayerFlags.NoXPGain);
break; break;
case GossipOptionNpc.Mailbox:
GetSession().SendShowMailBox(guid);
break;
case GossipOptionNpc.SpecializationMaster: case GossipOptionNpc.SpecializationMaster:
PlayerTalkClass.SendCloseGossip(); PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, 0, SpecResetType.Specialization); SendRespecWipeConfirm(guid, 0, SpecResetType.Specialization);
@@ -2614,22 +2551,74 @@ namespace Game.Entities
PlayerTalkClass.SendCloseGossip(); PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, 0, SpecResetType.Glyphs); SendRespecWipeConfirm(guid, 0, SpecResetType.Glyphs);
break; break;
case GossipOptionNpc.GarrisonTalent: case GossipOptionNpc.GarrisonTradeskillNpc: // NYI
break;
case GossipOptionNpc.GarrisonRecruitment: // NYI
break;
case GossipOptionNpc.ChromieTimeNpc: // NYI
break;
case GossipOptionNpc.RuneforgeLegendaryCrafting: // NYI
break;
case GossipOptionNpc.RuneforgeLegendaryUpgrade: // NYI
break;
case GossipOptionNpc.ProfessionsCraftingOrder: // NYI
break;
case GossipOptionNpc.ProfessionsCustomerOrder: // NYI
break;
case GossipOptionNpc.BarbersChoice: // NYI - unknown if needs sending
default:
handled = false;
break;
}
if (!handled)
{
if (item.GossipNpcOptionID.HasValue)
{ {
GossipMenuAddon addon = Global.ObjectMgr.GetGossipMenuAddon(menuId); GossipMenuAddon addon = Global.ObjectMgr.GetGossipMenuAddon(menuId);
GossipMenuItemAddon itemAddon = Global.ObjectMgr.GetGossipMenuItemAddon(menuId, gossipListId);
SendGarrisonOpenTalentNpc(guid, itemAddon != null ? itemAddon.GarrTalentTreeID.GetValueOrDefault(0) : 0, addon != null ? addon.FriendshipFactionID : 0); GossipOptionNPCInteraction npcInteraction = new();
break; npcInteraction.GossipGUID = source.GetGUID();
npcInteraction.GossipNpcOptionID = item.GossipNpcOptionID.Value;
if (addon != null && addon.FriendshipFactionID != 0)
npcInteraction.FriendshipFactionID = addon.FriendshipFactionID;
SendPacket(npcInteraction);
}
else
{
PlayerInteractionType[] GossipOptionNpcToInteractionType =
{
PlayerInteractionType.None, PlayerInteractionType.Vendor, PlayerInteractionType.TaxiNode,
PlayerInteractionType.Trainer, PlayerInteractionType.SpiritHealer, PlayerInteractionType.Binder,
PlayerInteractionType.Banker, PlayerInteractionType.PetitionVendor, PlayerInteractionType.TabardVendor,
PlayerInteractionType.BattleMaster, PlayerInteractionType.Auctioneer, PlayerInteractionType.TalentMaster,
PlayerInteractionType.StableMaster, PlayerInteractionType.None, PlayerInteractionType.GuildBanker,
PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.None,
PlayerInteractionType.MailInfo, PlayerInteractionType.None, PlayerInteractionType.LFGDungeon,
PlayerInteractionType.ArtifactForge, PlayerInteractionType.None, PlayerInteractionType.SpecializationMaster,
PlayerInteractionType.None, PlayerInteractionType.None, PlayerInteractionType.GarrArchitect,
PlayerInteractionType.GarrMission, PlayerInteractionType.ShipmentCrafter, PlayerInteractionType.GarrTradeskill,
PlayerInteractionType.GarrRecruitment, PlayerInteractionType.AdventureMap, PlayerInteractionType.GarrTalent,
PlayerInteractionType.ContributionCollector, PlayerInteractionType.Transmogrifier, PlayerInteractionType.AzeriteRespec,
PlayerInteractionType.IslandQueue, PlayerInteractionType.ItemInteraction, PlayerInteractionType.WorldMap,
PlayerInteractionType.Soulbind, PlayerInteractionType.ChromieTime, PlayerInteractionType.CovenantPreview,
PlayerInteractionType.LegendaryCrafting, PlayerInteractionType.NewPlayerGuide, PlayerInteractionType.LegendaryCrafting,
PlayerInteractionType.Renown, PlayerInteractionType.BlackMarketAuctioneer, PlayerInteractionType.PerksProgramVendor,
PlayerInteractionType.ProfessionsCraftingOrder, PlayerInteractionType.Professions, PlayerInteractionType.ProfessionsCustomerOrder,
PlayerInteractionType.TraitSystem, PlayerInteractionType.BarbersChoice, PlayerInteractionType.MajorFactionRenown
};
PlayerInteractionType interactionType = GossipOptionNpcToInteractionType[(int)gossipOptionNpc];
if (interactionType != PlayerInteractionType.None)
{
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = source.GetGUID();
npcInteraction.InteractionType = interactionType;
npcInteraction.Success = true;
SendPacket(npcInteraction);
}
} }
case GossipOptionNpc.Transmogrify:
GetSession().SendOpenTransmogrifier(guid);
break;
case GossipOptionNpc.AzeriteRespec:
PlayerTalkClass.SendCloseGossip();
GetSession().SendAzeriteRespecNPC(guid);
break;
default:
break;
} }
ModifyMoney(-cost); ModifyMoney(-cost);
@@ -2916,8 +2905,11 @@ namespace Game.Entities
} }
public void SetBindPoint(ObjectGuid guid) public void SetBindPoint(ObjectGuid guid)
{ {
BinderConfirm packet = new(guid); NPCInteractionOpenResult npcInteraction = new();
SendPacket(packet); npcInteraction.Npc = guid;
npcInteraction.InteractionType = PlayerInteractionType.Binder;
npcInteraction.Success = true;
SendPacket(npcInteraction);
} }
public void SendBindPointUpdate() public void SendBindPointUpdate()
{ {
@@ -4021,7 +4013,7 @@ namespace Game.Entities
corpse.SetDisplayId(GetNativeDisplayId()); corpse.SetDisplayId(GetNativeDisplayId());
corpse.SetFactionTemplate(CliDB.ChrRacesStorage.LookupByKey(GetRace()).FactionID); corpse.SetFactionTemplate(CliDB.ChrRacesStorage.LookupByKey(GetRace()).FactionID);
for (byte i = 0; i < EquipmentSlot.End; i++) for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; i++)
{ {
if (m_items[i] != null) if (m_items[i] != null)
{ {
@@ -6240,7 +6232,6 @@ namespace Game.Entities
packet.Reason = victim ? PlayerLogXPReason.Kill : PlayerLogXPReason.NoKill; packet.Reason = victim ? PlayerLogXPReason.Kill : PlayerLogXPReason.NoKill;
packet.Amount = (int)xp; packet.Amount = (int)xp;
packet.GroupBonus = group_rate; packet.GroupBonus = group_rate;
packet.ReferAFriendBonusType = (byte)(recruitAFriend ? 1 : 0);
SendPacket(packet); SendPacket(packet);
uint nextLvlXP = GetXPForNextLevel(); uint nextLvlXP = GetXPForNextLevel();
@@ -7238,7 +7229,7 @@ namespace Game.Entities
{ {
if (target == this) if (target == this)
{ {
for (byte i = 0; i < EquipmentSlot.End; ++i) for (byte i = EquipmentSlot.Start; i < InventorySlots.BankBagEnd; ++i)
{ {
if (m_items[i] == null) if (m_items[i] == null)
continue; continue;
@@ -7246,23 +7237,7 @@ namespace Game.Entities
m_items[i].BuildCreateUpdateBlockForPlayer(data, target); m_items[i].BuildCreateUpdateBlockForPlayer(data, target);
} }
for (byte i = InventorySlots.BagStart; i < InventorySlots.BankBagEnd; ++i) for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].BuildCreateUpdateBlockForPlayer(data, target);
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].BuildCreateUpdateBlockForPlayer(data, target);
}
for (byte i = InventorySlots.ChildEquipmentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{ {
if (m_items[i] == null) if (m_items[i] == null)
continue; continue;
@@ -7392,9 +7367,18 @@ namespace Game.Entities
} }
//Helpers //Helpers
public void AddGossipItem(GossipOptionNpc icon, string message, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, "", 0); } public void AddGossipItem(GossipOptionNpc optionNpc, string text, uint sender, uint action)
public void AddGossipItem(uint menuId, uint menuItemId, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(menuId, menuItemId, sender, action); } {
public void ADD_GOSSIP_ITEM_EXTENDED(GossipOptionNpc icon, string message, uint sender, uint action, string boxmessage, uint boxmoney, bool coded) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, boxmessage, boxmoney, coded); } PlayerTalkClass.GetGossipMenu().AddMenuItem(0, -1, optionNpc, text, 0, GossipOptionFlags.None, null, false, 0, "", null, null, sender, action);
}
public void AddGossipItem(GossipOptionNpc optionNpc, string text, uint sender, uint action, string popupText, uint popupMoney, bool coded)
{
PlayerTalkClass.GetGossipMenu().AddMenuItem(0, -1, optionNpc, text, 0, GossipOptionFlags.None, null, coded, popupMoney, popupText, null, null, sender, action);
}
public void AddGossipItem(uint gossipMenuID, uint gossipMenuItemID, uint sender, uint action)
{
PlayerTalkClass.GetGossipMenu().AddMenuItem(gossipMenuID, gossipMenuItemID, sender, action);
}
// This fuction Sends the current menu to show to client, a - NPCTEXTID(uint32), b - npc guid(uint64) // This fuction Sends the current menu to show to client, a - NPCTEXTID(uint32), b - npc guid(uint64)
public void SendGossipMenu(uint titleId, ObjectGuid objGUID) { PlayerTalkClass.SendGossipMenu(titleId, objGUID); } public void SendGossipMenu(uint titleId, ObjectGuid objGUID) { PlayerTalkClass.SendGossipMenu(titleId, objGUID); }
+9 -3
View File
@@ -1634,7 +1634,9 @@ namespace Game.Entities
0.9830f, // Warlock 0.9830f, // Warlock
0.9830f, // Monk 0.9830f, // Monk
0.9720f, // Druid 0.9720f, // Druid
0.9830f // Demon Hunter 0.9830f, // Demon Hunter
0.9880f, // Evoker
1.0f, // Adventurer
}; };
// 1 1 k cx // 1 1 k cx
@@ -1670,7 +1672,9 @@ namespace Game.Entities
0.0f, // Warlock 0.0f, // Warlock
90.6425f, // Monk 90.6425f, // Monk
0.0f, // Druid 0.0f, // Druid
65.631440f // Demon Hunter 65.631440f, // Demon Hunter
0.0f, // Evoker
0.0f, // Adventurer
}; };
public void UpdateParryPercentage() public void UpdateParryPercentage()
@@ -1708,7 +1712,9 @@ namespace Game.Entities
150.375940f, // Warlock 150.375940f, // Warlock
145.560408f, // Monk 145.560408f, // Monk
116.890707f, // Druid 116.890707f, // Druid
145.560408f // Demon Hunter 145.560408f, // Demon Hunter
145.560408f, // Evoker
0.0f, // Adventurer
}; };
public void UpdateDodgePercentage() public void UpdateDodgePercentage()
+5
View File
@@ -301,6 +301,11 @@ namespace Game.Entities
{ {
return aurEff.GetCasterGUID() == caster.GetGUID() && aurEff.IsAffectingSpell(spellProto); return aurEff.GetCasterGUID() == caster.GetGUID() && aurEff.IsAffectingSpell(spellProto);
}); });
TakenTotalMod *= GetTotalAuraMultiplier(AuraType.ModDamageTakenFromCasterByLabel, aurEff =>
{
return aurEff.GetCasterGUID() == caster.GetGUID() && spellProto.HasLabel((uint)aurEff.GetMiscValue());
});
} }
if (damagetype == DamageEffectType.DOT) if (damagetype == DamageEffectType.DOT)
+140 -124
View File
@@ -380,6 +380,8 @@ namespace Game
if (!result.IsEmpty()) if (!result.IsEmpty())
{ {
Dictionary<byte, Dictionary<byte, Tuple<byte, byte>>> temp = new(); Dictionary<byte, Dictionary<byte, Tuple<byte, byte>>> temp = new();
byte[] minRequirementForClass = new byte[(int)Class.Max];
Array.Fill(minRequirementForClass, (byte)Expansion.Max);
uint count = 0; uint count = 0;
do do
{ {
@@ -418,6 +420,7 @@ namespace Game
temp[raceID] = new Dictionary<byte, Tuple<byte, byte>>(); temp[raceID] = new Dictionary<byte, Tuple<byte, byte>>();
temp[raceID][classID] = Tuple.Create(activeExpansionLevel, accountExpansionLevel); temp[raceID][classID] = Tuple.Create(activeExpansionLevel, accountExpansionLevel);
minRequirementForClass[classID] = Math.Min(minRequirementForClass[classID], activeExpansionLevel);
++count; ++count;
} }
@@ -434,6 +437,7 @@ namespace Game
classAvailability.ClassID = class_.Key; classAvailability.ClassID = class_.Key;
classAvailability.ActiveExpansionLevel = class_.Value.Item1; classAvailability.ActiveExpansionLevel = class_.Value.Item1;
classAvailability.AccountExpansionLevel = class_.Value.Item2; classAvailability.AccountExpansionLevel = class_.Value.Item2;
classAvailability.MinActiveExpansionLevel = minRequirementForClass[class_.Key];
raceClassAvailability.Classes.Add(classAvailability); raceClassAvailability.Classes.Add(classAvailability);
} }
@@ -530,6 +534,15 @@ namespace Game
return classAvailability; return classAvailability;
} }
public ClassAvailability GetClassExpansionRequirementFallback(byte classId)
{
foreach (RaceClassAvailability raceClassAvailability in _classExpansionRequirementStorage)
foreach (ClassAvailability classAvailability in raceClassAvailability.Classes)
if (classAvailability.ClassID == classId)
return classAvailability;
return null;
}
public PlayerChoice GetPlayerChoice(int choiceId) public PlayerChoice GetPlayerChoice(int choiceId)
{ {
return _playerChoices.LookupByKey(choiceId); return _playerChoices.LookupByKey(choiceId);
@@ -578,9 +591,10 @@ namespace Game
gossipMenuItemsStorage.Clear(); gossipMenuItemsStorage.Clear();
// 0 1 2 3 4 5 6 7 8 9 10 11 // 0 1 2 3 4 5 6 7 8 9 10
SQLResult result = DB.World.Query("SELECT MenuID, OptionID, OptionNpc, OptionText, OptionBroadcastTextID, Language, ActionMenuID, ActionPoiID, BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID " + SQLResult result = DB.World.Query("SELECT MenuID, GossipOptionID, OptionID, OptionNpc, OptionText, OptionBroadcastTextID, Language, Flags, ActionMenuID, ActionPoiID, GossipNpcOptionID, " +
"FROM gossip_menu_option ORDER BY MenuID, OptionID"); //11 12 13 14 15 16
"BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID, SpellID, OverrideIconID FROM gossip_menu_option ORDER BY MenuID, OptionID");
if (result.IsEmpty()) if (result.IsEmpty())
{ {
@@ -588,26 +602,40 @@ namespace Game
return; return;
} }
Dictionary<int, uint> optionToNpcOption = new();
foreach (var (_, npcOption) in CliDB.GossipNPCOptionStorage)
optionToNpcOption[npcOption.GossipOptionID] = npcOption.Id;
do do
{ {
GossipMenuItems gMenuItem = new(); GossipMenuItems gMenuItem = new();
gMenuItem.MenuId = result.Read<uint>(0); gMenuItem.MenuID = result.Read<uint>(0);
gMenuItem.OptionId = result.Read<uint>(1); gMenuItem.GossipOptionID = result.Read<int>(1);
gMenuItem.OptionNpc = (GossipOptionNpc)result.Read<byte>(2); gMenuItem.OrderIndex = result.Read<uint>(2);
gMenuItem.OptionText = result.Read<string>(3); gMenuItem.OptionNpc = (GossipOptionNpc)result.Read<byte>(3);
gMenuItem.OptionBroadcastTextId = result.Read<uint>(4); gMenuItem.OptionText = result.Read<string>(4);
gMenuItem.Language = result.Read<uint>(5); gMenuItem.OptionBroadcastTextId = result.Read<uint>(5);
gMenuItem.ActionMenuId = result.Read<uint>(6); gMenuItem.Language = result.Read<uint>(6);
gMenuItem.ActionPoiId = result.Read<uint>(7); gMenuItem.Flags = (GossipOptionFlags)result.Read<int>(7);
gMenuItem.BoxCoded = result.Read<bool>(8); gMenuItem.ActionMenuID = result.Read<uint>(8);
gMenuItem.BoxMoney = result.Read<uint>(9); gMenuItem.ActionPoiID = result.Read<uint>(9);
gMenuItem.BoxText = result.Read<string>(10); if (!result.IsNull(10))
gMenuItem.BoxBroadcastTextId = result.Read<uint>(11); gMenuItem.GossipNpcOptionID = result.Read<int>(10);
gMenuItem.BoxCoded = result.Read<bool>(11);
gMenuItem.BoxMoney = result.Read<uint>(12);
gMenuItem.BoxText = result.Read<string>(13);
gMenuItem.BoxBroadcastTextId = result.Read<uint>(14);
if (!result.IsNull(15))
gMenuItem.SpellID = result.Read<int>(15);
if (!result.IsNull(16))
gMenuItem.OverrideIconID = result.Read<int>(16);
if (gMenuItem.OptionNpc >= GossipOptionNpc.Max) if (gMenuItem.OptionNpc >= GossipOptionNpc.Max)
{ {
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} has unknown NPC option id {gMenuItem.OptionNpc}. Replacing with GossipOptionNpc.None"); Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuID}, id {gMenuItem.OrderIndex} has unknown NPC option id {gMenuItem.OptionNpc}. Replacing with GossipOptionNpc.None");
gMenuItem.OptionNpc = GossipOptionNpc.None; gMenuItem.OptionNpc = GossipOptionNpc.None;
} }
@@ -615,47 +643,71 @@ namespace Game
{ {
if (!CliDB.BroadcastTextStorage.ContainsKey(gMenuItem.OptionBroadcastTextId)) if (!CliDB.BroadcastTextStorage.ContainsKey(gMenuItem.OptionBroadcastTextId))
{ {
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for MenuId {gMenuItem.MenuId}, OptionIndex {gMenuItem.OptionId} has non-existing or incompatible OptionBroadcastTextId {gMenuItem.OptionBroadcastTextId}, ignoring."); Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for MenuId {gMenuItem.MenuID}, OptionIndex {gMenuItem.OrderIndex} has non-existing or incompatible OptionBroadcastTextId {gMenuItem.OptionBroadcastTextId}, ignoring.");
gMenuItem.OptionBroadcastTextId = 0; gMenuItem.OptionBroadcastTextId = 0;
} }
} }
if (gMenuItem.Language != 0 && !CliDB.LanguagesStorage.ContainsKey(gMenuItem.Language)) if (gMenuItem.Language != 0 && !CliDB.LanguagesStorage.ContainsKey(gMenuItem.Language))
{ {
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} use non-existing Language {gMenuItem.Language}, ignoring"); Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuID}, id {gMenuItem.OrderIndex} use non-existing Language {gMenuItem.Language}, ignoring");
gMenuItem.Language = 0; gMenuItem.Language = 0;
} }
if (gMenuItem.ActionMenuId != 0 && gMenuItem.OptionNpc != GossipOptionNpc.None) if (gMenuItem.ActionMenuID != 0 && gMenuItem.OptionNpc != GossipOptionNpc.None)
{ {
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} can not use ActionMenuID for GossipOptionNpc different from GossipOptionNpc.None, ignoring"); Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuID}, id {gMenuItem.OrderIndex} can not use ActionMenuID for GossipOptionNpc different from GossipOptionNpc.None, ignoring");
gMenuItem.ActionMenuId = 0; gMenuItem.ActionMenuID = 0;
} }
if (gMenuItem.ActionPoiId != 0) if (gMenuItem.ActionPoiID != 0)
{ {
if (gMenuItem.OptionNpc != GossipOptionNpc.None) if (gMenuItem.OptionNpc != GossipOptionNpc.None)
{ {
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} can not use ActionPoiID for GossipOptionNpc different from GossipOptionNpc.None, ignoring"); Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuID}, id {gMenuItem.OrderIndex} can not use ActionPoiID for GossipOptionNpc different from GossipOptionNpc.None, ignoring");
gMenuItem.ActionPoiId = 0; gMenuItem.ActionPoiID = 0;
} }
else if (GetPointOfInterest(gMenuItem.ActionPoiId) == null) else if (GetPointOfInterest(gMenuItem.ActionPoiID) == null)
{ {
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuId}, id {gMenuItem.OptionId} use non-existing ActionPoiID {gMenuItem.ActionPoiId}, ignoring"); Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuID}, id {gMenuItem.OrderIndex} use non-existing ActionPoiID {gMenuItem.ActionPoiID}, ignoring");
gMenuItem.ActionPoiId = 0; gMenuItem.ActionPoiID = 0;
} }
} }
if (gMenuItem.GossipNpcOptionID.HasValue)
{
if (!CliDB.GossipNPCOptionStorage.ContainsKey(gMenuItem.GossipNpcOptionID.Value))
{
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuID}, id {gMenuItem.OrderIndex} use non-existing GossipNPCOption {gMenuItem.GossipNpcOptionID}, ignoring");
gMenuItem.GossipNpcOptionID = null;
}
}
else
{
uint npcOptionId = optionToNpcOption.LookupByKey(gMenuItem.GossipOptionID);
if (npcOptionId != 0)
gMenuItem.GossipNpcOptionID = (int)npcOptionId;
}
if (gMenuItem.BoxBroadcastTextId != 0) if (gMenuItem.BoxBroadcastTextId != 0)
{ {
if (!CliDB.BroadcastTextStorage.ContainsKey(gMenuItem.BoxBroadcastTextId)) if (!CliDB.BroadcastTextStorage.ContainsKey(gMenuItem.BoxBroadcastTextId))
{ {
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for MenuId {gMenuItem.MenuId}, OptionIndex {gMenuItem.OptionId} has non-existing or incompatible BoxBroadcastTextId {gMenuItem.BoxBroadcastTextId}, ignoring."); Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for MenuId {gMenuItem.MenuID}, OptionIndex {gMenuItem.OrderIndex} has non-existing or incompatible BoxBroadcastTextId {gMenuItem.BoxBroadcastTextId}, ignoring.");
gMenuItem.BoxBroadcastTextId = 0; gMenuItem.BoxBroadcastTextId = 0;
} }
} }
gossipMenuItemsStorage.Add(gMenuItem.MenuId, gMenuItem); if (gMenuItem.SpellID.HasValue)
{
if (!Global.SpellMgr.HasSpellInfo((uint)gMenuItem.SpellID.Value, Difficulty.None))
{
Log.outError(LogFilter.Sql, $"Table `gossip_menu_option` for menu {gMenuItem.MenuID}, id {gMenuItem.OrderIndex} use non-existing Spell {gMenuItem.SpellID}, ignoring");
gMenuItem.SpellID = null;
}
}
gossipMenuItemsStorage.Add(gMenuItem.MenuID, gMenuItem);
} while (result.NextRow()); } while (result.NextRow());
Log.outInfo(LogFilter.ServerLoading, $"Loaded {gossipMenuItemsStorage.Count} gossip_menu_option entries in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); Log.outInfo(LogFilter.ServerLoading, $"Loaded {gossipMenuItemsStorage.Count} gossip_menu_option entries in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
@@ -700,42 +752,6 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, $"Loaded {_gossipMenuAddonStorage.Count} gossip_menu_addon IDs in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); Log.outInfo(LogFilter.ServerLoading, $"Loaded {_gossipMenuAddonStorage.Count} gossip_menu_addon IDs in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
} }
public void LoadGossipMenuItemAddon()
{
uint oldMSTime = Time.GetMSTime();
_gossipMenuItemAddonStorage.Clear();
// 0 1 2
SQLResult result = DB.World.Query("SELECT MenuID, OptionId, GarrTalentTreeID FROM gossip_menu_option_addon");
if (result.IsEmpty())
{
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 gossip_menu_option_addon IDs. DB table `gossip_menu_option_addon` is empty!");
return;
}
do
{
uint menuId = result.Read<uint>(0);
uint optionId = result.Read<uint>(1);
GossipMenuItemAddon addon = new();
if (!result.IsNull(2))
{
addon.GarrTalentTreeID = result.Read<int>(2);
if (!CliDB.GarrTalentTreeStorage.ContainsKey(addon.GarrTalentTreeID.Value))
{
Log.outError(LogFilter.Sql, $"Table gossip_menu_option_addon: MenuID {menuId} OptionID {optionId} is using non-existing GarrTalentTree {addon.GarrTalentTreeID.Value}");
addon.GarrTalentTreeID = null;
}
}
_gossipMenuItemAddonStorage[Tuple.Create(menuId, optionId)] = addon;
} while (result.NextRow());
Log.outInfo(LogFilter.ServerLoading, $"Loaded {_gossipMenuItemAddonStorage.Count} gossip_menu_option_addon IDs in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
}
public void LoadPointsOfInterest() public void LoadPointsOfInterest()
{ {
@@ -791,10 +807,6 @@ namespace Game
{ {
return _gossipMenuAddonStorage.LookupByKey(menuId); return _gossipMenuAddonStorage.LookupByKey(menuId);
} }
public GossipMenuItemAddon GetGossipMenuItemAddon(uint menuId, uint optionId)
{
return _gossipMenuItemAddonStorage.LookupByKey(Tuple.Create(menuId, optionId));
}
public PointOfInterest GetPointOfInterest(uint id) public PointOfInterest GetPointOfInterest(uint id)
{ {
return pointsOfInterestStorage.LookupByKey(id); return pointsOfInterestStorage.LookupByKey(id);
@@ -3392,7 +3404,7 @@ namespace Game
var gossipMenuItems = GetGossipMenuItemsMapBounds(gossipMenuId); var gossipMenuItems = GetGossipMenuItemsMapBounds(gossipMenuId);
var gossipOptionItr = gossipMenuItems.Find(entry => var gossipOptionItr = gossipMenuItems.Find(entry =>
{ {
return entry.OptionId == gossipOptionIndex; return entry.OrderIndex == gossipOptionIndex;
}); });
if (gossipOptionItr == null) if (gossipOptionItr == null)
@@ -4999,6 +5011,12 @@ namespace Game
0.00f, // INVTYPE_RANGEDRIGHT 0.00f, // INVTYPE_RANGEDRIGHT
0.00f, // INVTYPE_QUIVER 0.00f, // INVTYPE_QUIVER
0.00f, // INVTYPE_RELIC 0.00f, // INVTYPE_RELIC
0.00f, // INVTYPE_PROFESSION_TOOL
0.00f, // INVTYPE_PROFESSION_GEAR
0.00f, // INVTYPE_EQUIPABLE_SPELL_OFFENSIVE
0.00f, // INVTYPE_EQUIPABLE_SPELL_UTILITY
0.00f, // INVTYPE_EQUIPABLE_SPELL_DEFENSIVE
0.00f, // INVTYPE_EQUIPABLE_SPELL_MOBILITY
}; };
static float[] weaponMultipliers = new float[] static float[] weaponMultipliers = new float[]
@@ -5944,9 +5962,6 @@ namespace Game
//Player //Player
public void LoadPlayerInfo() public void LoadPlayerInfo()
{ {
for (uint race = 0; race < (int)Race.Max; ++race)
_playerInfo[race] = new PlayerInfo[(int)Class.Max];
var time = Time.GetMSTime(); var time = Time.GetMSTime();
// Load playercreate // Load playercreate
{ {
@@ -6059,7 +6074,7 @@ namespace Game
Log.outError(LogFilter.Sql, $"Invalid NPE intro scene id {introSceneId} for class {currentclass} race {currentrace} pair in `playercreateinfo` table, ignoring."); Log.outError(LogFilter.Sql, $"Invalid NPE intro scene id {introSceneId} for class {currentclass} race {currentrace} pair in `playercreateinfo` table, ignoring.");
} }
_playerInfo[currentrace][currentclass] = info; _playerInfo[Tuple.Create((Race)currentrace, (Class)currentclass)] = info;
++count; ++count;
} while (result.NextRow()); } while (result.NextRow());
@@ -6092,9 +6107,11 @@ namespace Game
if (!characterLoadout.RaceMask.HasAnyFlag(SharedConst.GetMaskForRace(raceIndex))) if (!characterLoadout.RaceMask.HasAnyFlag(SharedConst.GetMaskForRace(raceIndex)))
continue; continue;
PlayerInfo playerInfo = _playerInfo[(int)raceIndex][characterLoadout.ChrClassID]; var playerInfo = _playerInfo.LookupByKey(Tuple.Create((Race)raceIndex, (Class)characterLoadout.ChrClassID));
if (playerInfo != null) if (playerInfo != null)
{ {
playerInfo.itemContext = (ItemContext)characterLoadout.ItemContext;
foreach (ItemTemplate itemTemplate in items) foreach (ItemTemplate itemTemplate in items)
{ {
// BuyCount by default // BuyCount by default
@@ -6200,11 +6217,11 @@ namespace Game
{ {
if (rcInfo.RaceMask == -1 || Convert.ToBoolean(SharedConst.GetMaskForRace(raceIndex) & rcInfo.RaceMask)) if (rcInfo.RaceMask == -1 || Convert.ToBoolean(SharedConst.GetMaskForRace(raceIndex) & rcInfo.RaceMask))
{ {
for (int classIndex = (int)Class.Warrior; classIndex < (int)Class.Max; ++classIndex) for (Class classIndex = Class.Warrior; classIndex < Class.Max; ++classIndex)
{ {
if (rcInfo.ClassMask == -1 || Convert.ToBoolean((1 << (classIndex - 1)) & rcInfo.ClassMask)) if (rcInfo.ClassMask == -1 || Convert.ToBoolean((1 << ((int)classIndex - 1)) & rcInfo.ClassMask))
{ {
PlayerInfo info = _playerInfo[(int)raceIndex][classIndex]; PlayerInfo info = _playerInfo.LookupByKey(Tuple.Create(raceIndex, classIndex));
if (info != null) if (info != null)
info.skills.Add(rcInfo); info.skills.Add(rcInfo);
} }
@@ -6251,14 +6268,14 @@ namespace Game
{ {
if (raceMask == 0 || Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(raceIndex) & raceMask)) if (raceMask == 0 || Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(raceIndex) & raceMask))
{ {
for (int classIndex = (int)Class.Warrior; classIndex < (int)Class.Max; ++classIndex) for (Class classIndex = Class.Warrior; classIndex < Class.Max; ++classIndex)
{ {
if (classMask == 0 || Convert.ToBoolean((1 << (classIndex - 1)) & classMask)) if (classMask == 0 || Convert.ToBoolean((1 << ((int)classIndex - 1)) & classMask))
{ {
PlayerInfo info = _playerInfo[(int)raceIndex][classIndex]; PlayerInfo playerInfo = _playerInfo.LookupByKey(Tuple.Create(raceIndex, classIndex));
if (info != null) if (playerInfo != null)
{ {
info.customSpells.Add(spellId); playerInfo.customSpells.Add(spellId);
++count; ++count;
} }
// We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them. // We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them.
@@ -6316,11 +6333,11 @@ namespace Game
{ {
if (raceMask == 0 || Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(raceIndex) & raceMask)) if (raceMask == 0 || Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(raceIndex) & raceMask))
{ {
for (int classIndex = (int)Class.Warrior; classIndex < (int)Class.Max; ++classIndex) for (Class classIndex = Class.Warrior; classIndex < Class.Max; ++classIndex)
{ {
if (classMask == 0 || Convert.ToBoolean((1 << (classIndex - 1)) & classMask)) if (classMask == 0 || Convert.ToBoolean((1 << ((int)classIndex - 1)) & classMask))
{ {
PlayerInfo info = _playerInfo[(int)raceIndex][classIndex]; PlayerInfo info = _playerInfo.LookupByKey(Tuple.Create(raceIndex, classIndex));
if (info != null) if (info != null)
{ {
info.castSpells[playerCreateMode].Add(spellId); info.castSpells[playerCreateMode].Add(spellId);
@@ -6350,20 +6367,20 @@ namespace Game
uint count = 0; uint count = 0;
do do
{ {
uint currentrace = result.Read<uint>(0); Race currentrace = (Race)result.Read<uint>(0);
if (currentrace >= (int)Race.Max) if (currentrace >= Race.Max)
{ {
Log.outError(LogFilter.Sql, "Wrong race {0} in `playercreateinfo_action` table, ignoring.", currentrace); Log.outError(LogFilter.Sql, "Wrong race {0} in `playercreateinfo_action` table, ignoring.", currentrace);
continue; continue;
} }
uint currentclass = result.Read<uint>(1); Class currentclass = (Class)result.Read<uint>(1);
if (currentclass >= (int)Class.Max) if (currentclass >= Class.Max)
{ {
Log.outError(LogFilter.Sql, "Wrong class {0} in `playercreateinfo_action` table, ignoring.", currentclass); Log.outError(LogFilter.Sql, "Wrong class {0} in `playercreateinfo_action` table, ignoring.", currentclass);
continue; continue;
} }
PlayerInfo info = _playerInfo[currentrace][currentclass]; PlayerInfo info = _playerInfo.LookupByKey(Tuple.Create(currentrace, currentclass));
if (info != null) if (info != null)
info.action.Add(new PlayerCreateInfoAction(result.Read<byte>(2), result.Read<uint>(3), result.Read<byte>(4))); info.action.Add(new PlayerCreateInfoAction(result.Read<byte>(2), result.Read<uint>(3), result.Read<byte>(4)));
@@ -6381,7 +6398,6 @@ namespace Game
for (var i = 0; i < (int)Race.Max; ++i) for (var i = 0; i < (int)Race.Max; ++i)
raceStatModifiers[i] = new short[(int)Stats.Max]; raceStatModifiers[i] = new short[(int)Stats.Max];
// 0 1 2 3 4 // 0 1 2 3 4
SQLResult result = DB.World.Query("SELECT race, str, agi, sta, inte FROM player_racestats"); SQLResult result = DB.World.Query("SELECT race, str, agi, sta, inte FROM player_racestats");
if (result.IsEmpty()) if (result.IsEmpty())
@@ -6393,15 +6409,15 @@ namespace Game
do do
{ {
uint currentrace = result.Read<uint>(0); Race currentrace = (Race)result.Read<uint>(0);
if (currentrace >= (int)Race.Max) if (currentrace >= Race.Max)
{ {
Log.outError(LogFilter.Sql, $"Wrong race {currentrace} in `player_racestats` table, ignoring."); Log.outError(LogFilter.Sql, $"Wrong race {currentrace} in `player_racestats` table, ignoring.");
continue; continue;
} }
for (int i = 0; i < (int)Stats.Max; ++i) for (int i = 0; i < (int)Stats.Max; ++i)
raceStatModifiers[currentrace][i] = result.Read<short>(i + 1); raceStatModifiers[(int)currentrace][i] = result.Read<short>(i + 1);
} while (result.NextRow()); } while (result.NextRow());
@@ -6418,8 +6434,8 @@ namespace Game
do do
{ {
uint currentclass = result.Read<byte>(0); Class currentclass = (Class)result.Read<byte>(0);
if (currentclass >= (int)Class.Max) if (currentclass >= Class.Max)
{ {
Log.outError(LogFilter.Sql, "Wrong class {0} in `player_classlevelstats` table, ignoring.", currentclass); Log.outError(LogFilter.Sql, "Wrong class {0} in `player_classlevelstats` table, ignoring.", currentclass);
continue; continue;
@@ -6438,14 +6454,14 @@ namespace Game
for (var race = 0; race < raceStatModifiers.Length; ++race) for (var race = 0; race < raceStatModifiers.Length; ++race)
{ {
var pInfo = _playerInfo[race][currentclass]; var playerInfo = _playerInfo.LookupByKey(Tuple.Create((Race)race, currentclass));
if (pInfo == null) if (playerInfo == null)
continue; continue;
if (pInfo.levelInfo[currentlevel - 1] == null) if (playerInfo.levelInfo[currentlevel - 1] == null)
pInfo.levelInfo[currentlevel - 1] = new PlayerLevelInfo(); playerInfo.levelInfo[currentlevel - 1] = new PlayerLevelInfo();
var levelinfo = pInfo.levelInfo[currentlevel - 1]; var levelinfo = playerInfo.levelInfo[currentlevel - 1];
for (var i = 0; i < (int)Stats.Max; i++) for (var i = 0; i < (int)Stats.Max; i++)
levelinfo.stats[i] = (ushort)(result.Read<ushort>(i + 2) + raceStatModifiers[race][i]); levelinfo.stats[i] = (ushort)(result.Read<ushort>(i + 2) + raceStatModifiers[race][i]);
@@ -6455,38 +6471,38 @@ namespace Game
} while (result.NextRow()); } while (result.NextRow());
// Fill gaps and check integrity // Fill gaps and check integrity
for (uint race = 0; race < (int)Race.Max; ++race) for (Race race = 0; race < Race.Max; ++race)
{ {
// skip non existed races // skip non existed races
if (!CliDB.ChrRacesStorage.ContainsKey(race) || _playerInfo[race][0] == null) if (!CliDB.ChrRacesStorage.ContainsKey(race))
continue; continue;
for (uint _class = 0; _class < (int)Class.Max; ++_class) for (Class _class = 0; _class < Class.Max; ++_class)
{ {
// skip non existed classes // skip non existed classes
if (CliDB.ChrClassesStorage.LookupByKey(_class) == null || _playerInfo[race][_class] == null) if (CliDB.ChrClassesStorage.LookupByKey(_class) == null)
continue; continue;
PlayerInfo pInfo = _playerInfo[race][_class]; var playerInfo = _playerInfo.LookupByKey(Tuple.Create(race, _class));
if (pInfo == null) if (playerInfo == null)
continue; continue;
// skip expansion races if not playing with expansion // skip expansion races if not playing with expansion
if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.BurningCrusade && (race == (int)Race.BloodElf || race == (int)Race.Draenei)) if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.BurningCrusade && (race == Race.BloodElf || race == Race.Draenei))
continue; continue;
// skip expansion classes if not playing with expansion // skip expansion classes if not playing with expansion
if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.WrathOfTheLichKing && _class == (int)Class.Deathknight) if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.WrathOfTheLichKing && _class == Class.Deathknight)
continue; continue;
if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.MistsOfPandaria && (race == (int)Race.PandarenNeutral || race == (int)Race.PandarenHorde || race == (int)Race.PandarenAlliance)) if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.MistsOfPandaria && (race == Race.PandarenNeutral || race == Race.PandarenHorde || race == Race.PandarenAlliance))
continue; continue;
if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.Legion && _class == (int)Class.DemonHunter) if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.Legion && _class == Class.DemonHunter)
continue; continue;
// fatal error if no level 1 data // fatal error if no level 1 data
if (pInfo.levelInfo == null || pInfo.levelInfo[0] == null) if (playerInfo.levelInfo == null || playerInfo.levelInfo[0].stats[0] == 0)
{ {
Log.outError(LogFilter.Sql, "Race {0} Class {1} Level 1 does not have stats data!", race, _class); Log.outError(LogFilter.Sql, "Race {0} Class {1} Level 1 does not have stats data!", race, _class);
Global.WorldMgr.StopNow(); Global.WorldMgr.StopNow();
@@ -6496,10 +6512,10 @@ namespace Game
// fill level gaps // fill level gaps
for (var level = 1; level < WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel); ++level) for (var level = 1; level < WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel); ++level)
{ {
if (pInfo.levelInfo[level] == null) if (playerInfo.levelInfo[level].stats[0] == 0)
{ {
Log.outError(LogFilter.Sql, "Race {0} Class {1} Level {2} does not have stats data. Using stats data of level {3}.", race, _class, level + 1, level); Log.outError(LogFilter.Sql, "Race {0} Class {1} Level {2} does not have stats data. Using stats data of level {3}.", race, _class, level + 1, level);
pInfo.levelInfo[level] = pInfo.levelInfo[level - 1]; playerInfo.levelInfo[level] = playerInfo.levelInfo[level - 1];
} }
} }
} }
@@ -6561,18 +6577,18 @@ namespace Game
} }
void PlayerCreateInfoAddItemHelper(uint race, uint class_, uint itemId, int count) void PlayerCreateInfoAddItemHelper(uint race, uint class_, uint itemId, int count)
{ {
if (_playerInfo[race][class_] == null) var playerInfo = _playerInfo.LookupByKey(Tuple.Create((Race)race, (Class)class_));
if (playerInfo == null)
return; return;
if (count > 0) if (count > 0)
_playerInfo[race][class_].item.Add(new PlayerCreateInfoItem(itemId, (uint)count)); playerInfo.item.Add(new PlayerCreateInfoItem(itemId, (uint)count));
else else
{ {
if (count < -1) if (count < -1)
Log.outError(LogFilter.Sql, "Invalid count {0} specified on item {1} be removed from original player create info (use -1)!", count, itemId); Log.outError(LogFilter.Sql, "Invalid count {0} specified on item {1} be removed from original player create info (use -1)!", count, itemId);
var items = _playerInfo[race][class_].item; playerInfo.item.RemoveAll(item => item.item_id == itemId);
items.RemoveAll(item => { return item.item_id == itemId; });
} }
} }
@@ -6584,7 +6600,7 @@ namespace Game
if (classId >= Class.Max) if (classId >= Class.Max)
return null; return null;
var info = _playerInfo[(int)raceId][(int)classId]; var info = _playerInfo.LookupByKey(Tuple.Create(raceId, classId));
if (info == null) if (info == null)
return null; return null;
@@ -6613,7 +6629,7 @@ namespace Game
if (level < 1 || race >= Race.Max || _class >= Class.Max) if (level < 1 || race >= Race.Max || _class >= Class.Max)
return null; return null;
PlayerInfo pInfo = _playerInfo[(int)race][(int)_class]; PlayerInfo pInfo = _playerInfo.LookupByKey(Tuple.Create(race, _class));
if (pInfo == null) if (pInfo == null)
return null; return null;
@@ -6626,7 +6642,7 @@ namespace Game
PlayerLevelInfo BuildPlayerLevelInfo(Race race, Class _class, uint level) PlayerLevelInfo BuildPlayerLevelInfo(Race race, Class _class, uint level)
{ {
// base data (last known level) // base data (last known level)
var info = _playerInfo[(byte)race][(int)_class].levelInfo[WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel) - 1]; var info = _playerInfo.LookupByKey(Tuple.Create(race, _class)).levelInfo[WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel) - 1];
for (int lvl = WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel) - 1; lvl < level; ++lvl) for (int lvl = WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel) - 1; lvl < level; ++lvl)
{ {
@@ -10911,7 +10927,6 @@ namespace Game
MultiMap<uint, GossipMenus> gossipMenusStorage = new(); MultiMap<uint, GossipMenus> gossipMenusStorage = new();
MultiMap<uint, GossipMenuItems> gossipMenuItemsStorage = new(); MultiMap<uint, GossipMenuItems> gossipMenuItemsStorage = new();
Dictionary<uint, GossipMenuAddon> _gossipMenuAddonStorage = new(); Dictionary<uint, GossipMenuAddon> _gossipMenuAddonStorage = new();
Dictionary<Tuple<uint, uint>, GossipMenuItemAddon> _gossipMenuItemAddonStorage = new();
Dictionary<uint, PointOfInterest> pointsOfInterestStorage = new(); Dictionary<uint, PointOfInterest> pointsOfInterestStorage = new();
//Creature //Creature
@@ -10946,7 +10961,7 @@ namespace Game
Dictionary<uint, ItemTemplate> ItemTemplateStorage = new(); Dictionary<uint, ItemTemplate> ItemTemplateStorage = new();
//Player //Player
PlayerInfo[][] _playerInfo = new PlayerInfo[(int)Race.Max][]; Dictionary<Tuple<Race, Class>, PlayerInfo> _playerInfo = new();
//Faction Change //Faction Change
public Dictionary<uint, uint> FactionChangeAchievements = new(); public Dictionary<uint, uint> FactionChangeAchievements = new();
@@ -12007,6 +12022,7 @@ namespace Game
public byte ClassID; public byte ClassID;
public byte ActiveExpansionLevel; public byte ActiveExpansionLevel;
public byte AccountExpansionLevel; public byte AccountExpansionLevel;
public byte MinActiveExpansionLevel;
} }
public class RaceClassAvailability public class RaceClassAvailability
@@ -86,6 +86,7 @@ namespace Game
SetTimeZoneInformation packet = new(); SetTimeZoneInformation packet = new();
packet.ServerTimeTZ = "Europe/Paris"; packet.ServerTimeTZ = "Europe/Paris";
packet.GameTimeTZ = "Europe/Paris"; packet.GameTimeTZ = "Europe/Paris";
packet.ServerRegionalTZ = "Europe/Paris";
SendPacket(packet);//enabled it SendPacket(packet);//enabled it
} }
+5 -1
View File
@@ -246,7 +246,11 @@ namespace Game
public void SendAzeriteRespecNPC(ObjectGuid npc) public void SendAzeriteRespecNPC(ObjectGuid npc)
{ {
SendPacket(new AzeriteRespecNPC(npc)); NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = npc;
npcInteraction.InteractionType = PlayerInteractionType.AzeriteRespec;
npcInteraction.Success = true;
SendPacket(npcInteraction);
} }
} }
} }
+5 -4
View File
@@ -297,10 +297,11 @@ namespace Game
public void SendShowBank(ObjectGuid guid) public void SendShowBank(ObjectGuid guid)
{ {
m_currentBankerGUID = guid; NPCInteractionOpenResult npcInteraction = new();
ShowBank packet = new(); npcInteraction.Npc = guid;
packet.Guid = guid; npcInteraction.InteractionType = PlayerInteractionType.Banker;
SendPacket(packet); npcInteraction.Success = true;
SendPacket(npcInteraction);
} }
} }
} }
+5 -4
View File
@@ -45,10 +45,11 @@ namespace Game
void SendBlackMarketOpenResult(ObjectGuid guid, Creature auctioneer) void SendBlackMarketOpenResult(ObjectGuid guid, Creature auctioneer)
{ {
BlackMarketOpenResult packet = new(); NPCInteractionOpenResult npcInteraction = new();
packet.Guid = guid; npcInteraction.Npc = guid;
packet.Enable = Global.BlackMarketMgr.IsEnabled(); npcInteraction.InteractionType = PlayerInteractionType.BlackMarketAuctioneer;
SendPacket(packet); npcInteraction.Success = Global.BlackMarketMgr.IsEnabled();
SendPacket(npcInteraction);
} }
[WorldPacketHandler(ClientOpcodes.BlackMarketRequestItems)] [WorldPacketHandler(ClientOpcodes.BlackMarketRequestItems)]
+81 -19
View File
@@ -192,6 +192,15 @@ namespace Game
if (req.ItemModifiedAppearanceID != 0 && !GetCollectionMgr().HasItemAppearance(req.ItemModifiedAppearanceID).PermAppearance) if (req.ItemModifiedAppearanceID != 0 && !GetCollectionMgr().HasItemAppearance(req.ItemModifiedAppearanceID).PermAppearance)
return false; return false;
if (req.QuestID != 0)
{
if (!_player)
return false;
if (!_player.IsQuestRewarded((uint)req.QuestID))
return false;
}
if (checkRequiredDependentChoices) if (checkRequiredDependentChoices)
{ {
var requiredChoices = Global.DB2Mgr.GetRequiredCustomizationChoices(req.Id); var requiredChoices = Global.DB2Mgr.GetRequiredCustomizationChoices(req.Id);
@@ -318,14 +327,14 @@ namespace Game
RaceUnlockRequirement raceExpansionRequirement = Global.ObjectMgr.GetRaceUnlockRequirement(charCreate.CreateInfo.RaceId); RaceUnlockRequirement raceExpansionRequirement = Global.ObjectMgr.GetRaceUnlockRequirement(charCreate.CreateInfo.RaceId);
if (raceExpansionRequirement == null) if (raceExpansionRequirement == null)
{ {
Log.outError(LogFilter.Player, $"Account {GetAccountId()} tried to create character with unavailable race {charCreate.CreateInfo.RaceId}"); Log.outError(LogFilter.Cheat, $"Account {GetAccountId()} tried to create character with unavailable race {charCreate.CreateInfo.RaceId}");
SendCharCreate(ResponseCodes.AccountCreateFailed); SendCharCreate(ResponseCodes.CharCreateFailed);
return; return;
} }
if (raceExpansionRequirement.Expansion > (byte)GetAccountExpansion()) if (raceExpansionRequirement.Expansion > (byte)GetAccountExpansion())
{ {
Log.outError(LogFilter.Player, $"Expansion {GetAccountExpansion()} account:[{GetAccountId()}] tried to Create character with expansion {raceExpansionRequirement.Expansion} race ({charCreate.CreateInfo.RaceId})"); Log.outError(LogFilter.Cheat, $"Expansion {GetAccountExpansion()} account:[{GetAccountId()}] tried to Create character with expansion {raceExpansionRequirement.Expansion} race ({charCreate.CreateInfo.RaceId})");
SendCharCreate(ResponseCodes.CharCreateExpansion); SendCharCreate(ResponseCodes.CharCreateExpansion);
return; return;
} }
@@ -338,18 +347,33 @@ namespace Game
// return; // return;
//} //}
// prevent character creating Expansion class without Expansion account // prevent character creating Expansion race without Expansion account
ClassAvailability classExpansionRequirement = Global.ObjectMgr.GetClassExpansionRequirement(charCreate.CreateInfo.RaceId, charCreate.CreateInfo.ClassId); ClassAvailability raceClassExpansionRequirement = Global.ObjectMgr.GetClassExpansionRequirement(charCreate.CreateInfo.RaceId, charCreate.CreateInfo.ClassId);
if (classExpansionRequirement == null) if (raceClassExpansionRequirement != null)
{ {
Log.outError(LogFilter.Player, $"Expansion {GetAccountExpansion()} account:[{GetAccountId()}] tried to Create character for race/class combination that is missing requirements in db ({charCreate.CreateInfo.RaceId}/{charCreate.CreateInfo.ClassId})"); if (raceClassExpansionRequirement.ActiveExpansionLevel > (byte)GetExpansion() || raceClassExpansionRequirement.AccountExpansionLevel > (byte)GetAccountExpansion())
SendCharCreate(ResponseCodes.CharCreateExpansionClass); {
return; Log.outError(LogFilter.Cheat, $"Account:[{GetAccountId()}] tried to create character with race/class {charCreate.CreateInfo.RaceId}/{charCreate.CreateInfo.ClassId} without required expansion " +
$"(had {GetExpansion()}/{GetAccountExpansion()}, required {raceClassExpansionRequirement.ActiveExpansionLevel}/{raceClassExpansionRequirement.AccountExpansionLevel})");
SendCharCreate(ResponseCodes.CharCreateExpansionClass);
return;
}
} }
else
if (classExpansionRequirement.ActiveExpansionLevel > (int)GetExpansion() || classExpansionRequirement.AccountExpansionLevel > (int)GetAccountExpansion())
{ {
Log.outError(LogFilter.Player, $"Account:[{GetAccountId()}] tried to create character with race/class {charCreate.CreateInfo.RaceId}/{charCreate.CreateInfo.ClassId} without required expansion(had {GetExpansion()}/{GetAccountExpansion()}, required {classExpansionRequirement.ActiveExpansionLevel}/{classExpansionRequirement.AccountExpansionLevel})"); ClassAvailability classExpansionRequirement = Global.ObjectMgr.GetClassExpansionRequirementFallback((byte)charCreate.CreateInfo.ClassId);
if (classExpansionRequirement != null)
{
if (classExpansionRequirement.MinActiveExpansionLevel > (byte)GetExpansion() || classExpansionRequirement.AccountExpansionLevel > (byte)GetAccountExpansion())
{
Log.outError(LogFilter.Cheat, $"Account:[{GetAccountId()}] tried to create character with race/class {charCreate.CreateInfo.RaceId}/{charCreate.CreateInfo.ClassId} without required expansion " +
$"(had {GetExpansion()}/{GetAccountExpansion()}, required {classExpansionRequirement.ActiveExpansionLevel}/{classExpansionRequirement.AccountExpansionLevel})");
SendCharCreate(ResponseCodes.CharCreateExpansionClass);
return;
}
}
else
Log.outError(LogFilter.Cheat, $"Expansion {GetAccountExpansion()} account:[{GetAccountId()}] tried to Create character for race/class combination that is missing requirements in db ({charCreate.CreateInfo.RaceId}/{charCreate.CreateInfo.ClassId})");
SendCharCreate(ResponseCodes.CharCreateExpansionClass); SendCharCreate(ResponseCodes.CharCreateExpansionClass);
return; return;
} }
@@ -450,9 +474,14 @@ namespace Game
int demonHunterReqLevel = WorldConfig.GetIntValue(WorldCfg.CharacterCreatingMinLevelForDemonHunter); int demonHunterReqLevel = WorldConfig.GetIntValue(WorldCfg.CharacterCreatingMinLevelForDemonHunter);
bool hasDemonHunterReqLevel = demonHunterReqLevel == 0; bool hasDemonHunterReqLevel = demonHunterReqLevel == 0;
uint evokerReqLevel = WorldConfig.GetUIntValue(WorldCfg.CharacterCreatingMinLevelForEvoker);
bool hasEvokerReqLevel = (evokerReqLevel == 0);
bool allowTwoSideAccounts = !Global.WorldMgr.IsPvPRealm() || HasPermission(RBACPermissions.TwoSideCharacterCreation); bool allowTwoSideAccounts = !Global.WorldMgr.IsPvPRealm() || HasPermission(RBACPermissions.TwoSideCharacterCreation);
int skipCinematics = WorldConfig.GetIntValue(WorldCfg.SkipCinematics); int skipCinematics = WorldConfig.GetIntValue(WorldCfg.SkipCinematics);
bool checkDemonHunterReqs = createInfo.ClassId == Class.DemonHunter && !HasPermission(RBACPermissions.SkipCheckCharacterCreationDemonHunter); bool checkClassLevelReqs = (createInfo.ClassId == Class.DemonHunter || createInfo.ClassId == Class.Evoker)
&& !HasPermission(RBACPermissions.SkipCheckCharacterCreationDemonHunter);
int evokerLimit = WorldConfig.GetIntValue(WorldCfg.CharacterCreatingEvokersPerRealm);
bool hasEvokerLimit = evokerLimit != 0;
void finalizeCharacterCreation(SQLResult result1) void finalizeCharacterCreation(SQLResult result1)
{ {
@@ -461,8 +490,9 @@ namespace Game
{ {
Team team = Player.TeamForRace(createInfo.RaceId); Team team = Player.TeamForRace(createInfo.RaceId);
byte accRace = result1.Read<byte>(1); byte accRace = result1.Read<byte>(1);
byte accClass = result1.Read<byte>(2);
if (checkDemonHunterReqs) if (checkClassLevelReqs)
{ {
if (!hasDemonHunterReqLevel) if (!hasDemonHunterReqLevel)
{ {
@@ -470,8 +500,17 @@ namespace Game
if (accLevel >= demonHunterReqLevel) if (accLevel >= demonHunterReqLevel)
hasDemonHunterReqLevel = true; hasDemonHunterReqLevel = true;
} }
if (!hasEvokerReqLevel)
{
byte accLevel = result1.Read<byte>(0);
if (accLevel >= evokerReqLevel)
hasEvokerReqLevel = true;
}
} }
if (accClass == (byte)Class.Evoker)
--evokerLimit;
// need to check team only for first character // need to check team only for first character
// @todo what to if account already has characters of both races? // @todo what to if account already has characters of both races?
if (!allowTwoSideAccounts) if (!allowTwoSideAccounts)
@@ -489,17 +528,18 @@ namespace Game
// search same race for cinematic or same class if need // search same race for cinematic or same class if need
// @todo check if cinematic already shown? (already logged in?; cinematic field) // @todo check if cinematic already shown? (already logged in?; cinematic field)
while ((skipCinematics == 1 && !haveSameRace) || createInfo.ClassId == Class.DemonHunter) while ((skipCinematics == 1 && !haveSameRace) || createInfo.ClassId == Class.DemonHunter || createInfo.ClassId == Class.Evoker)
{ {
if (!result1.NextRow()) if (!result1.NextRow())
break; break;
accRace = result1.Read<byte>(1); accRace = result1.Read<byte>(1);
accClass = result1.Read<byte>(2);
if (!haveSameRace) if (!haveSameRace)
haveSameRace = createInfo.RaceId == (Race)accRace; haveSameRace = createInfo.RaceId == (Race)accRace;
if (checkDemonHunterReqs) if (checkClassLevelReqs)
{ {
if (!hasDemonHunterReqLevel) if (!hasDemonHunterReqLevel)
{ {
@@ -507,11 +547,33 @@ namespace Game
if (acc_level >= demonHunterReqLevel) if (acc_level >= demonHunterReqLevel)
hasDemonHunterReqLevel = true; hasDemonHunterReqLevel = true;
} }
if (!hasEvokerReqLevel)
{
byte accLevel = result1.Read<byte>(0);
if (accLevel >= evokerReqLevel)
hasEvokerReqLevel = true;
}
} }
if (accClass == (byte)Class.Evoker)
--evokerLimit;
} }
} }
if (checkDemonHunterReqs && !hasDemonHunterReqLevel) if (checkClassLevelReqs)
{
if (!hasDemonHunterReqLevel)
{
SendCharCreate(ResponseCodes.CharCreateNewPlayer);
return;
}
if (!hasEvokerReqLevel)
{
SendCharCreate(ResponseCodes.CharCreateDracthyrLevelRequirement);
return;
}
}
if (createInfo.ClassId == Class.Evoker && hasEvokerLimit && evokerLimit < 1)
{ {
SendCharCreate(ResponseCodes.CharCreateNewPlayer); SendCharCreate(ResponseCodes.CharCreateNewPlayer);
return; return;
@@ -520,7 +582,7 @@ namespace Game
// Check name uniqueness in the same step as saving to database // Check name uniqueness in the same step as saving to database
if (Global.CharacterCacheStorage.GetCharacterCacheByName(createInfo.Name) != null) if (Global.CharacterCacheStorage.GetCharacterCacheByName(createInfo.Name) != null)
{ {
SendCharCreate(ResponseCodes.CharCreateNameInUse); SendCharCreate(ResponseCodes.CharCreateDracthyrDuplicate);
return; return;
} }
@@ -580,7 +642,7 @@ namespace Game
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_CREATE_INFO); stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_CREATE_INFO);
stmt.AddValue(0, GetAccountId()); stmt.AddValue(0, GetAccountId());
stmt.AddValue(1, (skipCinematics == 1 || createInfo.ClassId == Class.DemonHunter) ? 1200 : 1); // 200 (max chars per realm) + 1000 (max deleted chars per realm) stmt.AddValue(1, (skipCinematics == 1 || createInfo.ClassId == Class.DemonHunter || createInfo.ClassId == Class.Evoker) ? 1200 : 1); // 200 (max chars per realm) + 1000 (max deleted chars per realm)
queryCallback.WithCallback(finalizeCharacterCreation).SetNextQuery(DB.Characters.AsyncQuery(stmt)); queryCallback.WithCallback(finalizeCharacterCreation).SetNextQuery(DB.Characters.AsyncQuery(stmt));
})); }));
} }
+2 -2
View File
@@ -808,8 +808,8 @@ namespace Game
gems[i] = gem; gems[i] = gem;
gemData[i].ItemId = gem.GetEntry(); gemData[i].ItemId = gem.GetEntry();
gemData[i].Context = (byte)gem.m_itemData.Context; gemData[i].Context = (byte)gem.m_itemData.Context;
for (int b = 0; b < ((List<uint>)gem.m_itemData.BonusListIDs).Count && b < 16; ++b) for (int b = 0; b < gem.GetBonusListIDs().Count && b < 16; ++b)
gemData[i].BonusListIDs[b] = (ushort)((List<uint>)gem.m_itemData.BonusListIDs)[b]; gemData[i].BonusListIDs[b] = (ushort)gem.GetBonusListIDs()[b];
gemProperties[i] = CliDB.GemPropertiesStorage.LookupByKey(gem.GetTemplate().GetGemProperties()); gemProperties[i] = CliDB.GemPropertiesStorage.LookupByKey(gem.GetTemplate().GetGemProperties());
} }
+5 -3
View File
@@ -682,9 +682,11 @@ namespace Game
public void SendShowMailBox(ObjectGuid guid) public void SendShowMailBox(ObjectGuid guid)
{ {
ShowMailbox packet = new(); NPCInteractionOpenResult npcInteraction = new();
packet.PostmasterGUID = guid; npcInteraction.Npc = guid;
SendPacket(packet); npcInteraction.InteractionType = PlayerInteractionType.MailInfo;
npcInteraction.Success = true;
SendPacket(npcInteraction);
} }
} }
} }
+16 -12
View File
@@ -20,6 +20,7 @@ using Framework.Database;
using Game.BattleGrounds; using Game.BattleGrounds;
using Game.DataStorage; using Game.DataStorage;
using Game.Entities; using Game.Entities;
using Game.Misc;
using Game.Networking; using Game.Networking;
using Game.Networking.Packets; using Game.Networking.Packets;
using System; using System;
@@ -48,9 +49,11 @@ namespace Game
public void SendTabardVendorActivate(ObjectGuid guid) public void SendTabardVendorActivate(ObjectGuid guid)
{ {
PlayerTabardVendorActivate packet = new(); NPCInteractionOpenResult npcInteraction = new();
packet.Vendor = guid; npcInteraction.Npc = guid;
SendPacket(packet); npcInteraction.InteractionType = PlayerInteractionType.TabardVendor;
npcInteraction.Success = true;
SendPacket(npcInteraction);
} }
[WorldPacketHandler(ClientOpcodes.TrainerList, Processing = PacketProcessing.Inplace)] [WorldPacketHandler(ClientOpcodes.TrainerList, Processing = PacketProcessing.Inplace)]
@@ -172,7 +175,8 @@ namespace Game
[WorldPacketHandler(ClientOpcodes.GossipSelectOption)] [WorldPacketHandler(ClientOpcodes.GossipSelectOption)]
void HandleGossipSelectOption(GossipSelectOption packet) void HandleGossipSelectOption(GossipSelectOption packet)
{ {
if (GetPlayer().PlayerTalkClass.GetGossipMenu().GetItem(packet.GossipIndex) == null) GossipMenuItem gossipMenuItem = _player.PlayerTalkClass.GetGossipMenu().GetItem(packet.GossipOptionID);
if (gossipMenuItem == null)
return; return;
// Prevent cheating on C# scripted menus // Prevent cheating on C# scripted menus
@@ -224,26 +228,26 @@ namespace Game
{ {
if (unit != null) if (unit != null)
{ {
if (!unit.GetAI().OnGossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode)) if (!unit.GetAI().OnGossipSelectCode(_player, packet.GossipID, gossipMenuItem.OrderIndex, packet.PromotionCode))
GetPlayer().OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); GetPlayer().OnGossipSelect(unit, packet.GossipOptionID, packet.GossipID);
} }
else else
{ {
if (!go.GetAI().OnGossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode)) if (!go.GetAI().OnGossipSelectCode(_player, packet.GossipID, gossipMenuItem.OrderIndex, packet.PromotionCode))
_player.OnGossipSelect(go, packet.GossipIndex, packet.GossipID); _player.OnGossipSelect(go, packet.GossipOptionID, packet.GossipID);
} }
} }
else else
{ {
if (unit != null) if (unit != null)
{ {
if (!unit.GetAI().OnGossipSelect(_player, packet.GossipID, packet.GossipIndex)) if (!unit.GetAI().OnGossipSelect(_player, packet.GossipID, gossipMenuItem.OrderIndex))
GetPlayer().OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); GetPlayer().OnGossipSelect(unit, packet.GossipOptionID, packet.GossipID);
} }
else else
{ {
if (!go.GetAI().OnGossipSelect(_player, packet.GossipID, packet.GossipIndex)) if (!go.GetAI().OnGossipSelect(_player, packet.GossipID, gossipMenuItem.OrderIndex))
GetPlayer().OnGossipSelect(go, packet.GossipIndex, packet.GossipID); GetPlayer().OnGossipSelect(go, packet.GossipOptionID, packet.GossipID);
} }
} }
} }
@@ -342,7 +342,11 @@ namespace Game
public void SendOpenTransmogrifier(ObjectGuid guid) public void SendOpenTransmogrifier(ObjectGuid guid)
{ {
SendPacket(new TransmogrifyNPC(guid)); NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = guid;
npcInteraction.InteractionType = PlayerInteractionType.Transmogrifier;
npcInteraction.Success = true;
SendPacket(npcInteraction);
} }
} }
} }
+1 -1
View File
@@ -157,7 +157,7 @@ namespace Game
VoidStorageItem itemVS = new(Global.ObjectMgr.GenerateVoidStorageItemId(), item.GetEntry(), item.GetCreator(), VoidStorageItem itemVS = new(Global.ObjectMgr.GenerateVoidStorageItemId(), item.GetEntry(), item.GetCreator(),
item.GetItemRandomBonusListId(), item.GetModifier(ItemModifier.TimewalkerLevel), item.GetModifier(ItemModifier.ArtifactKnowledgeLevel), item.GetItemRandomBonusListId(), item.GetModifier(ItemModifier.TimewalkerLevel), item.GetModifier(ItemModifier.ArtifactKnowledgeLevel),
item.GetContext(), item.m_itemData.BonusListIDs); item.GetContext(), item.GetBonusListIDs());
VoidItem voidItem; VoidItem voidItem;
voidItem.Guid = ObjectGuid.Create(HighGuid.Item, itemVS.ItemId); voidItem.Guid = ObjectGuid.Create(HighGuid.Item, itemVS.ItemId);
+6 -16
View File
@@ -370,11 +370,7 @@ namespace Game.Maps
{ {
foreach (uint mapId in transport.MapIds) foreach (uint mapId in transport.MapIds)
Cypher.Assert(!CliDB.MapStorage.LookupByKey(mapId).Instanceable()); Cypher.Assert(!CliDB.MapStorage.LookupByKey(mapId).Instanceable());
transport.InInstance = false;
} }
else
transport.InInstance = CliDB.MapStorage.LookupByKey(transport.MapIds.First()).Instanceable();
transport.TotalPathTime = totalTime; transport.TotalPathTime = totalTime;
} }
@@ -424,6 +420,12 @@ namespace Game.Maps
return null; return null;
} }
if (!tInfo.MapIds.Contains(map.GetId()))
{
Log.outError(LogFilter.Transport, $"Transport {entry} attempted creation on map it has no path for {map.GetId()}!");
return null;
}
Position startingPosition = tInfo.ComputePosition(0, out _, out _); Position startingPosition = tInfo.ComputePosition(0, out _, out _);
if (startingPosition == null) if (startingPosition == null)
{ {
@@ -435,7 +437,6 @@ namespace Game.Maps
Transport trans = new(); Transport trans = new();
// ...at first waypoint // ...at first waypoint
uint mapId = tInfo.PathLegs.First().MapId;
float x = startingPosition.GetPositionX(); float x = startingPosition.GetPositionX();
float y = startingPosition.GetPositionY(); float y = startingPosition.GetPositionY();
float z = startingPosition.GetPositionZ(); float z = startingPosition.GetPositionZ();
@@ -448,16 +449,6 @@ namespace Game.Maps
PhasingHandler.InitDbPhaseShift(trans.GetPhaseShift(), phaseUseFlags, phaseId, phaseGroupId); PhasingHandler.InitDbPhaseShift(trans.GetPhaseShift(), phaseUseFlags, phaseId, phaseGroupId);
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(mapId);
if (mapEntry != null)
{
if (mapEntry.Instanceable() != tInfo.InInstance)
{
Log.outError(LogFilter.Transport, "Transport {0} (name: {1}) attempted creation in instance map (id: {2}) but it is not an instanced transport!", entry, trans.GetName(), mapId);
//return null;
}
}
// use preset map for instances (need to know which instance) // use preset map for instances (need to know which instance)
trans.SetMap(map); trans.SetMap(map);
if (instanceMap != null) if (instanceMap != null)
@@ -536,7 +527,6 @@ namespace Game.Maps
public List<TransportPathEvent> Events = new(); public List<TransportPathEvent> Events = new();
public HashSet<uint> MapIds = new(); public HashSet<uint> MapIds = new();
public bool InInstance;
public Position ComputePosition(uint time, out TransportMovementState moveState, out int legIndex) public Position ComputePosition(uint time, out TransportMovementState moveState, out int legIndex)
{ {
@@ -784,12 +784,12 @@ namespace Game.Networking.Packets
public struct AuctionListFilterSubClass public struct AuctionListFilterSubClass
{ {
public int ItemSubclass; public int ItemSubclass;
public uint InvTypeMask; public ulong InvTypeMask;
public AuctionListFilterSubClass(WorldPacket data) public AuctionListFilterSubClass(WorldPacket data)
{ {
InvTypeMask = data.ReadUInt64();
ItemSubclass = data.ReadInt32(); ItemSubclass = data.ReadInt32();
InvTypeMask = data.ReadUInt32();
} }
} }
@@ -138,6 +138,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt8(classAvailability.ClassID); _worldPacket.WriteUInt8(classAvailability.ClassID);
_worldPacket.WriteUInt8(classAvailability.ActiveExpansionLevel); _worldPacket.WriteUInt8(classAvailability.ActiveExpansionLevel);
_worldPacket.WriteUInt8(classAvailability.AccountExpansionLevel); _worldPacket.WriteUInt8(classAvailability.AccountExpansionLevel);
_worldPacket.WriteUInt8(classAvailability.MinActiveExpansionLevel);
} }
} }
@@ -166,7 +167,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt16(SuccessInfo.NumPlayersAlliance.Value); _worldPacket.WriteUInt16(SuccessInfo.NumPlayersAlliance.Value);
if(SuccessInfo.ExpansionTrialExpiration.HasValue) if(SuccessInfo.ExpansionTrialExpiration.HasValue)
_worldPacket.WriteInt32(SuccessInfo.ExpansionTrialExpiration.Value); _worldPacket.WriteInt64(SuccessInfo.ExpansionTrialExpiration.Value);
foreach (VirtualRealmInfo virtualRealm in SuccessInfo.VirtualRealms) foreach (VirtualRealmInfo virtualRealm in SuccessInfo.VirtualRealms)
virtualRealm.Write(_worldPacket); virtualRealm.Write(_worldPacket);
@@ -220,7 +221,7 @@ namespace Game.Networking.Packets
public bool ForceCharacterTemplate; // forces the client to always use a character template when creating a new character. @see Templates. @todo implement public bool ForceCharacterTemplate; // forces the client to always use a character template when creating a new character. @see Templates. @todo implement
public ushort? NumPlayersHorde; // number of horde players in this realm. @todo implement public ushort? NumPlayersHorde; // number of horde players in this realm. @todo implement
public ushort? NumPlayersAlliance; // number of alliance players in this realm. @todo implement public ushort? NumPlayersAlliance; // number of alliance players in this realm. @todo implement
public int? ExpansionTrialExpiration; // expansion trial expiration unix timestamp public long? ExpansionTrialExpiration; // expansion trial expiration unix timestamp
public struct GameTime public struct GameTime
{ {
@@ -34,25 +34,6 @@ namespace Game.Networking.Packets
public ulong XP; public ulong XP;
} }
class OpenHeartForge : ServerPacket
{
public OpenHeartForge() : base(ServerOpcodes.OpenHeartForge) { }
public override void Write()
{
_worldPacket.WritePackedGuid(ForgeGUID);
}
public ObjectGuid ForgeGUID;
}
class CloseHeartForge : ServerPacket
{
public CloseHeartForge() : base(ServerOpcodes.CloseHeartForge) { }
public override void Write() { }
}
class AzeriteEssenceUnlockMilestone : ClientPacket class AzeriteEssenceUnlockMilestone : ClientPacket
{ {
public AzeriteEssenceUnlockMilestone(WorldPacket packet) : base(packet) { } public AzeriteEssenceUnlockMilestone(WorldPacket packet) : base(packet) { }
@@ -141,19 +122,4 @@ namespace Game.Networking.Packets
public bool IsHeartEquipped; public bool IsHeartEquipped;
} }
class AzeriteRespecNPC : ServerPacket
{
public AzeriteRespecNPC(ObjectGuid npcGuid) : base(ServerOpcodes.AzeriteRespecNpc)
{
NpcGUID = npcGuid;
}
public override void Write()
{
_worldPacket.WritePackedGuid(NpcGUID);
}
public ObjectGuid NpcGUID;
}
} }
@@ -573,12 +573,15 @@ namespace Game.Networking.Packets
public int Unused2; public int Unused2;
public int WeeklyPlayed; public int WeeklyPlayed;
public int WeeklyWon; public int WeeklyWon;
public int RoundsSeasonPlayed;
public int RoundsSeasonWon;
public int RoundsWeeklyPlayed;
public int RoundsWeeklyWon;
public int BestWeeklyRating; public int BestWeeklyRating;
public int LastWeeksBestRating; public int LastWeeksBestRating;
public int BestSeasonRating; public int BestSeasonRating;
public int PvpTierID; public int PvpTierID;
public int Unused3; public int Unused3;
public int WeeklyBestWinPvpTierID;
public int Unused4; public int Unused4;
public int Rank; public int Rank;
public bool Disqualified; public bool Disqualified;
@@ -593,12 +596,15 @@ namespace Game.Networking.Packets
data.WriteInt32(Unused2); data.WriteInt32(Unused2);
data.WriteInt32(WeeklyPlayed); data.WriteInt32(WeeklyPlayed);
data.WriteInt32(WeeklyWon); data.WriteInt32(WeeklyWon);
data.WriteInt32(RoundsSeasonPlayed);
data.WriteInt32(RoundsSeasonWon);
data.WriteInt32(RoundsWeeklyPlayed);
data.WriteInt32(RoundsWeeklyWon);
data.WriteInt32(BestWeeklyRating); data.WriteInt32(BestWeeklyRating);
data.WriteInt32(LastWeeksBestRating); data.WriteInt32(LastWeeksBestRating);
data.WriteInt32(BestSeasonRating); data.WriteInt32(BestSeasonRating);
data.WriteInt32(PvpTierID); data.WriteInt32(PvpTierID);
data.WriteInt32(Unused3); data.WriteInt32(Unused3);
data.WriteInt32(WeeklyBestWinPvpTierID);
data.WriteInt32(Unused4); data.WriteInt32(Unused4);
data.WriteInt32(Rank); data.WriteInt32(Rank);
data.WriteBit(Disqualified); data.WriteBit(Disqualified);
@@ -33,21 +33,6 @@ namespace Game.Networking.Packets
public ObjectGuid Guid; public ObjectGuid Guid;
} }
class BlackMarketOpenResult : ServerPacket
{
public BlackMarketOpenResult() : base(ServerOpcodes.BlackMarketOpenResult) { }
public override void Write()
{
_worldPacket .WritePackedGuid(Guid);
_worldPacket.WriteBit(Enable);
_worldPacket.FlushBits();
}
public ObjectGuid Guid;
public bool Enable = true;
}
class BlackMarketRequestItems : ClientPacket class BlackMarketRequestItems : ClientPacket
{ {
public BlackMarketRequestItems(WorldPacket packet) : base(packet) { } public BlackMarketRequestItems(WorldPacket packet) : base(packet) { }
@@ -44,12 +44,14 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(IsNewPlayerRestrictionSkipped); _worldPacket.WriteBit(IsNewPlayerRestrictionSkipped);
_worldPacket.WriteBit(IsNewPlayerRestricted); _worldPacket.WriteBit(IsNewPlayerRestricted);
_worldPacket.WriteBit(IsNewPlayer); _worldPacket.WriteBit(IsNewPlayer);
_worldPacket.WriteBit(IsTrialAccountRestricted);
_worldPacket.WriteBit(DisabledClassesMask.HasValue); _worldPacket.WriteBit(DisabledClassesMask.HasValue);
_worldPacket.WriteBit(IsAlliedRacesCreationAllowed); _worldPacket.WriteBit(IsAlliedRacesCreationAllowed);
_worldPacket.WriteInt32(Characters.Count); _worldPacket.WriteInt32(Characters.Count);
_worldPacket.WriteInt32(MaxCharacterLevel); _worldPacket.WriteInt32(MaxCharacterLevel);
_worldPacket.WriteInt32(RaceUnlockData.Count); _worldPacket.WriteInt32(RaceUnlockData.Count);
_worldPacket.WriteInt32(UnlockedConditionalAppearances.Count); _worldPacket.WriteInt32(UnlockedConditionalAppearances.Count);
_worldPacket.WriteInt32(RaceLimitDisables.Count);
if (DisabledClassesMask.HasValue) if (DisabledClassesMask.HasValue)
_worldPacket.WriteUInt32(DisabledClassesMask.Value); _worldPacket.WriteUInt32(DisabledClassesMask.Value);
@@ -57,6 +59,9 @@ namespace Game.Networking.Packets
foreach (UnlockedConditionalAppearance unlockedConditionalAppearance in UnlockedConditionalAppearances) foreach (UnlockedConditionalAppearance unlockedConditionalAppearance in UnlockedConditionalAppearances)
unlockedConditionalAppearance.Write(_worldPacket); unlockedConditionalAppearance.Write(_worldPacket);
foreach (RaceLimitDisableInfo raceLimitDisableInfo in RaceLimitDisables)
raceLimitDisableInfo.Write(_worldPacket);
foreach (CharacterInfo charInfo in Characters) foreach (CharacterInfo charInfo in Characters)
charInfo.Write(_worldPacket); charInfo.Write(_worldPacket);
@@ -69,6 +74,7 @@ namespace Game.Networking.Packets
public bool IsNewPlayerRestrictionSkipped; // allows client to skip new player restrictions public bool IsNewPlayerRestrictionSkipped; // allows client to skip new player restrictions
public bool IsNewPlayerRestricted; // forbids using level boost and class trials public bool IsNewPlayerRestricted; // forbids using level boost and class trials
public bool IsNewPlayer; // forbids hero classes and allied races public bool IsNewPlayer; // forbids hero classes and allied races
public bool IsTrialAccountRestricted;
public bool IsAlliedRacesCreationAllowed; public bool IsAlliedRacesCreationAllowed;
public int MaxCharacterLevel = 1; public int MaxCharacterLevel = 1;
@@ -77,6 +83,7 @@ namespace Game.Networking.Packets
public List<CharacterInfo> Characters = new(); // all characters on the list public List<CharacterInfo> Characters = new(); // all characters on the list
public List<RaceUnlock> RaceUnlockData = new(); // public List<RaceUnlock> RaceUnlockData = new(); //
public List<UnlockedConditionalAppearance> UnlockedConditionalAppearances = new(); public List<UnlockedConditionalAppearance> UnlockedConditionalAppearances = new();
public List<RaceLimitDisableInfo> RaceLimitDisables = new();
public class CharacterInfo public class CharacterInfo
{ {
@@ -147,11 +154,11 @@ namespace Game.Networking.Packets
var spec = Global.DB2Mgr.GetChrSpecializationByIndex(ClassId, fields.Read<byte>(21)); var spec = Global.DB2Mgr.GetChrSpecializationByIndex(ClassId, fields.Read<byte>(21));
if (spec != null) if (spec != null)
SpecID = (ushort)spec.Id; SpecID = (short)spec.Id;
LastLoginVersion = fields.Read<uint>(22); LastLoginVersion = fields.Read<int>(22);
for (byte slot = 0; slot < InventorySlots.BagEnd; ++slot) for (byte slot = 0; slot < InventorySlots.ReagentBagEnd; ++slot)
{ {
VisualItems[slot].InvType = (byte)equipment.NextUInt32(); VisualItems[slot].InvType = (byte)equipment.NextUInt32();
VisualItems[slot].DisplayId = equipment.NextUInt32(); VisualItems[slot].DisplayId = equipment.NextUInt32();
@@ -190,9 +197,9 @@ namespace Game.Networking.Packets
visualItem.Write(data); visualItem.Write(data);
data.WriteInt64(LastPlayedTime); data.WriteInt64(LastPlayedTime);
data.WriteUInt16(SpecID); data.WriteInt16(SpecID);
data.WriteUInt32(Unknown703); data.WriteInt32(Unknown703);
data.WriteUInt32(LastLoginVersion); data.WriteInt32(LastLoginVersion);
data.WriteUInt32(Flags4); data.WriteUInt32(Flags4);
data.WriteInt32(MailSenders.Count); data.WriteInt32(MailSenders.Count);
data.WriteInt32(MailSenderTypes.Count); data.WriteInt32(MailSenderTypes.Count);
@@ -244,16 +251,16 @@ namespace Game.Networking.Packets
public bool FirstLogin; public bool FirstLogin;
public byte unkWod61x; public byte unkWod61x;
public long LastPlayedTime; public long LastPlayedTime;
public ushort SpecID; public short SpecID;
public uint Unknown703; public int Unknown703;
public uint LastLoginVersion; public int LastLoginVersion;
public uint OverrideSelectScreenFileDataID; public uint OverrideSelectScreenFileDataID;
public uint PetCreatureDisplayId; public uint PetCreatureDisplayId;
public uint PetExperienceLevel; public uint PetExperienceLevel;
public uint PetCreatureFamilyId; public uint PetCreatureFamilyId;
public bool BoostInProgress; // @todo public bool BoostInProgress; // @todo
public uint[] ProfessionIds = new uint[2]; // @todo public uint[] ProfessionIds = new uint[2]; // @todo
public VisualItemInfo[] VisualItems = new VisualItemInfo[InventorySlots.BagEnd]; public VisualItemInfo[] VisualItems = new VisualItemInfo[InventorySlots.ReagentBagEnd];
public List<string> MailSenders = new(); public List<string> MailSenders = new();
public List<uint> MailSenderTypes = new(); public List<uint> MailSenderTypes = new();
@@ -311,6 +318,24 @@ namespace Game.Networking.Packets
public int AchievementID; public int AchievementID;
public int Unused; public int Unused;
} }
public struct RaceLimitDisableInfo
{
enum blah
{
Server,
Level
}
public int RaceID;
public int BlockReason;
public void Write(WorldPacket data)
{
data.WriteInt32(RaceID);
data.WriteInt32(BlockReason);
}
}
} }
class CheckCharacterNameAvailability : ClientPacket class CheckCharacterNameAvailability : ClientPacket
@@ -500,6 +525,7 @@ namespace Game.Networking.Packets
RaceOrFactionChangeInfo.Guid = _worldPacket.ReadPackedGuid(); RaceOrFactionChangeInfo.Guid = _worldPacket.ReadPackedGuid();
RaceOrFactionChangeInfo.SexID = (Gender)_worldPacket.ReadUInt8(); RaceOrFactionChangeInfo.SexID = (Gender)_worldPacket.ReadUInt8();
RaceOrFactionChangeInfo.RaceID = (Race)_worldPacket.ReadUInt8(); RaceOrFactionChangeInfo.RaceID = (Race)_worldPacket.ReadUInt8();
RaceOrFactionChangeInfo.InitialRaceID = (Race)_worldPacket.ReadUInt8();
var customizationCount = _worldPacket.ReadUInt32(); var customizationCount = _worldPacket.ReadUInt32();
RaceOrFactionChangeInfo.Name = _worldPacket.ReadString(nameLength); RaceOrFactionChangeInfo.Name = _worldPacket.ReadString(nameLength);
@@ -851,6 +877,7 @@ namespace Game.Networking.Packets
{ {
var customizationCount = _worldPacket.ReadUInt32(); var customizationCount = _worldPacket.ReadUInt32();
NewSex = _worldPacket.ReadUInt8(); NewSex = _worldPacket.ReadUInt8();
CustomizedRace = _worldPacket.ReadInt32();
for (var i = 0; i < customizationCount; ++i) for (var i = 0; i < customizationCount; ++i)
{ {
@@ -866,6 +893,7 @@ namespace Game.Networking.Packets
public byte NewSex; public byte NewSex;
public Array<ChrCustomizationChoice> Customizations = new(50); public Array<ChrCustomizationChoice> Customizations = new(50);
public int CustomizedRace;
} }
public class BarberShopResult : ServerPacket public class BarberShopResult : ServerPacket
@@ -902,7 +930,6 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt8((byte)Reason); _worldPacket.WriteUInt8((byte)Reason);
_worldPacket.WriteInt32(Amount); _worldPacket.WriteInt32(Amount);
_worldPacket.WriteFloat(GroupBonus); _worldPacket.WriteFloat(GroupBonus);
_worldPacket.WriteUInt8(ReferAFriendBonusType);
} }
public ObjectGuid Victim; public ObjectGuid Victim;
@@ -910,7 +937,6 @@ namespace Game.Networking.Packets
public PlayerLogXPReason Reason; public PlayerLogXPReason Reason;
public int Amount; public int Amount;
public float GroupBonus; public float GroupBonus;
public byte ReferAFriendBonusType; // 1 - 300% of normal XP; 2 - 150% of normal XP
} }
class TitleEarned : ServerPacket class TitleEarned : ServerPacket
@@ -1105,6 +1131,7 @@ namespace Game.Networking.Packets
public class CharRaceOrFactionChangeInfo public class CharRaceOrFactionChangeInfo
{ {
public Race RaceID = Race.None; public Race RaceID = Race.None;
public Race InitialRaceID = Race.None;
public Gender SexID = Gender.None; public Gender SexID = Gender.None;
public ObjectGuid Guid; public ObjectGuid Guid;
public bool FactionChange; public bool FactionChange;
@@ -31,7 +31,7 @@ namespace Game.Networking.Packets
public override void Read() public override void Read()
{ {
Language = (Language)_worldPacket.ReadInt32(); Language = (Language)_worldPacket.ReadInt32();
uint len = _worldPacket.ReadBits<uint>(9); uint len = _worldPacket.ReadBits<uint>(11);
Text = _worldPacket.ReadString(len); Text = _worldPacket.ReadString(len);
} }
@@ -47,7 +47,7 @@ namespace Game.Networking.Packets
{ {
Language = (Language)_worldPacket.ReadInt32(); Language = (Language)_worldPacket.ReadInt32();
uint targetLen = _worldPacket.ReadBits<uint>(9); uint targetLen = _worldPacket.ReadBits<uint>(9);
uint textLen = _worldPacket.ReadBits<uint>(9); uint textLen = _worldPacket.ReadBits<uint>(11);
Target = _worldPacket.ReadString(targetLen); Target = _worldPacket.ReadString(targetLen);
Text = _worldPacket.ReadString(textLen); Text = _worldPacket.ReadString(textLen);
} }
@@ -66,7 +66,7 @@ namespace Game.Networking.Packets
Language = (Language)_worldPacket.ReadInt32(); Language = (Language)_worldPacket.ReadInt32();
ChannelGUID = _worldPacket.ReadPackedGuid(); ChannelGUID = _worldPacket.ReadPackedGuid();
uint targetLen = _worldPacket.ReadBits<uint>(9); uint targetLen = _worldPacket.ReadBits<uint>(9);
uint textLen = _worldPacket.ReadBits<uint>(9); uint textLen = _worldPacket.ReadBits<uint>(11);
Target = _worldPacket.ReadString(targetLen); Target = _worldPacket.ReadString(targetLen);
Text = _worldPacket.ReadString(textLen); Text = _worldPacket.ReadString(textLen);
} }
@@ -112,7 +112,7 @@ namespace Game.Networking.Packets
public override void Read() public override void Read()
{ {
uint len = _worldPacket.ReadBits<uint>(9); uint len = _worldPacket.ReadBits<uint>(11);
Text = _worldPacket.ReadString(len); Text = _worldPacket.ReadString(len);
} }
@@ -125,7 +125,7 @@ namespace Game.Networking.Packets
public override void Read() public override void Read()
{ {
uint len = _worldPacket.ReadBits<uint>(9); uint len = _worldPacket.ReadBits<uint>(11);
Text = _worldPacket.ReadString(len); Text = _worldPacket.ReadString(len);
} }
@@ -138,7 +138,7 @@ namespace Game.Networking.Packets
public override void Read() public override void Read()
{ {
uint len = _worldPacket.ReadBits<uint>(9); uint len = _worldPacket.ReadBits<uint>(11);
Text = _worldPacket.ReadString(len); Text = _worldPacket.ReadString(len);
} }
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Game.Entities;
using System.Collections.Generic;
namespace Game.Networking.Packets
{
struct SpellReducedReagent
{
public int ItemID;
public int Quantity;
public void Write(WorldPacket data)
{
data.WriteInt32(ItemID);
data.WriteInt32(Quantity);
}
}
class CraftingData
{
public int CraftingQualityID;
public int field_4;
public int field_8;
public int Multicraft;
public int field_10;
public int field_14;
public int CritBonusSkill;
public float field_1C;
public ulong field_20;
public bool IsCrit;
public bool field_29;
public bool field_2A;
public bool BonusCraft;
public List<SpellReducedReagent> ResourcesReturned = new();
public uint OperationID;
public ObjectGuid ItemGUID;
public int Quantity;
public ItemInstance OldItem = new();
public ItemInstance NewItem = new();
public int EnchantID;
public void Write(WorldPacket data)
{
data.WriteInt32(CraftingQualityID);
data.WriteInt32(field_4);
data.WriteInt32(field_8);
data.WriteInt32(Multicraft);
data.WriteInt32(field_10);
data.WriteInt32(field_14);
data.WriteInt32(CritBonusSkill);
data.WriteFloat(field_1C);
data.WriteUInt64(field_20);
data.WriteInt32(ResourcesReturned.Count);
data.WriteUInt32(OperationID);
data.WritePackedGuid(ItemGUID);
data.WriteInt32(Quantity);
data.WriteInt32(EnchantID);
foreach (SpellReducedReagent spellReducedReagent in ResourcesReturned)
spellReducedReagent.Write(data);
data.WriteBit(IsCrit);
data.WriteBit(field_29);
data.WriteBit(field_2A);
data.WriteBit(BonusCraft);
data.FlushBits();
OldItem.Write(data);
NewItem.Write(data);
}
}
}
@@ -27,9 +27,11 @@ namespace Game.Networking.Packets
public override void Read() public override void Read()
{ {
Guid = _worldPacket.ReadPackedGuid(); Guid = _worldPacket.ReadPackedGuid();
IsSoftInteract = _worldPacket.HasBit();
} }
public ObjectGuid Guid; public ObjectGuid Guid;
public bool IsSoftInteract;
} }
public class GameObjReportUse : ClientPacket public class GameObjReportUse : ClientPacket
@@ -39,9 +41,11 @@ namespace Game.Networking.Packets
public override void Read() public override void Read()
{ {
Guid = _worldPacket.ReadPackedGuid(); Guid = _worldPacket.ReadPackedGuid();
IsSoftInteract = _worldPacket.HasBit();
} }
public ObjectGuid Guid; public ObjectGuid Guid;
public bool IsSoftInteract;
} }
class GameObjectDespawn : ServerPacket class GameObjectDespawn : ServerPacket
@@ -136,22 +140,6 @@ namespace Game.Networking.Packets
public bool PlayAsDespawn; public bool PlayAsDespawn;
} }
class GameObjectUILink : ServerPacket
{
public GameObjectUILink() : base(ServerOpcodes.GameObjectUiLink, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(ObjectGUID);
_worldPacket.WriteInt32(UILink);
_worldPacket.WriteInt32(UIItemInteractionID);
}
public ObjectGuid ObjectGUID;
public int UILink;
public int UIItemInteractionID;
}
class GameObjectPlaySpellVisual : ServerPacket class GameObjectPlaySpellVisual : ServerPacket
{ {
public GameObjectPlaySpellVisual() : base(ServerOpcodes.GameObjectPlaySpellVisual) { } public GameObjectPlaySpellVisual() : base(ServerOpcodes.GameObjectPlaySpellVisual) { }
@@ -181,4 +169,29 @@ namespace Game.Networking.Packets
public ObjectGuid ObjectGUID; public ObjectGuid ObjectGUID;
public byte State; public byte State;
} }
class GameObjectInteraction : ServerPacket
{
public ObjectGuid ObjectGUID;
public PlayerInteractionType InteractionType;
public GameObjectInteraction() : base(ServerOpcodes.GameObjectInteraction) { }
public override void Write()
{
_worldPacket.WritePackedGuid(ObjectGUID);
_worldPacket.WriteInt32((int)InteractionType);
}
}
class GameObjectCloseInteraction : ServerPacket
{
public PlayerInteractionType InteractionType;
public GameObjectCloseInteraction() : base(ServerOpcodes.GameObjectCloseInteraction) { }
public override void Write()
{
_worldPacket.WriteInt32((int)InteractionType);
}
}
} }
@@ -316,22 +316,6 @@ namespace Game.Networking.Packets
public uint GarrPlotInstanceID; public uint GarrPlotInstanceID;
} }
class GarrisonOpenTalentNpc : ServerPacket
{
public GarrisonOpenTalentNpc() : base(ServerOpcodes.GarrisonOpenTalentNpc, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(NpcGUID);
_worldPacket.WriteInt32(GarrTalentTreeID);
_worldPacket.WriteInt32(FriendshipFactionID);
}
public ObjectGuid NpcGUID;
public int GarrTalentTreeID;
public int FriendshipFactionID; // Always 0 except on The Deaths of Chromie Scenario
}
//Structs //Structs
public struct GarrisonPlotInfo public struct GarrisonPlotInfo
@@ -75,7 +75,9 @@ namespace Game.Networking.Packets
GuildData.Value.Write(_worldPacket); GuildData.Value.Write(_worldPacket);
if (AzeriteLevel.HasValue) if (AzeriteLevel.HasValue)
_worldPacket.WriteUInt32((uint)AzeriteLevel); _worldPacket.WriteUInt32(AzeriteLevel.Value);
TalentTraits.Write(_worldPacket);
} }
public PlayerModelDisplayInfo DisplayInfo; public PlayerModelDisplayInfo DisplayInfo;
@@ -83,7 +85,7 @@ namespace Game.Networking.Packets
public List<ushort> Talents = new(); public List<ushort> Talents = new();
public Array<ushort> PvpTalents = new(PlayerConst.MaxPvpTalentSlots, 0); public Array<ushort> PvpTalents = new(PlayerConst.MaxPvpTalentSlots, 0);
public InspectGuildData? GuildData; public InspectGuildData? GuildData;
public Array<PVPBracketData> Bracket = new(6, default); public Array<PVPBracketData> Bracket = new(7, default);
public uint? AzeriteLevel; public uint? AzeriteLevel;
public int ItemLevel; public int ItemLevel;
public uint LifetimeHK; public uint LifetimeHK;
@@ -91,6 +93,7 @@ namespace Game.Networking.Packets
public ushort TodayHK; public ushort TodayHK;
public ushort YesterdayHK; public ushort YesterdayHK;
public byte LifetimeMaxRank; public byte LifetimeMaxRank;
public TraitInspectInfo TalentTraits;
} }
public class QueryInspectAchievements : ClientPacket public class QueryInspectAchievements : ClientPacket
@@ -290,6 +293,7 @@ namespace Game.Networking.Packets
public void Write(WorldPacket data) public void Write(WorldPacket data)
{ {
data.WriteUInt8(Bracket); data.WriteUInt8(Bracket);
data.WriteInt32(Unused3);
data.WriteInt32(Rating); data.WriteInt32(Rating);
data.WriteInt32(Rank); data.WriteInt32(Rank);
data.WriteInt32(WeeklyPlayed); data.WriteInt32(WeeklyPlayed);
@@ -302,6 +306,10 @@ namespace Game.Networking.Packets
data.WriteInt32(WeeklyBestWinPvpTierID); data.WriteInt32(WeeklyBestWinPvpTierID);
data.WriteInt32(Unused1); data.WriteInt32(Unused1);
data.WriteInt32(Unused2); data.WriteInt32(Unused2);
data.WriteInt32(RoundsSeasonPlayed);
data.WriteInt32(RoundsSeasonWon);
data.WriteInt32(RoundsWeeklyPlayed);
data.WriteInt32(RoundsWeeklyWon);
data.WriteBit(Disqualified); data.WriteBit(Disqualified);
data.FlushBits(); data.FlushBits();
} }
@@ -318,10 +326,29 @@ namespace Game.Networking.Packets
public int WeeklyBestWinPvpTierID; public int WeeklyBestWinPvpTierID;
public int Unused1; public int Unused1;
public int Unused2; public int Unused2;
public int Unused3;
public int RoundsSeasonPlayed;
public int RoundsSeasonWon;
public int RoundsWeeklyPlayed;
public int RoundsWeeklyWon;
public byte Bracket; public byte Bracket;
public bool Disqualified; public bool Disqualified;
} }
public struct TraitInspectInfo
{
public int Level;
public int ChrSpecializationID;
public TraitConfig Config;
public void Write(WorldPacket data)
{
data . WriteInt32(Level);
data . WriteInt32(ChrSpecializationID);
Config.Write(data);
}
}
public struct AzeriteEssenceData public struct AzeriteEssenceData
{ {
public uint Index; public uint Index;
+70 -6
View File
@@ -20,6 +20,7 @@ using Framework.Dynamic;
using Game.Entities; using Game.Entities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System;
namespace Game.Networking.Packets namespace Game.Networking.Packets
{ {
@@ -429,14 +430,26 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(BattlePetBreedQuality); _worldPacket.WriteUInt32(BattlePetBreedQuality);
_worldPacket.WriteInt32(BattlePetLevel); _worldPacket.WriteInt32(BattlePetLevel);
_worldPacket.WritePackedGuid(ItemGUID); _worldPacket.WritePackedGuid(ItemGUID);
_worldPacket.WriteInt32(Toasts.Count);
foreach (UiEventToast uiEventToast in Toasts)
uiEventToast.Write(_worldPacket);
_worldPacket.WriteBit(Pushed); _worldPacket.WriteBit(Pushed);
_worldPacket.WriteBit(Created); _worldPacket.WriteBit(Created);
_worldPacket.WriteBits((uint)DisplayText, 3); _worldPacket.WriteBits((uint)DisplayText, 3);
_worldPacket.WriteBit(IsBonusRoll); _worldPacket.WriteBit(IsBonusRoll);
_worldPacket.WriteBit(IsEncounterLoot); _worldPacket.WriteBit(IsEncounterLoot);
_worldPacket.WriteBit(CraftingData != null);
_worldPacket.WriteBit(FirstCraftOperationID.HasValue);
_worldPacket.FlushBits(); _worldPacket.FlushBits();
Item.Write(_worldPacket); Item.Write(_worldPacket);
if (FirstCraftOperationID.HasValue)
_worldPacket.WriteUInt32(FirstCraftOperationID.Value);
if (CraftingData != null)
CraftingData.Write(_worldPacket);
} }
public ObjectGuid PlayerGUID; public ObjectGuid PlayerGUID;
@@ -444,7 +457,7 @@ namespace Game.Networking.Packets
public int SlotInBag; public int SlotInBag;
public ItemInstance Item; public ItemInstance Item;
public int QuestLogItemID;// Item ID used for updating quest progress public int QuestLogItemID;// Item ID used for updating quest progress
// only set if different than real ID (similar to CreatureTemplate.KillCredit) // only set if different than real ID (similar to CreatureTemplate.KillCredit)
public uint Quantity; public uint Quantity;
public uint QuantityInInventory; public uint QuantityInInventory;
public int DungeonEncounterID; public int DungeonEncounterID;
@@ -453,6 +466,9 @@ namespace Game.Networking.Packets
public uint BattlePetBreedQuality; public uint BattlePetBreedQuality;
public int BattlePetLevel; public int BattlePetLevel;
public ObjectGuid ItemGUID; public ObjectGuid ItemGUID;
public List<UiEventToast> Toasts = new();
public CraftingData CraftingData;
public uint? FirstCraftOperationID;
public bool Pushed; public bool Pushed;
public DisplayType DisplayText; public DisplayType DisplayText;
public bool Created; public bool Created;
@@ -528,7 +544,7 @@ namespace Game.Networking.Packets
public EnchantmentLog() : base(ServerOpcodes.EnchantmentLog, ConnectionType.Instance) { } public EnchantmentLog() : base(ServerOpcodes.EnchantmentLog, ConnectionType.Instance) { }
public override void Write() public override void Write()
{ {
_worldPacket.WritePackedGuid(Owner); _worldPacket.WritePackedGuid(Owner);
_worldPacket.WritePackedGuid(Caster); _worldPacket.WritePackedGuid(Caster);
_worldPacket.WritePackedGuid(ItemGUID); _worldPacket.WritePackedGuid(ItemGUID);
@@ -572,7 +588,7 @@ namespace Game.Networking.Packets
public uint SpellID; public uint SpellID;
public uint Cooldown; public uint Cooldown;
} }
class ItemEnchantTimeUpdate : ServerPacket class ItemEnchantTimeUpdate : ServerPacket
{ {
public ItemEnchantTimeUpdate() : base(ServerOpcodes.ItemEnchantTimeUpdate, ConnectionType.Instance) { } public ItemEnchantTimeUpdate() : base(ServerOpcodes.ItemEnchantTimeUpdate, ConnectionType.Instance) { }
@@ -741,7 +757,7 @@ namespace Game.Networking.Packets
} }
public class ItemMod public class ItemMod
{ {
public uint Value; public uint Value;
public ItemModifier Type; public ItemModifier Type;
@@ -858,7 +874,7 @@ namespace Game.Networking.Packets
public ItemInstance(Item item) public ItemInstance(Item item)
{ {
ItemID = item.GetEntry(); ItemID = item.GetEntry();
List<uint> bonusListIds = item.m_itemData.BonusListIDs; List<uint> bonusListIds = item.GetBonusListIDs();
if (!bonusListIds.Empty()) if (!bonusListIds.Empty())
{ {
ItemBonus = new(); ItemBonus = new();
@@ -984,8 +1000,44 @@ namespace Game.Networking.Packets
} }
} }
public class ItemBonusKey : IEquatable<ItemBonusKey>
{
public uint ItemID;
public List<uint> BonusListIDs = new();
public List<ItemMod> Modifications = new();
public void Write(WorldPacket data)
{
data.WriteUInt32(ItemID);
data.WriteInt32(BonusListIDs.Count);
data.WriteInt32(Modifications.Count);
if (!BonusListIDs.Empty())
foreach (var id in BonusListIDs)
data.WriteUInt32(id);
foreach (ItemMod modification in Modifications)
modification.Write(data);
}
public bool Equals(ItemBonusKey right)
{
if (ItemID != right.ItemID)
return false;
if (BonusListIDs != right.BonusListIDs)
return false;
if (Modifications != right.Modifications)
return false;
return true;
}
}
public class ItemEnchantData public class ItemEnchantData
{ {
public ItemEnchantData() { }
public ItemEnchantData(uint id, uint expiration, int charges, byte slot) public ItemEnchantData(uint id, uint expiration, int charges, byte slot)
{ {
ID = id; ID = id;
@@ -1093,4 +1145,16 @@ namespace Game.Networking.Packets
public ItemPurchaseRefundItem[] Items = new ItemPurchaseRefundItem[5]; public ItemPurchaseRefundItem[] Items = new ItemPurchaseRefundItem[5];
public ItemPurchaseRefundCurrency[] Currencies = new ItemPurchaseRefundCurrency[5]; public ItemPurchaseRefundCurrency[] Currencies = new ItemPurchaseRefundCurrency[5];
} }
public struct UiEventToast
{
public int UiEventToastID;
public int Asset;
public void Write(WorldPacket data)
{
data.WriteInt32(UiEventToastID);
data.WriteInt32(Asset);
}
}
} }
@@ -29,9 +29,11 @@ namespace Game.Networking.Packets
public override void Read() public override void Read()
{ {
Unit = _worldPacket.ReadPackedGuid(); Unit = _worldPacket.ReadPackedGuid();
IsSoftInteract = _worldPacket.HasBit();
} }
public ObjectGuid Unit; public ObjectGuid Unit;
public bool IsSoftInteract;
} }
public class LootResponse : ServerPacket public class LootResponse : ServerPacket
@@ -273,6 +275,9 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt32(MapID); _worldPacket.WriteInt32(MapID);
_worldPacket.WriteUInt32(RollTime); _worldPacket.WriteUInt32(RollTime);
_worldPacket.WriteUInt8((byte)ValidRolls); _worldPacket.WriteUInt8((byte)ValidRolls);
foreach (var reason in LootRollIneligibleReason)
_worldPacket.WriteUInt32((uint)reason);
_worldPacket.WriteUInt8((byte)Method); _worldPacket.WriteUInt8((byte)Method);
Item.Write(_worldPacket); Item.Write(_worldPacket);
} }
@@ -282,6 +287,7 @@ namespace Game.Networking.Packets
public uint RollTime; public uint RollTime;
public LootMethod Method; public LootMethod Method;
public RollMask ValidRolls; public RollMask ValidRolls;
public Array<LootRollIneligibilityReason> LootRollIneligibleReason = new Array<LootRollIneligibilityReason>(4);
public LootItemData Item = new(); public LootItemData Item = new();
} }
@@ -293,18 +293,6 @@ namespace Game.Networking.Packets
public float Delay = 0.0f; public float Delay = 0.0f;
} }
class ShowMailbox : ServerPacket
{
public ShowMailbox() : base(ServerOpcodes.ShowMailbox) { }
public override void Write()
{
_worldPacket.WritePackedGuid(PostmasterGUID);
}
public ObjectGuid PostmasterGUID;
}
//Structs //Structs
public class MailAttachedItem public class MailAttachedItem
{ {
+26 -26
View File
@@ -58,21 +58,6 @@ namespace Game.Networking.Packets
uint AreaID; uint AreaID;
} }
public class BinderConfirm : ServerPacket
{
public BinderConfirm(ObjectGuid unit) : base(ServerOpcodes.BinderConfirm)
{
Unit = unit;
}
public override void Write()
{
_worldPacket.WritePackedGuid(Unit);
}
ObjectGuid Unit;
}
public class InvalidatePlayer : ServerPacket public class InvalidatePlayer : ServerPacket
{ {
public InvalidatePlayer() : base(ServerOpcodes.InvalidatePlayer) { } public InvalidatePlayer() : base(ServerOpcodes.InvalidatePlayer) { }
@@ -124,11 +109,13 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(WeeklyQuantity.HasValue); _worldPacket.WriteBit(WeeklyQuantity.HasValue);
_worldPacket.WriteBit(TrackedQuantity.HasValue); _worldPacket.WriteBit(TrackedQuantity.HasValue);
_worldPacket.WriteBit(MaxQuantity.HasValue); _worldPacket.WriteBit(MaxQuantity.HasValue);
_worldPacket.WriteBit(Unused901.HasValue); _worldPacket.WriteBit(TotalEarned.HasValue);
_worldPacket.WriteBit(SuppressChatLog); _worldPacket.WriteBit(SuppressChatLog);
_worldPacket.WriteBit(QuantityChange.HasValue); _worldPacket.WriteBit(QuantityChange.HasValue);
_worldPacket.WriteBit(QuantityGainSource.HasValue);
_worldPacket.WriteBit(QuantityLostSource.HasValue); _worldPacket.WriteBit(QuantityLostSource.HasValue);
_worldPacket.WriteBit(QuantityGainSource.HasValue);
_worldPacket.WriteBit(FirstCraftOperationID.HasValue);
_worldPacket.WriteBit(LastSpendTime.HasValue);
_worldPacket.FlushBits(); _worldPacket.FlushBits();
if (WeeklyQuantity.HasValue) if (WeeklyQuantity.HasValue)
@@ -140,29 +127,38 @@ namespace Game.Networking.Packets
if (MaxQuantity.HasValue) if (MaxQuantity.HasValue)
_worldPacket.WriteInt32(MaxQuantity.Value); _worldPacket.WriteInt32(MaxQuantity.Value);
if (Unused901.HasValue) if (TotalEarned.HasValue)
_worldPacket.WriteInt32(Unused901.Value); _worldPacket.WriteInt32(TotalEarned.Value);
if (QuantityChange.HasValue) if (QuantityChange.HasValue)
_worldPacket.WriteInt32(QuantityChange.Value); _worldPacket.WriteInt32(QuantityChange.Value);
if (QuantityLostSource.HasValue)
_worldPacket.WriteInt32(QuantityLostSource.Value);
if (QuantityGainSource.HasValue) if (QuantityGainSource.HasValue)
_worldPacket.WriteInt32(QuantityGainSource.Value); _worldPacket.WriteInt32(QuantityGainSource.Value);
if (QuantityLostSource.HasValue) if (FirstCraftOperationID.HasValue)
_worldPacket.WriteInt32(QuantityLostSource.Value); _worldPacket.WriteUInt32(FirstCraftOperationID.Value);
if (LastSpendTime.HasValue)
_worldPacket.WriteInt64(LastSpendTime.Value);
} }
public uint Type; public uint Type;
public int Quantity; public int Quantity;
public uint Flags; public uint Flags;
public List<UiEventToast> Toasts = new();
public int? WeeklyQuantity; public int? WeeklyQuantity;
public int? TrackedQuantity; public int? TrackedQuantity;
public int? MaxQuantity; public int? MaxQuantity;
public int? Unused901; public int? TotalEarned;
public int? QuantityChange; public int? QuantityChange;
public int? QuantityGainSource; public int? QuantityGainSource;
public int? QuantityLostSource; public int? QuantityLostSource;
public uint? FirstCraftOperationID;
public long? LastSpendTime;
public bool SuppressChatLog; public bool SuppressChatLog;
} }
@@ -209,7 +205,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(data.MaxWeeklyQuantity.HasValue); _worldPacket.WriteBit(data.MaxWeeklyQuantity.HasValue);
_worldPacket.WriteBit(data.TrackedQuantity.HasValue); _worldPacket.WriteBit(data.TrackedQuantity.HasValue);
_worldPacket.WriteBit(data.MaxQuantity.HasValue); _worldPacket.WriteBit(data.MaxQuantity.HasValue);
_worldPacket.WriteBit(data.Unused901.HasValue); _worldPacket.WriteBit(data.TotalEarned.HasValue);
_worldPacket.WriteBit(data.LastSpendTime.HasValue);
_worldPacket.WriteBits(data.Flags, 5); _worldPacket.WriteBits(data.Flags, 5);
_worldPacket.FlushBits(); _worldPacket.FlushBits();
@@ -221,8 +218,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(data.TrackedQuantity.Value); _worldPacket.WriteUInt32(data.TrackedQuantity.Value);
if (data.MaxQuantity.HasValue) if (data.MaxQuantity.HasValue)
_worldPacket.WriteInt32(data.MaxQuantity.Value); _worldPacket.WriteInt32(data.MaxQuantity.Value);
if (data.Unused901.HasValue) if (data.TotalEarned.HasValue)
_worldPacket.WriteInt32(data.Unused901.Value); _worldPacket.WriteInt32(data.TotalEarned.Value);
if (data.LastSpendTime.HasValue)
_worldPacket.WriteInt64(data.LastSpendTime.Value);
} }
} }
@@ -236,7 +235,8 @@ namespace Game.Networking.Packets
public uint? MaxWeeklyQuantity; // Weekly Currency cap. public uint? MaxWeeklyQuantity; // Weekly Currency cap.
public uint? TrackedQuantity; public uint? TrackedQuantity;
public int? MaxQuantity; public int? MaxQuantity;
public int? Unused901; public int? TotalEarned;
public long? LastSpendTime;
public byte Flags; // 0 = none, public byte Flags; // 0 = none,
} }
} }
@@ -106,6 +106,7 @@ namespace Game.Networking.Packets
data.ReadBit(); // HeightChangeFailed data.ReadBit(); // HeightChangeFailed
data.ReadBit(); // RemoteTimeValid data.ReadBit(); // RemoteTimeValid
bool hasInertia = data.HasBit(); bool hasInertia = data.HasBit();
bool hasAdvFlying = data.HasBit();
if (hasTransport) if (hasTransport)
ReadTransportInfo(data, ref movementInfo.transport); ReadTransportInfo(data, ref movementInfo.transport);
@@ -113,13 +114,22 @@ namespace Game.Networking.Packets
if (hasInertia) if (hasInertia)
{ {
MovementInfo.Inertia inertia = new(); MovementInfo.Inertia inertia = new();
inertia.guid = data.ReadPackedGuid(); inertia.id = data.ReadInt32();
inertia.force = data.ReadPosition(); inertia.force = data.ReadPosition();
inertia.lifetime = data.ReadUInt32(); inertia.lifetime = data.ReadUInt32();
movementInfo.inertia = inertia; movementInfo.inertia = inertia;
} }
if (hasAdvFlying)
{
MovementInfo.AdvFlying advFlying = new();
advFlying.forwardVelocity = data.ReadFloat();
advFlying.upVelocity = data.ReadFloat();
movementInfo.advFlying = advFlying;
}
if (hasFall) if (hasFall)
{ {
movementInfo.jump.fallTime = data.ReadUInt32(); movementInfo.jump.fallTime = data.ReadUInt32();
@@ -146,6 +156,7 @@ namespace Game.Networking.Packets
bool hasFallData = hasFallDirection || movementInfo.jump.fallTime != 0; bool hasFallData = hasFallDirection || movementInfo.jump.fallTime != 0;
bool hasSpline = false; // todo 6.x send this infos bool hasSpline = false; // todo 6.x send this infos
bool hasInertia = movementInfo.inertia.HasValue; bool hasInertia = movementInfo.inertia.HasValue;
bool hasAdvFlying = movementInfo.advFlying.HasValue;
data.WritePackedGuid(movementInfo.Guid); data.WritePackedGuid(movementInfo.Guid);
data.WriteUInt32((uint)movementInfo.GetMovementFlags()); data.WriteUInt32((uint)movementInfo.GetMovementFlags());
@@ -176,6 +187,7 @@ namespace Game.Networking.Packets
data.WriteBit(false); // HeightChangeFailed data.WriteBit(false); // HeightChangeFailed
data.WriteBit(false); // RemoteTimeValid data.WriteBit(false); // RemoteTimeValid
data.WriteBit(hasInertia); data.WriteBit(hasInertia);
data.WriteBit(hasAdvFlying);
data.FlushBits(); data.FlushBits();
if (hasTransportData) if (hasTransportData)
@@ -183,11 +195,17 @@ namespace Game.Networking.Packets
if (hasInertia) if (hasInertia)
{ {
data.WritePackedGuid(movementInfo.inertia.Value.guid); data.WriteInt32(movementInfo.inertia.Value.id);
data.WriteXYZ(movementInfo.inertia.Value.force); data.WriteXYZ(movementInfo.inertia.Value.force);
data.WriteUInt32(movementInfo.inertia.Value.lifetime); data.WriteUInt32(movementInfo.inertia.Value.lifetime);
} }
if (hasAdvFlying)
{
data.WriteFloat(movementInfo.advFlying.Value.forwardVelocity);
data.WriteFloat(movementInfo.advFlying.Value.upVelocity);
}
if (hasFallData) if (hasFallData)
{ {
data.WriteUInt32(movementInfo.jump.fallTime); data.WriteUInt32(movementInfo.jump.fallTime);
@@ -514,7 +532,7 @@ namespace Game.Networking.Packets
} }
public ObjectGuid MoverGUID; public ObjectGuid MoverGUID;
public uint SequenceIndex = 0; // Unit movement packet index, incremented each time public uint SequenceIndex; // Unit movement packet index, incremented each time
public float Speed = 1.0f; public float Speed = 1.0f;
} }
@@ -555,7 +573,7 @@ namespace Game.Networking.Packets
} }
public ObjectGuid MoverGUID; public ObjectGuid MoverGUID;
public uint SequenceIndex = 0; // Unit movement packet index, incremented each time public uint SequenceIndex; // Unit movement packet index, incremented each time
} }
public class TransferPending : ServerPacket public class TransferPending : ServerPacket
@@ -1167,6 +1185,12 @@ namespace Game.Networking.Packets
public float InitVertSpeed; public float InitVertSpeed;
} }
public class SpeedRange
{
public float Min;
public float Max;
}
public class MoveStateChange public class MoveStateChange
{ {
public MoveStateChange(ServerOpcodes messageId, uint sequenceIndex) public MoveStateChange(ServerOpcodes messageId, uint sequenceIndex)
@@ -1180,12 +1204,13 @@ namespace Game.Networking.Packets
data.WriteUInt16((ushort)MessageID); data.WriteUInt16((ushort)MessageID);
data.WriteUInt32(SequenceIndex); data.WriteUInt32(SequenceIndex);
data.WriteBit(Speed.HasValue); data.WriteBit(Speed.HasValue);
data.WriteBit(SpeedRange != null);
data.WriteBit(KnockBack.HasValue); data.WriteBit(KnockBack.HasValue);
data.WriteBit(VehicleRecID.HasValue); data.WriteBit(VehicleRecID.HasValue);
data.WriteBit(CollisionHeight.HasValue); data.WriteBit(CollisionHeight.HasValue);
data.WriteBit(@MovementForce != null); data.WriteBit(@MovementForce != null);
data.WriteBit(MovementForceGUID.HasValue); data.WriteBit(MovementForceGUID.HasValue);
data.WriteBit(MovementInertiaGUID.HasValue); data.WriteBit(MovementInertiaID.HasValue);
data.WriteBit(MovementInertiaLifetimeMs.HasValue); data.WriteBit(MovementInertiaLifetimeMs.HasValue);
data.FlushBits(); data.FlushBits();
@@ -1195,6 +1220,12 @@ namespace Game.Networking.Packets
if (Speed.HasValue) if (Speed.HasValue)
data.WriteFloat(Speed.Value); data.WriteFloat(Speed.Value);
if (SpeedRange != null)
{
data.WriteFloat(SpeedRange.Min);
data.WriteFloat(SpeedRange.Max);
}
if (KnockBack.HasValue) if (KnockBack.HasValue)
{ {
data.WriteFloat(KnockBack.Value.HorzSpeed); data.WriteFloat(KnockBack.Value.HorzSpeed);
@@ -1216,8 +1247,8 @@ namespace Game.Networking.Packets
if (MovementForceGUID.HasValue) if (MovementForceGUID.HasValue)
data.WritePackedGuid(MovementForceGUID.Value); data.WritePackedGuid(MovementForceGUID.Value);
if (MovementInertiaGUID.HasValue) if (MovementInertiaID.HasValue)
data.WritePackedGuid(MovementInertiaGUID.Value); data.WriteInt32(MovementInertiaID.Value);
if (MovementInertiaLifetimeMs.HasValue) if (MovementInertiaLifetimeMs.HasValue)
data.WriteUInt32(MovementInertiaLifetimeMs.Value); data.WriteUInt32(MovementInertiaLifetimeMs.Value);
@@ -1226,12 +1257,13 @@ namespace Game.Networking.Packets
public ServerOpcodes MessageID; public ServerOpcodes MessageID;
public uint SequenceIndex; public uint SequenceIndex;
public float? Speed; public float? Speed;
public SpeedRange SpeedRange;
public KnockBackInfo? KnockBack; public KnockBackInfo? KnockBack;
public int? VehicleRecID; public int? VehicleRecID;
public CollisionHeightInfo? CollisionHeight; public CollisionHeightInfo? CollisionHeight;
public MovementForce MovementForce; public MovementForce MovementForce;
public ObjectGuid? MovementForceGUID; public ObjectGuid? MovementForceGUID;
public ObjectGuid? MovementInertiaGUID; public int? MovementInertiaID;
public uint? MovementInertiaLifetimeMs; public uint? MovementInertiaLifetimeMs;
} }
} }
+88 -67
View File
@@ -43,6 +43,23 @@ namespace Game.Networking.Packets
public ObjectGuid Unit; public ObjectGuid Unit;
} }
public class NPCInteractionOpenResult : ServerPacket
{
public NPCInteractionOpenResult() : base(ServerOpcodes.NpcInteractionOpenResult) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Npc);
_worldPacket.WriteInt32((int)InteractionType);
_worldPacket.WriteBit(Success);
_worldPacket.FlushBits();
}
public ObjectGuid Npc;
public PlayerInteractionType InteractionType;
public bool Success = true;
}
public class GossipMessagePkt : ServerPacket public class GossipMessagePkt : ServerPacket
{ {
public GossipMessagePkt() : base(ServerOpcodes.GossipMessage) { } public GossipMessagePkt() : base(ServerOpcodes.GossipMessage) { }
@@ -52,33 +69,20 @@ namespace Game.Networking.Packets
_worldPacket.WritePackedGuid(GossipGUID); _worldPacket.WritePackedGuid(GossipGUID);
_worldPacket.WriteUInt32(GossipID); _worldPacket.WriteUInt32(GossipID);
_worldPacket.WriteInt32(FriendshipFactionID); _worldPacket.WriteInt32(FriendshipFactionID);
_worldPacket.WriteInt32(TextID);
_worldPacket.WriteInt32(GossipOptions.Count); _worldPacket.WriteInt32(GossipOptions.Count);
_worldPacket.WriteInt32(GossipText.Count); _worldPacket.WriteInt32(GossipText.Count);
_worldPacket.WriteBit(TextID.HasValue);
_worldPacket.WriteBit(TextID2.HasValue);
_worldPacket.FlushBits();
foreach (ClientGossipOptions options in GossipOptions) foreach (ClientGossipOptions options in GossipOptions)
{ options.Write(_worldPacket);
_worldPacket.WriteInt32(options.ClientOption);
_worldPacket.WriteUInt8((byte)options.OptionNPC);
_worldPacket.WriteUInt8(options.OptionFlags);
_worldPacket.WriteInt32(options.OptionCost);
_worldPacket.WriteUInt32(options.OptionLanguage);
_worldPacket.WriteBits(options.Text.GetByteCount(), 12); if (TextID.HasValue)
_worldPacket.WriteBits(options.Confirm.GetByteCount(), 12); _worldPacket.WriteInt32(TextID.Value);
_worldPacket.WriteBits((byte)options.Status, 2);
_worldPacket.WriteBit(options.SpellID.HasValue);
_worldPacket.FlushBits();
options.Treasure.Write(_worldPacket); if (TextID2.HasValue)
_worldPacket.WriteInt32(TextID2.Value);
_worldPacket.WriteString(options.Text);
_worldPacket.WriteString(options.Confirm);
if (options.SpellID.HasValue)
_worldPacket.WriteInt32(options.SpellID.Value);
}
foreach (ClientGossipText text in GossipText) foreach (ClientGossipText text in GossipText)
text.Write(_worldPacket); text.Write(_worldPacket);
@@ -88,7 +92,8 @@ namespace Game.Networking.Packets
public int FriendshipFactionID; public int FriendshipFactionID;
public ObjectGuid GossipGUID; public ObjectGuid GossipGUID;
public List<ClientGossipText> GossipText = new(); public List<ClientGossipText> GossipText = new();
public int TextID; public int? TextID;
public int? TextID2;
public uint GossipID; public uint GossipID;
} }
@@ -100,18 +105,38 @@ namespace Game.Networking.Packets
{ {
GossipUnit = _worldPacket.ReadPackedGuid(); GossipUnit = _worldPacket.ReadPackedGuid();
GossipID = _worldPacket.ReadUInt32(); GossipID = _worldPacket.ReadUInt32();
GossipIndex = _worldPacket.ReadUInt32(); GossipOptionID = _worldPacket.ReadInt32();
uint length = _worldPacket.ReadBits<uint>(8); uint length = _worldPacket.ReadBits<uint>(8);
PromotionCode = _worldPacket.ReadString(length); PromotionCode = _worldPacket.ReadString(length);
} }
public ObjectGuid GossipUnit; public ObjectGuid GossipUnit;
public uint GossipIndex; public int GossipOptionID;
public uint GossipID; public uint GossipID;
public string PromotionCode; public string PromotionCode;
} }
class GossipOptionNPCInteraction : ServerPacket
{
public GossipOptionNPCInteraction() : base(ServerOpcodes.GossipOptionNpcInteraction) { }
public override void Write()
{
_worldPacket.WritePackedGuid(GossipGUID);
_worldPacket.WriteInt32(GossipNpcOptionID);
_worldPacket.WriteBit(FriendshipFactionID.HasValue);
_worldPacket.FlushBits();
if (FriendshipFactionID.HasValue)
_worldPacket.WriteInt32(FriendshipFactionID.Value);
}
public ObjectGuid GossipGUID;
public int GossipNpcOptionID;
public int? FriendshipFactionID;
}
public class GossipComplete : ServerPacket public class GossipComplete : ServerPacket
{ {
public bool SuppressSound; public bool SuppressSound;
@@ -181,30 +206,6 @@ namespace Game.Networking.Packets
public string Greeting; public string Greeting;
} }
public class ShowBank : ServerPacket
{
public ShowBank() : base(ServerOpcodes.ShowBank, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Guid);
}
public ObjectGuid Guid;
}
public class PlayerTabardVendorActivate : ServerPacket
{
public PlayerTabardVendorActivate() : base(ServerOpcodes.PlayerTabardVendorActivate) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Vendor);
}
public ObjectGuid Vendor;
}
class GossipPOI : ServerPacket class GossipPOI : ServerPacket
{ {
public GossipPOI() : base(ServerOpcodes.GossipPoi) { } public GossipPOI() : base(ServerOpcodes.GossipPoi) { }
@@ -243,18 +244,6 @@ namespace Game.Networking.Packets
public ObjectGuid Healer; public ObjectGuid Healer;
} }
public class SpiritHealerConfirm : ServerPacket
{
public SpiritHealerConfirm() : base(ServerOpcodes.SpiritHealerConfirm) { }
public override void Write()
{
_worldPacket.WritePackedGuid(Unit);
}
public ObjectGuid Unit;
}
class TrainerBuySpell : ClientPacket class TrainerBuySpell : ClientPacket
{ {
public TrainerBuySpell(WorldPacket packet) : base(packet) { } public TrainerBuySpell(WorldPacket packet) : base(packet) { }
@@ -344,16 +333,47 @@ namespace Game.Networking.Packets
public class ClientGossipOptions public class ClientGossipOptions
{ {
public int ClientOption; public int GossipOptionID;
public GossipOptionNpc OptionNPC; public GossipOptionNpc OptionNPC;
public byte OptionFlags; public byte OptionFlags;
public int OptionCost; public int OptionCost;
public uint OptionLanguage; public uint OptionLanguage;
public GossipOptionFlags Flags;
public int OrderIndex;
public GossipOptionStatus Status; public GossipOptionStatus Status;
public string Text; public string Text = "";
public string Confirm; public string Confirm = "";
public TreasureLootList Treasure = new(); public TreasureLootList Treasure = new();
public int? SpellID; public int? SpellID;
public int? OverrideIconID;
public void Write(WorldPacket data)
{
data.WriteInt32(GossipOptionID);
data.WriteUInt8((byte)OptionNPC);
data.WriteInt8((sbyte)OptionFlags);
data.WriteInt32(OptionCost);
data.WriteUInt32(OptionLanguage);
data.WriteInt32((int)Flags);
data.WriteInt32(OrderIndex);
data.WriteBits(Text.GetByteCount(), 12);
data.WriteBits(Confirm.GetByteCount(), 12);
data.WriteBits((byte)Status, 2);
data.WriteBit(SpellID.HasValue);
data.WriteBit(OverrideIconID.HasValue);
data.FlushBits();
Treasure.Write(data);
data.WriteString(Text);
data.WriteString(Confirm);
if (SpellID.HasValue)
data.WriteInt32(SpellID.Value);
if (OverrideIconID.HasValue)
data.WriteInt32(OverrideIconID.Value);
}
} }
public class ClientGossipText public class ClientGossipText
@@ -386,19 +406,20 @@ namespace Game.Networking.Packets
{ {
public void Write(WorldPacket data) public void Write(WorldPacket data)
{ {
data.WriteInt32(MuID);
data.WriteInt32(Type);
data.WriteInt32(Quantity);
data.WriteUInt64(Price); data.WriteUInt64(Price);
data.WriteInt32(MuID);
data.WriteInt32(Durability); data.WriteInt32(Durability);
data.WriteInt32(StackCount); data.WriteInt32(StackCount);
data.WriteInt32(Quantity);
data.WriteInt32(ExtendedCostID); data.WriteInt32(ExtendedCostID);
data.WriteInt32(PlayerConditionFailed); data.WriteInt32(PlayerConditionFailed);
Item.Write(data); data.WriteBits(Type, 3);
data.WriteBit(Locked); data.WriteBit(Locked);
data.WriteBit(DoNotFilterOnVendor); data.WriteBit(DoNotFilterOnVendor);
data.WriteBit(Refundable); data.WriteBit(Refundable);
data.FlushBits(); data.FlushBits();
Item.Write(data);
} }
public int MuID; public int MuID;
+66 -3
View File
@@ -197,6 +197,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt32(Info.Expansion); _worldPacket.WriteInt32(Info.Expansion);
_worldPacket.WriteInt32(Info.ManagedWorldStateID); _worldPacket.WriteInt32(Info.ManagedWorldStateID);
_worldPacket.WriteInt32(Info.QuestSessionBonus); _worldPacket.WriteInt32(Info.QuestSessionBonus);
_worldPacket.WriteInt32(Info.QuestGiverCreatureID);
_worldPacket.WriteInt32(Info.ConditionalQuestDescription.Count);
_worldPacket.WriteInt32(Info.ConditionalQuestCompletionLog.Count);
foreach (QuestCompleteDisplaySpell rewardDisplaySpell in Info.RewardDisplaySpell) foreach (QuestCompleteDisplaySpell rewardDisplaySpell in Info.RewardDisplaySpell)
rewardDisplaySpell.Write(_worldPacket); rewardDisplaySpell.Write(_worldPacket);
@@ -243,6 +247,12 @@ namespace Game.Networking.Packets
_worldPacket.WriteString(Info.PortraitTurnInText); _worldPacket.WriteString(Info.PortraitTurnInText);
_worldPacket.WriteString(Info.PortraitTurnInName); _worldPacket.WriteString(Info.PortraitTurnInName);
_worldPacket.WriteString(Info.QuestCompletionLog); _worldPacket.WriteString(Info.QuestCompletionLog);
foreach (ConditionalQuestText conditionalQuestText in Info.ConditionalQuestDescription)
conditionalQuestText.Write(_worldPacket);
foreach (ConditionalQuestText conditionalQuestText in Info.ConditionalQuestCompletionLog)
conditionalQuestText.Write(_worldPacket);
} }
} }
@@ -315,6 +325,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(PortraitGiverMount); _worldPacket.WriteUInt32(PortraitGiverMount);
_worldPacket.WriteInt32(PortraitGiverModelSceneID); _worldPacket.WriteInt32(PortraitGiverModelSceneID);
_worldPacket.WriteUInt32(PortraitTurnIn); _worldPacket.WriteUInt32(PortraitTurnIn);
_worldPacket.WriteUInt32(QuestGiverCreatureID);
_worldPacket.WriteInt32(ConditionalRewardText.Count);
_worldPacket.WriteBits(QuestTitle.GetByteCount(), 9); _worldPacket.WriteBits(QuestTitle.GetByteCount(), 9);
_worldPacket.WriteBits(RewardText.GetByteCount(), 12); _worldPacket.WriteBits(RewardText.GetByteCount(), 12);
@@ -322,6 +334,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteBits(PortraitGiverName.GetByteCount(), 8); _worldPacket.WriteBits(PortraitGiverName.GetByteCount(), 8);
_worldPacket.WriteBits(PortraitTurnInText.GetByteCount(), 10); _worldPacket.WriteBits(PortraitTurnInText.GetByteCount(), 10);
_worldPacket.WriteBits(PortraitTurnInName.GetByteCount(), 8); _worldPacket.WriteBits(PortraitTurnInName.GetByteCount(), 8);
_worldPacket.FlushBits();
foreach (ConditionalQuestText conditionalQuestText in ConditionalRewardText)
conditionalQuestText.Write(_worldPacket);
_worldPacket.WriteString(QuestTitle); _worldPacket.WriteString(QuestTitle);
_worldPacket.WriteString(RewardText); _worldPacket.WriteString(RewardText);
@@ -335,12 +351,14 @@ namespace Game.Networking.Packets
public uint PortraitGiver; public uint PortraitGiver;
public uint PortraitGiverMount; public uint PortraitGiverMount;
public int PortraitGiverModelSceneID; public int PortraitGiverModelSceneID;
public uint QuestGiverCreatureID;
public string QuestTitle = ""; public string QuestTitle = "";
public string RewardText = ""; public string RewardText = "";
public string PortraitGiverText = ""; public string PortraitGiverText = "";
public string PortraitGiverName = ""; public string PortraitGiverName = "";
public string PortraitTurnInText = ""; public string PortraitTurnInText = "";
public string PortraitTurnInName = ""; public string PortraitTurnInName = "";
public List<ConditionalQuestText> ConditionalRewardText = new();
public QuestGiverOfferReward QuestData; public QuestGiverOfferReward QuestData;
public uint QuestPackageID; public uint QuestPackageID;
} }
@@ -437,12 +455,15 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(PortraitTurnIn); _worldPacket.WriteUInt32(PortraitTurnIn);
_worldPacket.WriteUInt32(QuestFlags[0]); // Flags _worldPacket.WriteUInt32(QuestFlags[0]); // Flags
_worldPacket.WriteUInt32(QuestFlags[1]); // FlagsEx _worldPacket.WriteUInt32(QuestFlags[1]); // FlagsEx
_worldPacket.WriteUInt32(QuestFlags[2]); // FlagsEx
_worldPacket.WriteUInt32(SuggestedPartyMembers); _worldPacket.WriteUInt32(SuggestedPartyMembers);
_worldPacket.WriteInt32(LearnSpells.Count); _worldPacket.WriteInt32(LearnSpells.Count);
_worldPacket.WriteInt32(DescEmotes.Count); _worldPacket.WriteInt32(DescEmotes.Count);
_worldPacket.WriteInt32(Objectives.Count); _worldPacket.WriteInt32(Objectives.Count);
_worldPacket.WriteInt32(QuestStartItemID); _worldPacket.WriteInt32(QuestStartItemID);
_worldPacket.WriteInt32(QuestSessionBonus); _worldPacket.WriteInt32(QuestSessionBonus);
_worldPacket.WriteInt32(QuestGiverCreatureID);
_worldPacket.WriteInt32(ConditionalDescriptionText.Count);
foreach (uint spell in LearnSpells) foreach (uint spell in LearnSpells)
_worldPacket.WriteUInt32(spell); _worldPacket.WriteUInt32(spell);
@@ -483,13 +504,16 @@ namespace Game.Networking.Packets
_worldPacket.WriteString(PortraitGiverName); _worldPacket.WriteString(PortraitGiverName);
_worldPacket.WriteString(PortraitTurnInText); _worldPacket.WriteString(PortraitTurnInText);
_worldPacket.WriteString(PortraitTurnInName); _worldPacket.WriteString(PortraitTurnInName);
foreach (ConditionalQuestText conditionalQuestText in ConditionalDescriptionText)
conditionalQuestText.Write(_worldPacket);
} }
public ObjectGuid QuestGiverGUID; public ObjectGuid QuestGiverGUID;
public ObjectGuid InformUnit; public ObjectGuid InformUnit;
public uint QuestID; public uint QuestID;
public int QuestPackageID; public int QuestPackageID;
public uint[] QuestFlags = new uint[2]; public uint[] QuestFlags = new uint[3];
public uint SuggestedPartyMembers; public uint SuggestedPartyMembers;
public QuestRewards Rewards = new(); public QuestRewards Rewards = new();
public List<QuestObjectiveSimple> Objectives = new(); public List<QuestObjectiveSimple> Objectives = new();
@@ -501,6 +525,7 @@ namespace Game.Networking.Packets
public int PortraitGiverModelSceneID; public int PortraitGiverModelSceneID;
public int QuestStartItemID; public int QuestStartItemID;
public int QuestSessionBonus; public int QuestSessionBonus;
public int QuestGiverCreatureID;
public string PortraitGiverText = ""; public string PortraitGiverText = "";
public string PortraitGiverName = ""; public string PortraitGiverName = "";
public string PortraitTurnInText = ""; public string PortraitTurnInText = "";
@@ -508,6 +533,7 @@ namespace Game.Networking.Packets
public string QuestTitle = ""; public string QuestTitle = "";
public string LogDescription = ""; public string LogDescription = "";
public string DescriptionText = ""; public string DescriptionText = "";
public List<ConditionalQuestText> ConditionalDescriptionText = new();
public bool DisplayPopup; public bool DisplayPopup;
public bool StartCheat; public bool StartCheat;
public bool AutoLaunched; public bool AutoLaunched;
@@ -526,6 +552,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(CompEmoteType); _worldPacket.WriteUInt32(CompEmoteType);
_worldPacket.WriteUInt32(QuestFlags[0]); _worldPacket.WriteUInt32(QuestFlags[0]);
_worldPacket.WriteUInt32(QuestFlags[1]); _worldPacket.WriteUInt32(QuestFlags[1]);
_worldPacket.WriteUInt32(QuestFlags[2]);
_worldPacket.WriteUInt32(SuggestPartyMembers); _worldPacket.WriteUInt32(SuggestPartyMembers);
_worldPacket.WriteInt32(MoneyToGet); _worldPacket.WriteInt32(MoneyToGet);
_worldPacket.WriteInt32(Collect.Count); _worldPacket.WriteInt32(Collect.Count);
@@ -547,8 +574,15 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(AutoLaunched); _worldPacket.WriteBit(AutoLaunched);
_worldPacket.FlushBits(); _worldPacket.FlushBits();
_worldPacket.WriteUInt32(QuestGiverCreatureID);
_worldPacket.WriteInt32(ConditionalCompletionText.Count);
_worldPacket.WriteBits(QuestTitle.GetByteCount(), 9); _worldPacket.WriteBits(QuestTitle.GetByteCount(), 9);
_worldPacket.WriteBits(CompletionText.GetByteCount(), 12); _worldPacket.WriteBits(CompletionText.GetByteCount(), 12);
_worldPacket.FlushBits();
foreach (ConditionalQuestText conditionalQuestText in ConditionalCompletionText)
conditionalQuestText.Write(_worldPacket);
_worldPacket.WriteString(QuestTitle); _worldPacket.WriteString(QuestTitle);
_worldPacket.WriteString(CompletionText); _worldPacket.WriteString(CompletionText);
@@ -565,9 +599,10 @@ namespace Game.Networking.Packets
public List<QuestObjectiveCollect> Collect = new(); public List<QuestObjectiveCollect> Collect = new();
public List<QuestCurrency> Currency = new(); public List<QuestCurrency> Currency = new();
public int StatusFlags; public int StatusFlags;
public uint[] QuestFlags = new uint[2]; public uint[] QuestFlags = new uint[3];
public string QuestTitle = ""; public string QuestTitle = "";
public string CompletionText = ""; public string CompletionText = "";
public List<ConditionalQuestText> ConditionalCompletionText = new();
} }
public class QuestGiverRequestReward : ClientPacket public class QuestGiverRequestReward : ClientPacket
@@ -937,6 +972,30 @@ namespace Game.Networking.Packets
} }
} }
public class ConditionalQuestText
{
public int PlayerConditionID;
public int QuestGiverCreatureID;
public string Text = "";
public ConditionalQuestText(int playerConditionID, int questGiverCreatureID, string text)
{
PlayerConditionID = playerConditionID;
QuestGiverCreatureID = questGiverCreatureID;
Text = text;
}
public void Write(WorldPacket data)
{
data.WriteInt32(PlayerConditionID);
data.WriteInt32(QuestGiverCreatureID);
data.WriteBits(Text.GetByteCount(), 12);
data.FlushBits();
data.WriteString(Text);
}
}
public class QuestInfo public class QuestInfo
{ {
public QuestInfo() public QuestInfo()
@@ -1008,7 +1067,10 @@ namespace Game.Networking.Packets
public int Expansion; public int Expansion;
public int ManagedWorldStateID; public int ManagedWorldStateID;
public int QuestSessionBonus; public int QuestSessionBonus;
public int QuestGiverCreatureID; // used to select ConditionalQuestText
public List<QuestObjective> Objectives = new(); public List<QuestObjective> Objectives = new();
public List<ConditionalQuestText> ConditionalQuestDescription = new();
public List<ConditionalQuestText> ConditionalQuestCompletionLog = new();
public uint[] RewardItems = new uint[SharedConst.QuestRewardItemCount]; public uint[] RewardItems = new uint[SharedConst.QuestRewardItemCount];
public uint[] RewardAmount = new uint[SharedConst.QuestRewardItemCount]; public uint[] RewardAmount = new uint[SharedConst.QuestRewardItemCount];
public int[] ItemDrop = new int[SharedConst.QuestItemDropCount]; public int[] ItemDrop = new int[SharedConst.QuestItemDropCount];
@@ -1144,6 +1206,7 @@ namespace Game.Networking.Packets
data.WriteUInt32(QuestID); data.WriteUInt32(QuestID);
data.WriteUInt32(QuestFlags[0]); // Flags data.WriteUInt32(QuestFlags[0]); // Flags
data.WriteUInt32(QuestFlags[1]); // FlagsEx data.WriteUInt32(QuestFlags[1]); // FlagsEx
data.WriteUInt32(QuestFlags[2]); // FlagsEx2
data.WriteUInt32(SuggestedPartyMembers); data.WriteUInt32(SuggestedPartyMembers);
data.WriteInt32(Emotes.Count); data.WriteInt32(Emotes.Count);
@@ -1167,7 +1230,7 @@ namespace Game.Networking.Packets
public uint SuggestedPartyMembers = 0; public uint SuggestedPartyMembers = 0;
public QuestRewards Rewards = new(); public QuestRewards Rewards = new();
public List<QuestDescEmote> Emotes = new(); public List<QuestDescEmote> Emotes = new();
public uint[] QuestFlags = new uint[2]; // Flags and FlagsEx public uint[] QuestFlags = new uint[3]; // Flags and FlagsEx
} }
public struct QuestObjectiveSimple public struct QuestObjectiveSimple
@@ -22,7 +22,7 @@ namespace Game.Networking.Packets
{ {
public class InitializeFactions : ServerPacket public class InitializeFactions : ServerPacket
{ {
const ushort FactionCount = 400; const ushort FactionCount = 443;
public InitializeFactions() : base(ServerOpcodes.InitializeFactions, ConnectionType.Instance) { } public InitializeFactions() : base(ServerOpcodes.InitializeFactions, ConnectionType.Instance) { }
@@ -30,7 +30,7 @@ namespace Game.Networking.Packets
{ {
for (ushort i = 0; i < FactionCount; ++i) for (ushort i = 0; i < FactionCount; ++i)
{ {
_worldPacket.WriteUInt8((byte)((ushort)FactionFlags[i] & 0xFF)); _worldPacket.WriteUInt16((ushort)((ushort)FactionFlags[i] & 0xFF));
_worldPacket.WriteInt32(FactionStandings[i]); _worldPacket.WriteInt32(FactionStandings[i]);
} }
@@ -72,7 +72,6 @@ namespace Game.Networking.Packets
public override void Write() public override void Write()
{ {
_worldPacket.WriteFloat(ReferAFriendBonus);
_worldPacket.WriteFloat(BonusFromAchievementSystem); _worldPacket.WriteFloat(BonusFromAchievementSystem);
_worldPacket.WriteInt32(Faction.Count); _worldPacket.WriteInt32(Faction.Count);
@@ -83,7 +82,6 @@ namespace Game.Networking.Packets
_worldPacket.FlushBits(); _worldPacket.FlushBits();
} }
public float ReferAFriendBonus;
public float BonusFromAchievementSystem; public float BonusFromAchievementSystem;
public List<FactionStandingData> Faction = new(); public List<FactionStandingData> Faction = new();
public bool ShowVisual; public bool ShowVisual;
+60 -36
View File
@@ -305,23 +305,13 @@ namespace Game.Networking.Packets
public override void Write() public override void Write()
{ {
_worldPacket.WriteInt32(SpellID.Count); _worldPacket.WriteInt32(ClientLearnedSpellData.Count);
_worldPacket.WriteInt32(Superceded.Count);
_worldPacket.WriteInt32(FavoriteSpellID.Count);
foreach (var spellId in SpellID) foreach (LearnedSpellInfo spell in ClientLearnedSpellData)
_worldPacket.WriteUInt32(spellId); spell.Write(_worldPacket);
foreach (var spellId in Superceded)
_worldPacket.WriteUInt32(spellId);
foreach (var spellId in FavoriteSpellID)
_worldPacket.WriteInt32(spellId);
} }
public List<uint> SpellID = new(); public List<LearnedSpellInfo> ClientLearnedSpellData = new();
public List<uint> Superceded = new();
public List<int> FavoriteSpellID = new();
} }
public class LearnedSpells : ServerPacket public class LearnedSpells : ServerPacket
@@ -330,22 +320,16 @@ namespace Game.Networking.Packets
public override void Write() public override void Write()
{ {
_worldPacket.WriteInt32(SpellID.Count); _worldPacket.WriteInt32(ClientLearnedSpellData.Count);
_worldPacket.WriteInt32(FavoriteSpellID.Count);
_worldPacket.WriteUInt32(SpecializationID); _worldPacket.WriteUInt32(SpecializationID);
foreach (uint spell in SpellID)
_worldPacket.WriteUInt32(spell);
foreach (int spell in FavoriteSpellID)
_worldPacket.WriteInt32(spell);
_worldPacket.WriteBit(SuppressMessaging); _worldPacket.WriteBit(SuppressMessaging);
_worldPacket.FlushBits(); _worldPacket.FlushBits();
foreach (LearnedSpellInfo spell in ClientLearnedSpellData)
spell.Write(_worldPacket);
} }
public List<uint> SpellID = new(); public List<LearnedSpellInfo> ClientLearnedSpellData = new();
public List<int> FavoriteSpellID = new();
public uint SpecializationID; public uint SpecializationID;
public bool SuppressMessaging; public bool SuppressMessaging;
} }
@@ -998,10 +982,12 @@ namespace Game.Networking.Packets
{ {
SpellClickUnitGuid = _worldPacket.ReadPackedGuid(); SpellClickUnitGuid = _worldPacket.ReadPackedGuid();
TryAutoDismount = _worldPacket.HasBit(); TryAutoDismount = _worldPacket.HasBit();
IsSoftInteract = _worldPacket.HasBit();
} }
public ObjectGuid SpellClickUnitGuid; public ObjectGuid SpellClickUnitGuid;
public bool TryAutoDismount; public bool TryAutoDismount;
public bool IsSoftInteract;
} }
class ResyncRunes : ServerPacket class ResyncRunes : ServerPacket
@@ -1520,7 +1506,7 @@ namespace Game.Networking.Packets
{ {
public void Read(WorldPacket data) public void Read(WorldPacket data)
{ {
Flags = (SpellCastTargetFlags)data.ReadBits<uint>(26); Flags = (SpellCastTargetFlags)data.ReadBits<uint>(28);
if (data.HasBit()) if (data.HasBit())
SrcLocation = new(); SrcLocation = new();
@@ -1552,7 +1538,7 @@ namespace Game.Networking.Packets
public void Write(WorldPacket data) public void Write(WorldPacket data)
{ {
data.WriteBits((uint)Flags, 26); data.WriteBits((uint)Flags, 28);
data.WriteBit(SrcLocation != null); data.WriteBit(SrcLocation != null);
data.WriteBit(DstLocation != null); data.WriteBit(DstLocation != null);
data.WriteBit(Orientation.HasValue); data.WriteBit(Orientation.HasValue);
@@ -1607,15 +1593,20 @@ namespace Game.Networking.Packets
public uint Quantity; public uint Quantity;
} }
public struct SpellOptionalReagent public struct SpellCraftingReagent
{ {
public int ItemID; public int ItemID;
public int Slot; public int DataSlotIndex;
public int Quantity;
public byte? Unknown_1000;
public void Read(WorldPacket data) public void Read(WorldPacket data)
{ {
ItemID = data.ReadInt32(); ItemID = data.ReadInt32();
Slot = data.ReadInt32(); DataSlotIndex = data.ReadInt32();
Quantity = data.ReadInt32();
if (data.HasBit())
Unknown_1000 = data.ReadUInt8();
} }
} }
@@ -1641,8 +1632,9 @@ namespace Game.Networking.Packets
public MissileTrajectoryRequest MissileTrajectory; public MissileTrajectoryRequest MissileTrajectory;
public MovementInfo MoveUpdate; public MovementInfo MoveUpdate;
public List<SpellWeight> Weight = new(); public List<SpellWeight> Weight = new();
public Array<SpellOptionalReagent> OptionalReagents = new(3); public Array<SpellCraftingReagent> OptionalReagents = new(3);
public Array<SpellExtraCurrencyCost> OptionalCurrencies = new(5 /*MAX_ITEM_EXT_COST_CURRENCIES*/); public Array<SpellExtraCurrencyCost> OptionalCurrencies = new(5 /*MAX_ITEM_EXT_COST_CURRENCIES*/);
public ulong? CraftingOrderID;
public ObjectGuid CraftingNPC; public ObjectGuid CraftingNPC;
public uint[] Misc = new uint[2]; public uint[] Misc = new uint[2];
@@ -1658,21 +1650,25 @@ namespace Game.Networking.Packets
MissileTrajectory.Read(data); MissileTrajectory.Read(data);
CraftingNPC = data.ReadPackedGuid(); CraftingNPC = data.ReadPackedGuid();
var optionalReagents = data.ReadUInt32();
var optionalCurrencies = data.ReadUInt32(); var optionalCurrencies = data.ReadUInt32();
var optionalReagents = data.ReadUInt32();
for (var i = 0; i < optionalReagents; ++i)
OptionalReagents[i].Read(data);
for (var i = 0; i < optionalCurrencies; ++i) for (var i = 0; i < optionalCurrencies; ++i)
OptionalCurrencies[i].Read(data); OptionalCurrencies[i].Read(data);
SendCastFlags = data.ReadBits<uint>(5); SendCastFlags = data.ReadBits<uint>(5);
bool hasMoveUpdate = data.HasBit(); bool hasMoveUpdate = data.HasBit();
bool hasCraftingOrderID = data.HasBit();
var weightCount = data.ReadBits<uint>(2); var weightCount = data.ReadBits<uint>(2);
Target.Read(data); Target.Read(data);
if (hasCraftingOrderID)
CraftingOrderID = data.ReadUInt64();
for (var i = 0; i < optionalReagents; ++i)
OptionalReagents[i].Read(data);
if (hasMoveUpdate) if (hasMoveUpdate)
MoveUpdate = MovementExtensions.ReadMovementInfo(data); MoveUpdate = MovementExtensions.ReadMovementInfo(data);
@@ -1884,6 +1880,34 @@ namespace Game.Networking.Packets
public SpellHealPrediction Predict; public SpellHealPrediction Predict;
} }
public struct LearnedSpellInfo
{
public uint SpellID;
public bool IsFavorite;
public int? field_8;
public int? Superceded;
public int? TraitDefinitionID;
public void Write(WorldPacket data)
{
data.WriteUInt32(SpellID);
data.WriteBit(IsFavorite);
data.WriteBit(field_8.HasValue);
data.WriteBit(Superceded.HasValue);
data.WriteBit(TraitDefinitionID.HasValue);
data.FlushBits();
if (field_8.HasValue)
data.WriteInt32(field_8.Value);
if (Superceded.HasValue)
data.WriteInt32(Superceded.Value);
if (TraitDefinitionID.HasValue)
data.WriteInt32(TraitDefinitionID.Value);
}
}
public struct SpellModifierData public struct SpellModifierData
{ {
public float ModifierValue; public float ModifierValue;
@@ -58,6 +58,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt16(MaxPlayerNameQueriesPerPacket); _worldPacket.WriteInt16(MaxPlayerNameQueriesPerPacket);
_worldPacket.WriteInt16(PlayerNameQueryTelemetryInterval); _worldPacket.WriteInt16(PlayerNameQueryTelemetryInterval);
_worldPacket.WriteUInt32((uint)PlayerNameQueryInterval.TotalSeconds);
foreach (GameRuleValuePair gameRuleValue in GameRuleValues) foreach (GameRuleValuePair gameRuleValue in GameRuleValues)
gameRuleValue.Write(_worldPacket); gameRuleValue.Write(_worldPacket);
@@ -70,6 +71,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(BpayStoreDisabledByParentalControls); _worldPacket.WriteBit(BpayStoreDisabledByParentalControls);
_worldPacket.WriteBit(ItemRestorationButtonEnabled); _worldPacket.WriteBit(ItemRestorationButtonEnabled);
_worldPacket.WriteBit(BrowserEnabled); _worldPacket.WriteBit(BrowserEnabled);
_worldPacket.WriteBit(SessionAlert.HasValue); _worldPacket.WriteBit(SessionAlert.HasValue);
_worldPacket.WriteBit(RAFSystem.Enabled); _worldPacket.WriteBit(RAFSystem.Enabled);
_worldPacket.WriteBit(RAFSystem.RecruitingEnabled); _worldPacket.WriteBit(RAFSystem.RecruitingEnabled);
@@ -78,6 +80,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(CommerceSystemEnabled); _worldPacket.WriteBit(CommerceSystemEnabled);
_worldPacket.WriteBit(TutorialsEnabled); _worldPacket.WriteBit(TutorialsEnabled);
_worldPacket.WriteBit(TwitterEnabled); _worldPacket.WriteBit(TwitterEnabled);
_worldPacket.WriteBit(Unk67); _worldPacket.WriteBit(Unk67);
_worldPacket.WriteBit(WillKickFromWorld); _worldPacket.WriteBit(WillKickFromWorld);
_worldPacket.WriteBit(KioskModeEnabled); _worldPacket.WriteBit(KioskModeEnabled);
@@ -86,6 +89,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(WarModeFeatureEnabled); _worldPacket.WriteBit(WarModeFeatureEnabled);
_worldPacket.WriteBit(ClubsEnabled); _worldPacket.WriteBit(ClubsEnabled);
_worldPacket.WriteBit(ClubsBattleNetClubTypeAllowed); _worldPacket.WriteBit(ClubsBattleNetClubTypeAllowed);
_worldPacket.WriteBit(ClubsCharacterClubTypeAllowed); _worldPacket.WriteBit(ClubsCharacterClubTypeAllowed);
_worldPacket.WriteBit(ClubsPresenceUpdateEnabled); _worldPacket.WriteBit(ClubsPresenceUpdateEnabled);
_worldPacket.WriteBit(VoiceChatDisabledByParentalControl); _worldPacket.WriteBit(VoiceChatDisabledByParentalControl);
@@ -94,10 +98,14 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(IsMuted); _worldPacket.WriteBit(IsMuted);
_worldPacket.WriteBit(ClubFinderEnabled); _worldPacket.WriteBit(ClubFinderEnabled);
_worldPacket.WriteBit(Unknown901CheckoutRelated); _worldPacket.WriteBit(Unknown901CheckoutRelated);
_worldPacket.WriteBit(TextToSpeechFeatureEnabled); _worldPacket.WriteBit(TextToSpeechFeatureEnabled);
_worldPacket.WriteBit(ChatDisabledByDefault); _worldPacket.WriteBit(ChatDisabledByDefault);
_worldPacket.WriteBit(ChatDisabledByPlayer); _worldPacket.WriteBit(ChatDisabledByPlayer);
_worldPacket.WriteBit(LFGListCustomRequiresAuthenticator); _worldPacket.WriteBit(LFGListCustomRequiresAuthenticator);
_worldPacket.WriteBit(AddonsDisabled);
_worldPacket.WriteBit(Unused1000);
_worldPacket.FlushBits(); _worldPacket.FlushBits();
{ {
@@ -164,6 +172,7 @@ namespace Game.Networking.Packets
public int ActiveSeason; // Currently active Classic season public int ActiveSeason; // Currently active Classic season
public short MaxPlayerNameQueriesPerPacket = 50; public short MaxPlayerNameQueriesPerPacket = 50;
public short PlayerNameQueryTelemetryInterval = 600; public short PlayerNameQueryTelemetryInterval = 600;
public TimeSpan PlayerNameQueryInterval = TimeSpan.FromSeconds(10);
public bool ItemRestorationButtonEnabled; public bool ItemRestorationButtonEnabled;
public bool CharUndeleteEnabled; // Implemented public bool CharUndeleteEnabled; // Implemented
public bool BpayStoreDisabledByParentalControls; public bool BpayStoreDisabledByParentalControls;
@@ -192,6 +201,8 @@ namespace Game.Networking.Packets
public bool ChatDisabledByDefault; public bool ChatDisabledByDefault;
public bool ChatDisabledByPlayer; public bool ChatDisabledByPlayer;
public bool LFGListCustomRequiresAuthenticator; public bool LFGListCustomRequiresAuthenticator;
public bool AddonsDisabled;
public bool Unused1000;
public SocialQueueConfig QuickJoinConfig; public SocialQueueConfig QuickJoinConfig;
public SquelchInfo Squelch; public SquelchInfo Squelch;
@@ -264,6 +275,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(Unk14); _worldPacket.WriteBit(Unk14);
_worldPacket.WriteBit(WillKickFromWorld); _worldPacket.WriteBit(WillKickFromWorld);
_worldPacket.WriteBit(IsExpansionPreorderInStore); _worldPacket.WriteBit(IsExpansionPreorderInStore);
_worldPacket.WriteBit(KioskModeEnabled); _worldPacket.WriteBit(KioskModeEnabled);
_worldPacket.WriteBit(CompetitiveModeEnabled); _worldPacket.WriteBit(CompetitiveModeEnabled);
_worldPacket.WriteBit(TrialBoostEnabled); _worldPacket.WriteBit(TrialBoostEnabled);
@@ -272,9 +284,12 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(LiveRegionCharacterCopyEnabled); _worldPacket.WriteBit(LiveRegionCharacterCopyEnabled);
_worldPacket.WriteBit(LiveRegionAccountCopyEnabled); _worldPacket.WriteBit(LiveRegionAccountCopyEnabled);
_worldPacket.WriteBit(LiveRegionKeyBindingsCopyEnabled); _worldPacket.WriteBit(LiveRegionKeyBindingsCopyEnabled);
_worldPacket.WriteBit(Unknown901CheckoutRelated); _worldPacket.WriteBit(Unknown901CheckoutRelated);
_worldPacket.WriteBit(EuropaTicketSystemStatus.HasValue); _worldPacket.WriteBit(EuropaTicketSystemStatus.HasValue);
_worldPacket.WriteBit(LaunchETA.HasValue); _worldPacket.WriteBit(LaunchETA.HasValue);
_worldPacket.WriteBit(AddonsDisabled);
_worldPacket.WriteBit(Unused1000);
_worldPacket.FlushBits(); _worldPacket.FlushBits();
if (EuropaTicketSystemStatus.HasValue) if (EuropaTicketSystemStatus.HasValue)
@@ -294,6 +309,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt32(GameRuleValues.Count); _worldPacket.WriteInt32(GameRuleValues.Count);
_worldPacket.WriteInt16(MaxPlayerNameQueriesPerPacket); _worldPacket.WriteInt16(MaxPlayerNameQueriesPerPacket);
_worldPacket.WriteInt16(PlayerNameQueryTelemetryInterval); _worldPacket.WriteInt16(PlayerNameQueryTelemetryInterval);
_worldPacket.WriteUInt32((uint)PlayerNameQueryInterval.TotalSeconds);
if (LaunchETA.HasValue) if (LaunchETA.HasValue)
_worldPacket.WriteInt32(LaunchETA.Value); _worldPacket.WriteInt32(LaunchETA.Value);
@@ -320,8 +336,10 @@ namespace Game.Networking.Packets
public bool LiveRegionCharacterListEnabled; // NYI public bool LiveRegionCharacterListEnabled; // NYI
public bool LiveRegionCharacterCopyEnabled; // NYI public bool LiveRegionCharacterCopyEnabled; // NYI
public bool LiveRegionAccountCopyEnabled; // NYI public bool LiveRegionAccountCopyEnabled; // NYI
public bool LiveRegionKeyBindingsCopyEnabled = false; public bool LiveRegionKeyBindingsCopyEnabled;
public bool Unknown901CheckoutRelated = false; // NYI public bool Unknown901CheckoutRelated; // NYI
public bool AddonsDisabled;
public bool Unused1000;
public EuropaTicketConfig? EuropaTicketSystemStatus; public EuropaTicketConfig? EuropaTicketSystemStatus;
public List<int> LiveRegionCharacterCopySourceRegions = new(); public List<int> LiveRegionCharacterCopySourceRegions = new();
public uint TokenPollTimeSeconds; // NYI public uint TokenPollTimeSeconds; // NYI
@@ -337,6 +355,7 @@ namespace Game.Networking.Packets
public List<GameRuleValuePair> GameRuleValues = new(); public List<GameRuleValuePair> GameRuleValues = new();
public short MaxPlayerNameQueriesPerPacket = 50; public short MaxPlayerNameQueriesPerPacket = 50;
public short PlayerNameQueryTelemetryInterval = 600; public short PlayerNameQueryTelemetryInterval = 600;
public TimeSpan PlayerNameQueryInterval = TimeSpan.FromSeconds(10);
public int? LaunchETA; public int? LaunchETA;
} }
@@ -368,12 +387,18 @@ namespace Game.Networking.Packets
{ {
_worldPacket.WriteBits(ServerTimeTZ.GetByteCount(), 7); _worldPacket.WriteBits(ServerTimeTZ.GetByteCount(), 7);
_worldPacket.WriteBits(GameTimeTZ.GetByteCount(), 7); _worldPacket.WriteBits(GameTimeTZ.GetByteCount(), 7);
_worldPacket.WriteBits(ServerRegionalTZ.GetByteCount(), 7);
_worldPacket.FlushBits();
_worldPacket.WriteString(ServerTimeTZ); _worldPacket.WriteString(ServerTimeTZ);
_worldPacket.WriteString(GameTimeTZ); _worldPacket.WriteString(GameTimeTZ);
_worldPacket.WriteString(ServerRegionalTZ);
} }
public string ServerTimeTZ; public string ServerTimeTZ;
public string GameTimeTZ; public string GameTimeTZ;
public string ServerRegionalTZ;
} }
public struct SavedThrottleObjectState public struct SavedThrottleObjectState
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2012-2020 CypherCore <http://github.com/CypherCore>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Constants;
using Game.Entities;
using System.Collections.Generic;
using System;
namespace Game.Networking.Packets
{
public struct TraitEntry
{
public int TraitNodeID;
public int TraitNodeEntryID;
public int Rank;
public int GrantedRanks;
public void Write(WorldPacket data)
{
data.WriteInt32(TraitNodeID);
data.WriteInt32(TraitNodeEntryID);
data.WriteInt32(Rank);
data.WriteInt32(GrantedRanks);
}
}
public class TraitConfig
{
public int ID;
public TraitConfigType Type;
public int ChrSpecializationID = 0;
public TraitCombatConfigFlags CombatConfigFlags;
public int LocalIdentifier; // Local to specialization
public int SkillLineID;
public int TraitSystemID;
public List<TraitEntry> Entries = new();
public string Name = "";
public void Write(WorldPacket data)
{
data.WriteInt32(ID);
data.WriteInt32((int)Type);
data.WriteInt32(Entries.Count);
switch (Type)
{
case TraitConfigType.Combat:
data.WriteInt32(ChrSpecializationID);
data.WriteInt32((int)CombatConfigFlags);
data.WriteInt32(LocalIdentifier);
break;
case TraitConfigType.Profession:
data.WriteInt32(SkillLineID);
break;
case TraitConfigType.Generic:
data.WriteInt32(TraitSystemID);
break;
default:
break;
}
foreach (TraitEntry traitEntry in Entries)
traitEntry.Write(data);
data.WriteBits(Name.GetByteCount(), 9);
data.FlushBits();
data.WriteString(Name);
}
}
}
@@ -69,21 +69,6 @@ namespace Game.Networking.Packets
public List<uint> NewAppearances = new(); public List<uint> NewAppearances = new();
} }
class TransmogrifyNPC : ServerPacket
{
public TransmogrifyNPC(ObjectGuid guid) : base(ServerOpcodes.TransmogrifyNpc, ConnectionType.Instance)
{
Guid = guid;
}
public override void Write()
{
_worldPacket.WritePackedGuid(Guid);
}
ObjectGuid Guid;
}
struct TransmogrifyItem struct TransmogrifyItem
{ {
public void Read(WorldPacket data) public void Read(WorldPacket data)
+121
View File
@@ -279,6 +279,93 @@ namespace Game
} }
} }
void LoadConditionalConditionalQuestDescription(SQLFields fields)
{
Locale locale = fields.Read<string>(4).ToEnum<Locale>();
if (locale >= Locale.Total)
{
Log.outError(LogFilter.Sql, $"Table `quest_description_conditional` has invalid locale {fields.Read<string>(4)} set for quest {fields.Read<uint>(0)}. Skipped.");
return;
}
QuestConditionalText text = ConditionalQuestDescription.Find(text => text.PlayerConditionId == fields.Read<int>(1) && text.QuestgiverCreatureId == fields.Read<int>(2));
if (text == null)
{
text = new();
ConditionalQuestDescription.Add(text);
}
text.PlayerConditionId = fields.Read<int>(1);
text.QuestgiverCreatureId = fields.Read<int>(2);
ObjectManager.AddLocaleString(fields.Read<string>(3), locale, text.Text);
}
void LoadConditionalConditionalRequestItemsText(SQLFields fields)
{
Locale locale = fields.Read<string>(4).ToEnum<Locale>();
if (locale >= Locale.Total)
{
Log.outError(LogFilter.Sql, $"Table `quest_request_items_conditional` has invalid locale {fields.Read<string>(4)} set for quest {fields.Read<uint>(0)}. Skipped.");
return;
}
QuestConditionalText text = ConditionalRequestItemsText.Find(text => text.PlayerConditionId == fields.Read<int>(1) && text.QuestgiverCreatureId == fields.Read<uint>(2));
if (text == null)
{
text = new();
ConditionalRequestItemsText.Add(text);
}
text.PlayerConditionId = fields.Read<int>(1);
text.QuestgiverCreatureId = fields.Read<int>(2);
ObjectManager.AddLocaleString(fields.Read<string>(3), locale, text.Text);
}
void LoadConditionalConditionalOfferRewardText(SQLFields fields)
{
Locale locale = fields.Read<string>(4).ToEnum<Locale>();
if (locale >= Locale.Total)
{
Log.outError(LogFilter.Sql, $"Table `quest_offer_reward_conditional` has invalid locale {fields.Read<string>(4)} set for quest {fields.Read<uint>(0)}. Skipped.");
return;
}
QuestConditionalText text = ConditionalOfferRewardText.Find(text => text.PlayerConditionId == fields.Read<int>(1) && text.QuestgiverCreatureId == fields.Read<uint>(2));
if (text == null)
{
text = new();
ConditionalOfferRewardText.Add(text);
}
text.PlayerConditionId = fields.Read<int>(1);
text.QuestgiverCreatureId = fields.Read<int>(2);
ObjectManager.AddLocaleString(fields.Read<string>(3), locale, text.Text);
}
void LoadConditionalConditionalQuestCompletionLog(SQLFields fields)
{
Locale locale = fields.Read<string>(4).ToEnum<Locale>();
if (locale >= Locale.Total)
{
Log.outError(LogFilter.Sql, $"Table `quest_completion_log_conditional` has invalid locale {fields.Read<string>(4)} set for quest {fields.Read<uint>(0)}. Skipped.");
return;
}
QuestConditionalText text = ConditionalQuestCompletionLog.Find(text => text.PlayerConditionId == fields.Read<int>(1) && text.QuestgiverCreatureId == fields.Read<uint>(2));
if (text == null)
{
text = new();
ConditionalQuestCompletionLog.Add(text);
}
text.PlayerConditionId = fields.Read<int>(1);
text.QuestgiverCreatureId = fields.Read<int>(2);
ObjectManager.AddLocaleString(fields.Read<string>(3), locale, text.Text);
}
public uint XPValue(Player player) public uint XPValue(Player player)
{ {
if (player) if (player)
@@ -498,6 +585,20 @@ namespace Game
response.Info.PortraitTurnInText = PortraitTurnInText; response.Info.PortraitTurnInText = PortraitTurnInText;
response.Info.PortraitTurnInName = PortraitTurnInName; response.Info.PortraitTurnInName = PortraitTurnInName;
response.Info.ConditionalQuestDescription = ConditionalQuestDescription.Select(text =>
{
string content = text.Text[(int)Locale.enUS];
ObjectManager.GetLocaleString(text.Text, loc, ref content);
return new ConditionalQuestText(text.PlayerConditionId, text.QuestgiverCreatureId, content);
}).ToList();
response.Info.ConditionalQuestCompletionLog = ConditionalQuestCompletionLog.Select(text =>
{
string content = text.Text[(int)Locale.enUS];
ObjectManager.GetLocaleString(text.Text, loc, ref content);
return new ConditionalQuestText(text.PlayerConditionId, text.QuestgiverCreatureId, content);
}).ToList();
if (loc != Locale.enUS) if (loc != Locale.enUS)
{ {
var questTemplateLocale = Global.ObjectMgr.GetQuestLocale(Id); var questTemplateLocale = Global.ObjectMgr.GetQuestLocale(Id);
@@ -596,6 +697,7 @@ namespace Game
response.Info.Expansion = Expansion; response.Info.Expansion = Expansion;
response.Info.ManagedWorldStateID = ManagedWorldStateID; response.Info.ManagedWorldStateID = ManagedWorldStateID;
response.Info.QuestSessionBonus = 0; //GetQuestSessionBonus(); // this is only sent while quest session is active response.Info.QuestSessionBonus = 0; //GetQuestSessionBonus(); // this is only sent while quest session is active
response.Info.QuestGiverCreatureID = 0; // only sent during npc interaction
foreach (QuestObjective questObjective in Objectives) foreach (QuestObjective questObjective in Objectives)
{ {
@@ -744,6 +846,12 @@ namespace Game
public string PortraitTurnInName = ""; public string PortraitTurnInName = "";
public string QuestCompletionLog = ""; public string QuestCompletionLog = "";
// quest_description_conditional
public List<QuestConditionalText> ConditionalQuestDescription = new();
// quest_completion_log_conditional
public List<QuestConditionalText> ConditionalQuestCompletionLog = new();
// quest_detais table // quest_detais table
public uint[] DetailsEmote = new uint[SharedConst.QuestEmoteCount]; public uint[] DetailsEmote = new uint[SharedConst.QuestEmoteCount];
public uint[] DetailsEmoteDelay = new uint[SharedConst.QuestEmoteCount]; public uint[] DetailsEmoteDelay = new uint[SharedConst.QuestEmoteCount];
@@ -755,11 +863,17 @@ namespace Game
public uint EmoteOnIncompleteDelay; public uint EmoteOnIncompleteDelay;
public string RequestItemsText = ""; public string RequestItemsText = "";
// quest_request_items_conditional
public List<QuestConditionalText> ConditionalRequestItemsText = new();
// quest_offer_reward table // quest_offer_reward table
public int[] OfferRewardEmote = new int[SharedConst.QuestEmoteCount]; public int[] OfferRewardEmote = new int[SharedConst.QuestEmoteCount];
public uint[] OfferRewardEmoteDelay = new uint[SharedConst.QuestEmoteCount]; public uint[] OfferRewardEmoteDelay = new uint[SharedConst.QuestEmoteCount];
public string OfferRewardText = ""; public string OfferRewardText = "";
// quest_offer_reward_conditional
public List<QuestConditionalText> ConditionalOfferRewardText = new();
// quest_template_addon table (custom data) // quest_template_addon table (custom data)
public uint MaxLevel { get; set; } public uint MaxLevel { get; set; }
public uint AllowableClasses { get; set; } public uint AllowableClasses { get; set; }
@@ -864,6 +978,13 @@ namespace Game
} }
} }
public class QuestConditionalText
{
public int PlayerConditionId;
public int QuestgiverCreatureId;
public StringArray Text = new((int)Locale.Total);
}
public class QuestObjective public class QuestObjective
{ {
public uint Id; public uint Id;
@@ -239,7 +239,6 @@ namespace Game
public void SendState(FactionState faction) public void SendState(FactionState faction)
{ {
SetFactionStanding setFactionStanding = new(); SetFactionStanding setFactionStanding = new();
setFactionStanding.ReferAFriendBonus = 0.0f;
setFactionStanding.BonusFromAchievementSystem = 0.0f; setFactionStanding.BonusFromAchievementSystem = 0.0f;
if (faction != null) if (faction != null)
setFactionStanding.Faction.Add(new FactionStandingData((int)faction.ReputationListID, faction.Standing)); setFactionStanding.Faction.Add(new FactionStandingData((int)faction.ReputationListID, faction.Standing));
+2 -2
View File
@@ -59,12 +59,12 @@ namespace Game.Scripting
// Using provided text, not from DB // Using provided text, not from DB
public static void AddGossipItemFor(Player player, GossipOptionNpc optionNpc, string text, uint sender, uint action) public static void AddGossipItemFor(Player player, GossipOptionNpc optionNpc, string text, uint sender, uint action)
{ {
player.PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, optionNpc, text, sender, action, "", 0); player.PlayerTalkClass.GetGossipMenu().AddMenuItem(0, -1, optionNpc, text, 0, GossipOptionFlags.None, null, false, 0, "", null, null, sender, action);
} }
// Using provided texts, not from DB // Using provided texts, not from DB
public static void AddGossipItemFor(Player player, GossipOptionNpc optionNpc, string text, uint sender, uint action, string popupText, uint popupMoney, bool coded) public static void AddGossipItemFor(Player player, GossipOptionNpc optionNpc, string text, uint sender, uint action, string popupText, uint popupMoney, bool coded)
{ {
player.PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, optionNpc, text, sender, action, popupText, popupMoney, coded); player.PlayerTalkClass.GetGossipMenu().AddMenuItem(0, -1, optionNpc, text, 0, GossipOptionFlags.None, null, coded, popupMoney, popupText, null, null, sender, action);
} }
// Uses gossip item info from DB // Uses gossip item info from DB
public static void AddGossipItemFor(Player player, uint gossipMenuID, uint gossipMenuItemID, uint sender, uint action) public static void AddGossipItemFor(Player player, uint gossipMenuID, uint gossipMenuItemID, uint sender, uint action)
+10 -2
View File
@@ -372,7 +372,7 @@ namespace Game
Values[WorldCfg.CharacterCreatingDisabledRacemask] = GetDefaultValue("CharacterCreating.Disabled.RaceMask", 0); Values[WorldCfg.CharacterCreatingDisabledRacemask] = GetDefaultValue("CharacterCreating.Disabled.RaceMask", 0);
Values[WorldCfg.CharacterCreatingDisabledClassmask] = GetDefaultValue("CharacterCreating.Disabled.ClassMask", 0); Values[WorldCfg.CharacterCreatingDisabledClassmask] = GetDefaultValue("CharacterCreating.Disabled.ClassMask", 0);
Values[WorldCfg.CharactersPerRealm] = GetDefaultValue("CharactersPerRealm", 50); Values[WorldCfg.CharactersPerRealm] = GetDefaultValue("CharactersPerRealm", 60);
if ((int)Values[WorldCfg.CharactersPerRealm] < 1 || (int)Values[WorldCfg.CharactersPerRealm] > 200) if ((int)Values[WorldCfg.CharactersPerRealm] < 1 || (int)Values[WorldCfg.CharactersPerRealm] > 200)
{ {
Log.outError(LogFilter.ServerLoading, "CharactersPerRealm ({0}) must be in range 1..200. Set to 200.", Values[WorldCfg.CharactersPerRealm]); Log.outError(LogFilter.ServerLoading, "CharactersPerRealm ({0}) must be in range 1..200. Set to 200.", Values[WorldCfg.CharactersPerRealm]);
@@ -380,14 +380,22 @@ namespace Game
} }
// must be after CharactersPerRealm // must be after CharactersPerRealm
Values[WorldCfg.CharactersPerAccount] = GetDefaultValue("CharactersPerAccount", 50); Values[WorldCfg.CharactersPerAccount] = GetDefaultValue("CharactersPerAccount", 60);
if ((int)Values[WorldCfg.CharactersPerAccount] < (int)Values[WorldCfg.CharactersPerRealm]) if ((int)Values[WorldCfg.CharactersPerAccount] < (int)Values[WorldCfg.CharactersPerRealm])
{ {
Log.outError(LogFilter.ServerLoading, "CharactersPerAccount ({0}) can't be less than CharactersPerRealm ({1}).", Values[WorldCfg.CharactersPerAccount], Values[WorldCfg.CharactersPerRealm]); Log.outError(LogFilter.ServerLoading, "CharactersPerAccount ({0}) can't be less than CharactersPerRealm ({1}).", Values[WorldCfg.CharactersPerAccount], Values[WorldCfg.CharactersPerRealm]);
Values[WorldCfg.CharactersPerAccount] = Values[WorldCfg.CharactersPerRealm]; Values[WorldCfg.CharactersPerAccount] = Values[WorldCfg.CharactersPerRealm];
} }
Values[WorldCfg.CharacterCreatingEvokersPerRealm] = GetDefaultValue("CharacterCreating.EvokersPerRealm", 1);
if ((int)Values[WorldCfg.CharacterCreatingEvokersPerRealm] < 0 || (int)Values[WorldCfg.CharacterCreatingEvokersPerRealm] > 10)
{
Log.outError(LogFilter.ServerLoading, $"CharacterCreating.EvokersPerRealm ({Values[WorldCfg.CharacterCreatingEvokersPerRealm]}) must be in range 0..10. Set to 1.");
Values[WorldCfg.CharacterCreatingEvokersPerRealm] = 1;
}
Values[WorldCfg.CharacterCreatingMinLevelForDemonHunter] = GetDefaultValue("CharacterCreating.MinLevelForDemonHunter", 0); Values[WorldCfg.CharacterCreatingMinLevelForDemonHunter] = GetDefaultValue("CharacterCreating.MinLevelForDemonHunter", 0);
Values[WorldCfg.CharacterCreatingMinLevelForEvoker] = GetDefaultValue("CharacterCreating.MinLevelForEvoker", 50);
Values[WorldCfg.CharacterCreatingDisableAlliedRaceAchievementRequirement] = GetDefaultValue("CharacterCreating.DisableAlliedRaceAchievementRequirement", false); Values[WorldCfg.CharacterCreatingDisableAlliedRaceAchievementRequirement] = GetDefaultValue("CharacterCreating.DisableAlliedRaceAchievementRequirement", false);
Values[WorldCfg.SkipCinematics] = GetDefaultValue("SkipCinematics", 0); Values[WorldCfg.SkipCinematics] = GetDefaultValue("SkipCinematics", 0);
+16 -17
View File
@@ -4763,6 +4763,11 @@ namespace Game.Spells
if (m_spellInfo.ExcludeCasterAuraSpell != 0 && unitCaster.HasAura(m_spellInfo.ExcludeCasterAuraSpell)) if (m_spellInfo.ExcludeCasterAuraSpell != 0 && unitCaster.HasAura(m_spellInfo.ExcludeCasterAuraSpell))
return SpellCastResult.CasterAurastate; return SpellCastResult.CasterAurastate;
if (m_spellInfo.CasterAuraType != 0 && !unitCaster.HasAuraType(m_spellInfo.CasterAuraType))
return SpellCastResult.CasterAurastate;
if (m_spellInfo.ExcludeCasterAuraType != 0 && unitCaster.HasAuraType(m_spellInfo.ExcludeCasterAuraType))
return SpellCastResult.CasterAurastate;
if (reqCombat && unitCaster.IsInCombat() && !m_spellInfo.CanBeUsedInCombat()) if (reqCombat && unitCaster.IsInCombat() && !m_spellInfo.CanBeUsedInCombat())
return SpellCastResult.AffectingCombat; return SpellCastResult.AffectingCombat;
} }
@@ -5589,21 +5594,15 @@ namespace Game.Spells
if (spellEffectInfo.Effect == SpellEffectName.ChangeBattlepetQuality) if (spellEffectInfo.Effect == SpellEffectName.ChangeBattlepetQuality)
{ {
var qualityRecord = CliDB.BattlePetBreedQualityStorage.Values.FirstOrDefault(a1 => a1.MaxQualityRoll < spellEffectInfo.BasePoints);
BattlePetBreedQuality quality = BattlePetBreedQuality.Poor; BattlePetBreedQuality quality = BattlePetBreedQuality.Poor;
switch (spellEffectInfo.BasePoints) if (qualityRecord != null)
{ quality = (BattlePetBreedQuality)qualityRecord.QualityEnum;
case 85:
quality = BattlePetBreedQuality.Rare;
break;
case 75:
quality = BattlePetBreedQuality.Uncommon;
break;
default:
// Ignore Epic Battle-Stones
break;
}
if (battlePet.PacketInfo.Quality >= (byte)quality) if (battlePet.PacketInfo.Quality >= (byte)quality)
return SpellCastResult.CantUpgradeBattlePet; return SpellCastResult.CantUpgradeBattlePet;
} }
if (spellEffectInfo.Effect == SpellEffectName.GrantBattlepetLevel || spellEffectInfo.Effect == SpellEffectName.GrantBattlepetExperience) if (spellEffectInfo.Effect == SpellEffectName.GrantBattlepetLevel || spellEffectInfo.Effect == SpellEffectName.GrantBattlepetExperience)
@@ -6634,21 +6633,21 @@ namespace Game.Spells
{ {
Item item = m_targets.GetItemTarget(); Item item = m_targets.GetItemTarget();
if (!item) if (!item)
return SpellCastResult.CantBeDisenchanted; return SpellCastResult.CantBeSalvaged;
// prevent disenchanting in trade slot // prevent disenchanting in trade slot
if (item.GetOwnerGUID() != player.GetGUID()) if (item.GetOwnerGUID() != player.GetGUID())
return SpellCastResult.CantBeDisenchanted; return SpellCastResult.CantBeSalvaged;
ItemTemplate itemProto = item.GetTemplate(); ItemTemplate itemProto = item.GetTemplate();
if (itemProto == null) if (itemProto == null)
return SpellCastResult.CantBeDisenchanted; return SpellCastResult.CantBeSalvaged;
ItemDisenchantLootRecord itemDisenchantLoot = item.GetDisenchantLoot(m_caster.ToPlayer()); ItemDisenchantLootRecord itemDisenchantLoot = item.GetDisenchantLoot(m_caster.ToPlayer());
if (itemDisenchantLoot == null) if (itemDisenchantLoot == null)
return SpellCastResult.CantBeDisenchanted; return SpellCastResult.CantBeSalvaged;
if (itemDisenchantLoot.SkillRequired > player.GetSkillValue(SkillType.Enchanting)) if (itemDisenchantLoot.SkillRequired > player.GetSkillValue(SkillType.Enchanting))
return SpellCastResult.LowCastlevel; return SpellCastResult.CantBeSalvagedSkill;
break; break;
} }
case SpellEffectName.Prospecting: case SpellEffectName.Prospecting:
+79 -37
View File
@@ -2127,30 +2127,7 @@ namespace Game.Spells
} }
// select enchantment duration // select enchantment duration
uint duration; uint duration = (uint)pEnchant.Duration;
// rogue family enchantments exception by duration
if (m_spellInfo.Id == 38615)
duration = 1800; // 30 mins
// other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
else if (m_spellInfo.SpellFamilyName == SpellFamilyNames.Rogue)
duration = 3600; // 1 hour
// shaman family enchantments
else if (m_spellInfo.SpellFamilyName == SpellFamilyNames.Shaman)
duration = 3600; // 30 mins
// other cases with this SpellVisual already selected
else if (m_spellInfo.GetSpellVisual() == 215)
duration = 1800; // 30 mins
// some fishing pole bonuses except Glow Worm which lasts full hour
else if (m_spellInfo.GetSpellVisual() == 563 && m_spellInfo.Id != 64401)
duration = 600; // 10 mins
else if (m_spellInfo.Id == 29702)
duration = 300; // 5 mins
else if (m_spellInfo.Id == 37360)
duration = 300; // 5 mins
// default case
else
duration = 3600; // 1 hour
// item can be in trade slot and have owner diff. from caster // item can be in trade slot and have owner diff. from caster
Player item_owner = itemTarget.GetOwner(); Player item_owner = itemTarget.GetOwner();
@@ -5208,19 +5185,11 @@ namespace Game.Spells
if (unitTarget == null || !unitTarget.IsCreature()) if (unitTarget == null || !unitTarget.IsCreature())
return; return;
var quality = BattlePetBreedQuality.Poor; var qualityRecord = CliDB.BattlePetBreedQualityStorage.Values.FirstOrDefault(a1 => a1.MaxQualityRoll < damage);
switch (damage)
{ BattlePetBreedQuality quality = BattlePetBreedQuality.Poor;
case 85: if (qualityRecord != null)
quality = BattlePetBreedQuality.Rare; quality = (BattlePetBreedQuality)qualityRecord.QualityEnum;
break;
case 75:
quality = BattlePetBreedQuality.Uncommon;
break;
default:
// Ignore Epic Battle-Stones
break;
}
playerCaster.GetSession().GetBattlePetMgr().ChangeBattlePetQuality(unitTarget.GetBattlePetCompanionGUID(), quality); playerCaster.GetSession().GetBattlePetMgr().ChangeBattlePetQuality(unitTarget.GetBattlePetCompanionGUID(), quality);
} }
@@ -5634,6 +5603,79 @@ namespace Game.Spells
player.GetSession().GetCollectionMgr().AddTransmogIllusion(illusionId); player.GetSession().GetCollectionMgr().AddTransmogIllusion(illusionId);
} }
[SpellEffectHandler(SpellEffectName.ModifyAuraStacks)]
void EffectModifyAuraStacks()
{
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
return;
Aura targetAura = unitTarget.GetAura(effectInfo.TriggerSpell);
if (targetAura == null)
return;
switch (effectInfo.MiscValue)
{
case 0:
targetAura.ModStackAmount(damage);
break;
case 1:
targetAura.SetStackAmount((byte)damage);
break;
default:
break;
}
}
[SpellEffectHandler(SpellEffectName.ModifyCooldown)]
void EffectModifyCooldown()
{
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
return;
unitTarget.GetSpellHistory().ModifyCooldown(effectInfo.TriggerSpell, TimeSpan.FromMilliseconds(damage));
}
[SpellEffectHandler(SpellEffectName.ModifyCooldowns)]
void EffectModifyCooldowns()
{
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
return;
unitTarget.GetSpellHistory().ModifyCoooldowns(itr =>
{
SpellInfo spellOnCooldown = Global.SpellMgr.GetSpellInfo(itr.SpellId, Difficulty.None);
if ((int)spellOnCooldown.SpellFamilyName != effectInfo.MiscValue)
return false;
int bitIndex = effectInfo.MiscValueB - 1;
if (bitIndex < 0 || bitIndex >= sizeof(uint) * 8)
return false;
FlagArray128 reqFlag = new();
reqFlag[bitIndex / 32] = 1u << (bitIndex % 32);
return (spellOnCooldown.SpellFamilyFlags & reqFlag);
}, TimeSpan.FromMilliseconds(damage));
}
[SpellEffectHandler(SpellEffectName.ModifyCooldownsByCategory)]
void EffectModifyCooldownsByCategory()
{
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
return;
unitTarget.GetSpellHistory().ModifyCoooldowns(itr => Global.SpellMgr.GetSpellInfo(itr.SpellId, Difficulty.None).CategoryId == effectInfo.MiscValue, TimeSpan.FromMilliseconds(damage));
}
[SpellEffectHandler(SpellEffectName.ModifyCharges)]
void EffectModifySpellCharges()
{
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
return;
for (int i = 0; i < damage; ++i)
unitTarget.GetSpellHistory().RestoreCharge((uint)effectInfo.MiscValue);
}
} }
public class DispelableAura public class DispelableAura
+26 -9
View File
@@ -514,20 +514,25 @@ namespace Game.Spells
} }
} }
public void ModifySpellCooldown(uint spellId, TimeSpan offset, bool withoutCategoryCooldown = false) public void ModifySpellCooldown(uint spellId, TimeSpan cooldownMod, bool withoutCategoryCooldown)
{ {
var cooldownEntry = _spellCooldowns.LookupByKey(spellId); var cooldownEntry = _spellCooldowns.LookupByKey(spellId);
if (offset.TotalMilliseconds == 0 || cooldownEntry == null) if (cooldownMod.TotalMilliseconds == 0 || cooldownEntry == null)
return; return;
ModifySpellCooldown(cooldownEntry, cooldownMod, withoutCategoryCooldown);
}
void ModifySpellCooldown(CooldownEntry cooldownEntry, TimeSpan cooldownMod, bool withoutCategoryCooldown)
{
DateTime now = GameTime.GetSystemTime(); DateTime now = GameTime.GetSystemTime();
cooldownEntry.CooldownEnd += offset; cooldownEntry.CooldownEnd += cooldownMod;
if (cooldownEntry.CategoryId != 0) if (cooldownEntry.CategoryId != 0)
{ {
if (!withoutCategoryCooldown) if (!withoutCategoryCooldown)
cooldownEntry.CategoryEnd += offset; cooldownEntry.CategoryEnd += cooldownMod;
// Because category cooldown existence is tied to regular cooldown, we cannot allow a situation where regular cooldown is shorter than category // Because category cooldown existence is tied to regular cooldown, we cannot allow a situation where regular cooldown is shorter than category
if (cooldownEntry.CooldownEnd < cooldownEntry.CategoryEnd) if (cooldownEntry.CooldownEnd < cooldownEntry.CategoryEnd)
@@ -535,9 +540,9 @@ namespace Game.Spells
} }
if (cooldownEntry.CooldownEnd <= now) if (cooldownEntry.CooldownEnd <= now)
{ {
_categoryCooldowns.Remove(cooldownEntry.CategoryId); _categoryCooldowns.Remove(cooldownEntry.CategoryId);
_spellCooldowns.Remove(spellId); _spellCooldowns.Remove(cooldownEntry.SpellId);
} }
Player playerOwner = GetPlayerOwner(); Player playerOwner = GetPlayerOwner();
@@ -545,8 +550,8 @@ namespace Game.Spells
{ {
ModifyCooldown modifyCooldown = new(); ModifyCooldown modifyCooldown = new();
modifyCooldown.IsPet = _owner != playerOwner; modifyCooldown.IsPet = _owner != playerOwner;
modifyCooldown.SpellID = spellId; modifyCooldown.SpellID = cooldownEntry.SpellId;
modifyCooldown.DeltaTime = (int)offset.TotalMilliseconds; modifyCooldown.DeltaTime = (int)cooldownMod.TotalMilliseconds;
modifyCooldown.WithoutCategoryCooldown = withoutCategoryCooldown; modifyCooldown.WithoutCategoryCooldown = withoutCategoryCooldown;
playerOwner.SendPacket(modifyCooldown); playerOwner.SendPacket(modifyCooldown);
} }
@@ -569,7 +574,16 @@ namespace Game.Spells
else else
ModifySpellCooldown(spellInfo.Id, cooldownMod, withoutCategoryCooldown); ModifySpellCooldown(spellInfo.Id, cooldownMod, withoutCategoryCooldown);
} }
public void ModifyCoooldowns(Func<CooldownEntry, bool> predicate, TimeSpan cooldownMod, bool withoutCategoryCooldown = false)
{
foreach (var cooldownEntry in _spellCooldowns.Values.ToList())
{
if (predicate(cooldownEntry))
ModifySpellCooldown(cooldownEntry, cooldownMod, withoutCategoryCooldown);
}
}
public void ResetCooldown(uint spellId, bool update = false) public void ResetCooldown(uint spellId, bool update = false)
{ {
var entry = _spellCooldowns.LookupByKey(spellId); var entry = _spellCooldowns.LookupByKey(spellId);
@@ -635,6 +649,9 @@ namespace Game.Spells
if (_spellCooldowns.ContainsKey(spellInfo.Id)) if (_spellCooldowns.ContainsKey(spellInfo.Id))
return true; return true;
if (spellInfo.CooldownAuraSpellId != 0 && _owner.HasAura(spellInfo.CooldownAuraSpellId))
return true;
uint category = 0; uint category = 0;
GetCooldownDurations(spellInfo, itemId, ref category); GetCooldownDurations(spellInfo, itemId, ref category);
+58 -3
View File
@@ -120,6 +120,10 @@ namespace Game.Spells
TargetAuraSpell = _aura.TargetAuraSpell; TargetAuraSpell = _aura.TargetAuraSpell;
ExcludeCasterAuraSpell = _aura.ExcludeCasterAuraSpell; ExcludeCasterAuraSpell = _aura.ExcludeCasterAuraSpell;
ExcludeTargetAuraSpell = _aura.ExcludeTargetAuraSpell; ExcludeTargetAuraSpell = _aura.ExcludeTargetAuraSpell;
CasterAuraType = (AuraType)_aura.CasterAuraType;
TargetAuraType = (AuraType)_aura.TargetAuraType;
ExcludeCasterAuraType = (AuraType)_aura.ExcludeCasterAuraType;
ExcludeTargetAuraType = (AuraType)_aura.ExcludeTargetAuraType;
} }
RequiredAreasID = -1; RequiredAreasID = -1;
@@ -161,6 +165,7 @@ namespace Game.Spells
RecoveryTime = _cooldowns.RecoveryTime; RecoveryTime = _cooldowns.RecoveryTime;
CategoryRecoveryTime = _cooldowns.CategoryRecoveryTime; CategoryRecoveryTime = _cooldowns.CategoryRecoveryTime;
StartRecoveryTime = _cooldowns.StartRecoveryTime; StartRecoveryTime = _cooldowns.StartRecoveryTime;
CooldownAuraSpellId = _cooldowns.AuraSpellID;
} }
EquippedItemClass = ItemClass.None; EquippedItemClass = ItemClass.None;
@@ -2855,7 +2860,7 @@ namespace Game.Spells
} }
Log.outError(LogFilter.Spells, $"SpellInfo.CalcPowerCost: Unknown power type '{power.PowerType}' in spell {Id}"); Log.outError(LogFilter.Spells, $"SpellInfo.CalcPowerCost: Unknown power type '{power.PowerType}' in spell {Id}");
return default; return null;
} }
} }
} }
@@ -2863,6 +2868,36 @@ namespace Game.Spells
else else
{ {
powerCost = (int)power.OptionalCost; powerCost = (int)power.OptionalCost;
if (power.OptionalCostPct != 0)
{
switch (power.PowerType)
{
// health as power used
case PowerType.Health:
powerCost += (int)MathFunctions.CalculatePct(unitCaster.GetMaxHealth(), power.OptionalCostPct);
break;
case PowerType.Mana:
powerCost += (int)MathFunctions.CalculatePct(unitCaster.GetCreateMana(), power.OptionalCostPct);
break;
case PowerType.AlternatePower:
Log.outError(LogFilter.Spells, $"SpellInfo::CalcPowerCost: Unsupported power type POWER_ALTERNATE_POWER in spell {Id} for optional cost percent");
return null;
default:
{
var powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(power.PowerType);
if (powerTypeEntry != null)
{
powerCost += (int)MathFunctions.CalculatePct(powerTypeEntry.MaxBasePower, power.OptionalCostPct);
break;
}
Log.outError(LogFilter.Spells, $"SpellInfo::CalcPowerCost: Unknown power type '{power.PowerType}' in spell {Id} for optional cost percent");
return null;
}
}
}
powerCost += unitCaster.GetTotalAuraModifier(AuraType.ModAdditionalPowerCost, aurEff => powerCost += unitCaster.GetTotalAuraModifier(AuraType.ModAdditionalPowerCost, aurEff =>
{ {
return aurEff.GetMiscValue() == (int)power.PowerType && aurEff.IsAffectingSpell(this); return aurEff.GetMiscValue() == (int)power.PowerType && aurEff.IsAffectingSpell(this);
@@ -3964,11 +3999,16 @@ namespace Game.Spells
public uint TargetAuraSpell { get; set; } public uint TargetAuraSpell { get; set; }
public uint ExcludeCasterAuraSpell { get; set; } public uint ExcludeCasterAuraSpell { get; set; }
public uint ExcludeTargetAuraSpell { get; set; } public uint ExcludeTargetAuraSpell { get; set; }
public AuraType CasterAuraType { get; set; }
public AuraType TargetAuraType { get; set; }
public AuraType ExcludeCasterAuraType { get; set; }
public AuraType ExcludeTargetAuraType { get; set; }
public SpellCastTimesRecord CastTimeEntry { get; set; } public SpellCastTimesRecord CastTimeEntry { get; set; }
public uint RecoveryTime { get; set; } public uint RecoveryTime { get; set; }
public uint CategoryRecoveryTime { get; set; } public uint CategoryRecoveryTime { get; set; }
public uint StartRecoveryCategory { get; set; } public uint StartRecoveryCategory { get; set; }
public uint StartRecoveryTime { get; set; } public uint StartRecoveryTime { get; set; }
public uint CooldownAuraSpellId { get; set; }
public SpellInterruptFlags InterruptFlags { get; set; } public SpellInterruptFlags InterruptFlags { get; set; }
public SpellAuraInterruptFlags AuraInterruptFlags { get; set; } public SpellAuraInterruptFlags AuraInterruptFlags { get; set; }
public SpellAuraInterruptFlags2 AuraInterruptFlags2 { get; set; } public SpellAuraInterruptFlags2 AuraInterruptFlags2 { get; set; }
@@ -4777,8 +4817,23 @@ namespace Game.Spells
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 285 SPELL_EFFECT_MODIFY_KEYSTONE_2 new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 285 SPELL_EFFECT_MODIFY_KEYSTONE_2
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 286 SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 286 SPELL_EFFECT_GRANT_BATTLEPET_EXPERIENCE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 287 SPELL_EFFECT_SET_GARRISON_FOLLOWER_LEVEL new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 287 SPELL_EFFECT_SET_GARRISON_FOLLOWER_LEVEL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 288 SPELL_EFFECT_288 new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 288 SPELL_EFFECT_CRAFT_ITEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 289 SPELL_EFFECT_289 new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 289 SPELL_EFFECT_MODIFY_AURA_STACKS
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 290 SPELL_EFFECT_MODIFY_COOLDOWN
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 291 SPELL_EFFECT_MODIFY_COOLDOWNS
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 292 SPELL_EFFECT_MODIFY_COOLDOWNS_BY_CATEGORY
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 293 SPELL_EFFECT_MODIFY_CHARGES
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 294 SPELL_EFFECT_CRAFT_LOOT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 295 SPELL_EFFECT_SALVAGE_ITEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 296 SPELL_EFFECT_CRAFT_SALVAGE_ITEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 297 SPELL_EFFECT_RECRAFT_ITEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 298 SPELL_EFFECT_CANCEL_ALL_PRIVATE_CONVERSATIONS
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 299 SPELL_EFFECT_299
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 300 SPELL_EFFECT_300
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 301 SPELL_EFFECT_CRAFT_ENCHANT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.None), // 302 SPELL_EFFECT_GATHERING
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
}; };
#region Fields #region Fields
+52 -46
View File
@@ -2471,17 +2471,19 @@ namespace Game.Entities
"AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, AttributesEx8, AttributesEx9, AttributesEx10, AttributesEx11, AttributesEx12, AttributesEx13, " + "AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, AttributesEx8, AttributesEx9, AttributesEx10, AttributesEx11, AttributesEx12, AttributesEx13, " +
//19 20 21 22 23 24 25 26 27 //19 20 21 22 23 24 25 26 27
"AttributesEx14, Stances, StancesNot, Targets, TargetCreatureType, RequiresSpellFocus, FacingCasterFlags, CasterAuraState, TargetAuraState, " + "AttributesEx14, Stances, StancesNot, Targets, TargetCreatureType, RequiresSpellFocus, FacingCasterFlags, CasterAuraState, TargetAuraState, " +
//28 29 30 31 32 33 34 //28 29 30 31 32 33
"ExcludeCasterAuraState, ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, CastingTimeIndex, " + "ExcludeCasterAuraState, ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, " +
//35 36 37 38 39 40 41 //34 35 36 37 38
"CasterAuraType, TargetAuraType, ExcludeCasterAuraType, ExcludeTargetAuraType, CastingTimeIndex, " +
//39 40 41 42 43 44 45
"RecoveryTime, CategoryRecoveryTime, StartRecoveryCategory, StartRecoveryTime, InterruptFlags, AuraInterruptFlags1, AuraInterruptFlags2, " + "RecoveryTime, CategoryRecoveryTime, StartRecoveryCategory, StartRecoveryTime, InterruptFlags, AuraInterruptFlags1, AuraInterruptFlags2, " +
//42 43 44 45 46 47 48 49 50 51 52 //46 47 48 49 50 51 52 53 54 55 56
"ChannelInterruptFlags1, ChannelInterruptFlags2, ProcFlags, ProcFlags2, ProcChance, ProcCharges, ProcCooldown, ProcBasePPM, MaxLevel, BaseLevel, SpellLevel, " + "ChannelInterruptFlags1, ChannelInterruptFlags2, ProcFlags, ProcFlags2, ProcChance, ProcCharges, ProcCooldown, ProcBasePPM, MaxLevel, BaseLevel, SpellLevel, " +
//53 54 55 56 57 58 59 60 61 //57 58 59 60 61 62 63 64 65
"DurationIndex, RangeIndex, Speed, LaunchDelay, StackAmount, EquippedItemClass, EquippedItemSubClassMask, EquippedItemInventoryTypeMask, ContentTuningId, " + "DurationIndex, RangeIndex, Speed, LaunchDelay, StackAmount, EquippedItemClass, EquippedItemSubClassMask, EquippedItemInventoryTypeMask, ContentTuningId, " +
//62 63 64 65 66 67 68 69 70 71 //66 67 68 69 70 71 72 73 74 75
"SpellName, ConeAngle, ConeWidth, MaxTargetLevel, MaxAffectedTargets, SpellFamilyName, SpellFamilyFlags1, SpellFamilyFlags2, SpellFamilyFlags3, SpellFamilyFlags4, " + "SpellName, ConeAngle, ConeWidth, MaxTargetLevel, MaxAffectedTargets, SpellFamilyName, SpellFamilyFlags1, SpellFamilyFlags2, SpellFamilyFlags3, SpellFamilyFlags4, " +
//72 73 74 75 76 //76 77 78 79 80
"DmgClass, PreventionType, AreaGroupId, SchoolMask, ChargeCategoryId FROM serverside_spell"); "DmgClass, PreventionType, AreaGroupId, SchoolMask, ChargeCategoryId FROM serverside_spell");
if (!spellsResult.IsEmpty()) if (!spellsResult.IsEmpty())
@@ -2496,7 +2498,7 @@ namespace Game.Entities
continue; continue;
} }
mServersideSpellNames.Add(new(spellId, spellsResult.Read<string>(62))); mServersideSpellNames.Add(new(spellId, spellsResult.Read<string>(66)));
SpellInfo spellInfo = new(mServersideSpellNames.Last().Name, difficulty, spellEffects[(spellId, difficulty)]); SpellInfo spellInfo = new(mServersideSpellNames.Last().Name, difficulty, spellEffects[(spellId, difficulty)]);
spellInfo.CategoryId = spellsResult.Read<uint>(2); spellInfo.CategoryId = spellsResult.Read<uint>(2);
@@ -2531,44 +2533,48 @@ namespace Game.Entities
spellInfo.TargetAuraSpell = spellsResult.Read<uint>(31); spellInfo.TargetAuraSpell = spellsResult.Read<uint>(31);
spellInfo.ExcludeCasterAuraSpell = spellsResult.Read<uint>(32); spellInfo.ExcludeCasterAuraSpell = spellsResult.Read<uint>(32);
spellInfo.ExcludeTargetAuraSpell = spellsResult.Read<uint>(33); spellInfo.ExcludeTargetAuraSpell = spellsResult.Read<uint>(33);
spellInfo.CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(spellsResult.Read<uint>(34)); spellInfo.CasterAuraType = (AuraType)spellsResult.Read<int>(34);
spellInfo.RecoveryTime = spellsResult.Read<uint>(35); spellInfo.TargetAuraType = (AuraType)spellsResult.Read<int>(35);
spellInfo.CategoryRecoveryTime = spellsResult.Read<uint>(36); spellInfo.ExcludeCasterAuraType = (AuraType)spellsResult.Read<int>(36);
spellInfo.StartRecoveryCategory = spellsResult.Read<uint>(37); spellInfo.ExcludeTargetAuraType = (AuraType)spellsResult.Read<int>(37);
spellInfo.StartRecoveryTime = spellsResult.Read<uint>(38); spellInfo.CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(spellsResult.Read<uint>(38));
spellInfo.InterruptFlags = (SpellInterruptFlags)spellsResult.Read<uint>(39); spellInfo.RecoveryTime = spellsResult.Read<uint>(39);
spellInfo.AuraInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(40); spellInfo.CategoryRecoveryTime = spellsResult.Read<uint>(40);
spellInfo.AuraInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(41); spellInfo.StartRecoveryCategory = spellsResult.Read<uint>(41);
spellInfo.ChannelInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(42); spellInfo.StartRecoveryTime = spellsResult.Read<uint>(42);
spellInfo.ChannelInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(43); spellInfo.InterruptFlags = (SpellInterruptFlags)spellsResult.Read<uint>(43);
spellInfo.ProcFlags = new ProcFlagsInit(spellsResult.Read<int>(44), spellsResult.Read<int>(45)); spellInfo.AuraInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(44);
spellInfo.ProcChance = spellsResult.Read<uint>(46); spellInfo.AuraInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(45);
spellInfo.ProcCharges = spellsResult.Read<uint>(47); spellInfo.ChannelInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(46);
spellInfo.ProcCooldown = spellsResult.Read<uint>(48); spellInfo.ChannelInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(47);
spellInfo.ProcBasePPM = spellsResult.Read<float>(49); spellInfo.ProcFlags = new ProcFlagsInit(spellsResult.Read<int>(48), spellsResult.Read<int>(49));
spellInfo.MaxLevel = spellsResult.Read<uint>(50); spellInfo.ProcChance = spellsResult.Read<uint>(50);
spellInfo.BaseLevel = spellsResult.Read<uint>(51); spellInfo.ProcCharges = spellsResult.Read<uint>(51);
spellInfo.SpellLevel = spellsResult.Read<uint>(52); spellInfo.ProcCooldown = spellsResult.Read<uint>(52);
spellInfo.DurationEntry = CliDB.SpellDurationStorage.LookupByKey(spellsResult.Read<uint>(53)); spellInfo.ProcBasePPM = spellsResult.Read<float>(53);
spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(spellsResult.Read<uint>(54)); spellInfo.MaxLevel = spellsResult.Read<uint>(54);
spellInfo.Speed = spellsResult.Read<float>(55); spellInfo.BaseLevel = spellsResult.Read<uint>(55);
spellInfo.LaunchDelay = spellsResult.Read<float>(56); spellInfo.SpellLevel = spellsResult.Read<uint>(56);
spellInfo.StackAmount = spellsResult.Read<uint>(57); spellInfo.DurationEntry = CliDB.SpellDurationStorage.LookupByKey(spellsResult.Read<uint>(57));
spellInfo.EquippedItemClass = (ItemClass)spellsResult.Read<int>(58); spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(spellsResult.Read<uint>(58));
spellInfo.EquippedItemSubClassMask = spellsResult.Read<int>(59); spellInfo.Speed = spellsResult.Read<float>(59);
spellInfo.EquippedItemInventoryTypeMask = spellsResult.Read<int>(60); spellInfo.LaunchDelay = spellsResult.Read<float>(60);
spellInfo.ContentTuningId = spellsResult.Read<uint>(61); spellInfo.StackAmount = spellsResult.Read<uint>(61);
spellInfo.ConeAngle = spellsResult.Read<float>(63); spellInfo.EquippedItemClass = (ItemClass)spellsResult.Read<int>(62);
spellInfo.Width = spellsResult.Read<float>(64); spellInfo.EquippedItemSubClassMask = spellsResult.Read<int>(63);
spellInfo.MaxTargetLevel = spellsResult.Read<uint>(65); spellInfo.EquippedItemInventoryTypeMask = spellsResult.Read<int>(64);
spellInfo.MaxAffectedTargets = spellsResult.Read<uint>(66); spellInfo.ContentTuningId = spellsResult.Read<uint>(65);
spellInfo.SpellFamilyName = (SpellFamilyNames)spellsResult.Read<uint>(67); spellInfo.ConeAngle = spellsResult.Read<float>(67);
spellInfo.SpellFamilyFlags = new FlagArray128(spellsResult.Read<uint>(68), spellsResult.Read<uint>(69), spellsResult.Read<uint>(70), spellsResult.Read<uint>(71)); spellInfo.Width = spellsResult.Read<float>(68);
spellInfo.DmgClass = (SpellDmgClass)spellsResult.Read<uint>(72); spellInfo.MaxTargetLevel = spellsResult.Read<uint>(69);
spellInfo.PreventionType = (SpellPreventionType)spellsResult.Read<uint>(73); spellInfo.MaxAffectedTargets = spellsResult.Read<uint>(70);
spellInfo.RequiredAreasID = spellsResult.Read<int>(74); spellInfo.SpellFamilyName = (SpellFamilyNames)spellsResult.Read<uint>(71);
spellInfo.SchoolMask = (SpellSchoolMask)spellsResult.Read<uint>(75); spellInfo.SpellFamilyFlags = new FlagArray128(spellsResult.Read<uint>(72), spellsResult.Read<uint>(73), spellsResult.Read<uint>(74), spellsResult.Read<uint>(75));
spellInfo.ChargeCategoryId = spellsResult.Read<uint>(76); spellInfo.DmgClass = (SpellDmgClass)spellsResult.Read<uint>(76);
spellInfo.PreventionType = (SpellPreventionType)spellsResult.Read<uint>(77);
spellInfo.RequiredAreasID = spellsResult.Read<int>(78);
spellInfo.SchoolMask = (SpellSchoolMask)spellsResult.Read<uint>(79);
spellInfo.ChargeCategoryId = spellsResult.Read<uint>(80);
mSpellInfoMap.Add(spellId, spellInfo); mSpellInfoMap.Add(spellId, spellInfo);
-3
View File
@@ -890,9 +890,6 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu addon..."); Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu addon...");
Global.ObjectMgr.LoadGossipMenuAddon(); Global.ObjectMgr.LoadGossipMenuAddon();
Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu item addon...");
Global.ObjectMgr.LoadGossipMenuItemAddon();
Log.outInfo(LogFilter.ServerLoading, "Loading Creature trainers..."); Log.outInfo(LogFilter.ServerLoading, "Loading Creature trainers...");
Global.ObjectMgr.LoadCreatureTrainers(); // must be after LoadGossipMenuItems Global.ObjectMgr.LoadCreatureTrainers(); // must be after LoadGossipMenuItems
+4 -2
View File
@@ -3281,8 +3281,10 @@ namespace Scripts.Spells.Generic
Unit target = GetHitUnit(); Unit target = GetHitUnit();
if (target) if (target)
{ {
SpiritHealerConfirm spiritHealerConfirm = new(); NPCInteractionOpenResult spiritHealerConfirm = new();
spiritHealerConfirm.Unit = target.GetGUID(); spiritHealerConfirm.Npc = target.GetGUID();
spiritHealerConfirm.InteractionType = PlayerInteractionType.SpiritHealer;
spiritHealerConfirm.Success = true;
originalCaster.SendPacket(spiritHealerConfirm); originalCaster.SendPacket(spiritHealerConfirm);
} }
} }
+19 -2
View File
@@ -806,9 +806,17 @@ CharactersPerAccount = 50
# CharactersPerRealm # CharactersPerRealm
# Description: Limit number of characters per account on this realm. # Description: Limit number of characters per account on this realm.
# Range: 1-200 # Range: 1-200
# Default: 50 # Default: 60
CharactersPerRealm = 50 CharactersPerRealm = 60
#
# CharacterCreating.EvokersPerRealm
# Description: Limit number of death knight characters per account on this realm.
# Range: 1-60
# Default: 1
CharacterCreating.EvokersPerRealm = 1
# #
# CharacterCreating.MinLevelForDemonHunter # CharacterCreating.MinLevelForDemonHunter
@@ -819,6 +827,15 @@ CharactersPerRealm = 50
CharacterCreating.MinLevelForDemonHunter = 0 CharacterCreating.MinLevelForDemonHunter = 0
#
# CharacterCreating.MinLevelForEvoker
# Description: Limit creating demon hunters only for account with another
# character of specific level.
# Default: 50 - (Enabled, Requires at least another level 50 character)
# 0 - (Disabled, No requirement)
CharacterCreating.MinLevelForEvoker = 0
# #
# CharacterCreating.DisableAlliedRaceAchievementRequirement # CharacterCreating.DisableAlliedRaceAchievementRequirement
# Description: Disable achievement requirements for allied race character creation # Description: Disable achievement requirements for allied race character creation