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}"
PlayerHasVanillaCollectorsEdition = 326, // Player has Vanilla Collector's Edition
PlayerHasItemWithKeystoneLevelModifierEqualOrGreaterThan = 327,
PlayerMythicPlusRatingInDisplaySeasonEqualOrGreaterThan = 329, /*NYI*/ // Player has Mythic+ Rating of at least "{#DungeonScore}" in {DisplaySeason}
MythicPlusRatingIsInTop01Percent = 334, // top 0.1% rating
PlayerMythicPlusLadderRatingInDisplaySeasonEqualOrGreaterThan = 333, /*NYI*/ // Player has Mythic+ Ladder Rating of at least "{#DungeonScore}" in {DisplaySeason}
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
@@ -714,7 +725,11 @@ namespace Framework.Constants
MythicPlusRatingAttained = 230, /*NYI*/ // (Player) Mythic+ Rating "{#DungeonScore}" attained
SpentTalentPoint = 231, /*NYI*/ // (Player) spent talent point
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
}
@@ -77,60 +77,64 @@ namespace Framework.Constants
CharCreateNewPlayer = 50,
CharCreateNameReservationFull = 51,
CharCreateClassTrialNewcomer = 52,
CharCreateClassTrialThrottleHour = 53,
CharCreateClassTrialThrottleDay = 54,
CharCreateClassTrialThrottleWeek = 55,
CharCreateClassTrialThrottleAccount = 56,
CharCreateDracthyrDuplicate = 52,
CharCreateDracthyrLevelRequirement = 53,
CharCreateDeathknightDuplicate = 54,
CharCreateDeathknightLevelRequirement = 55,
CharCreateClassTrialNewcomer = 56,
CharCreateClassTrialThrottleHour = 57,
CharCreateClassTrialThrottleDay = 58,
CharCreateClassTrialThrottleWeek = 59,
CharCreateClassTrialThrottleAccount = 60,
CharDeleteInProgress = 57,
CharDeleteSuccess = 58,
CharDeleteFailed = 59,
CharDeleteFailedLockedForTransfer = 60,
CharDeleteFailedGuildLeader = 61,
CharDeleteFailedArenaCaptain = 62,
CharDeleteFailedHasHeirloomOrMail = 63,
CharDeleteFailedUpgradeInProgress = 64,
CharDeleteFailedHasWowToken = 65,
CharDeleteFailedVasTransactionInProgress = 66,
CharDeleteFailedCommunityOwner = 67,
CharDeleteInProgress = 61,
CharDeleteSuccess = 62,
CharDeleteFailed = 63,
CharDeleteFailedLockedForTransfer = 64,
CharDeleteFailedGuildLeader = 65,
CharDeleteFailedArenaCaptain = 66,
CharDeleteFailedHasHeirloomOrMail = 67,
CharDeleteFailedUpgradeInProgress = 68,
CharDeleteFailedHasWowToken = 69,
CharDeleteFailedVasTransactionInProgress = 70,
CharDeleteFailedCommunityOwner = 71,
CharLoginInProgress = 68,
CharLoginSuccess = 69,
CharLoginNoWorld = 70,
CharLoginDuplicateCharacter = 71,
CharLoginNoInstances = 72,
CharLoginFailed = 73,
CharLoginDisabled = 74,
CharLoginNoCharacter = 75,
CharLoginLockedForTransfer = 76,
CharLoginLockedByBilling = 77,
CharLoginLockedByMobileAh = 78,
CharLoginTemporaryGmLock = 79,
CharLoginLockedByCharacterUpgrade = 80,
CharLoginLockedByRevokedCharacterUpgrade = 81,
CharLoginLockedByRevokedVasTransaction = 82,
CharLoginLockedByRestriction = 83,
CharLoginLockedForRealmPlaytype = 84,
CharLoginInProgress = 72,
CharLoginSuccess = 73,
CharLoginNoWorld = 74,
CharLoginDuplicateCharacter = 75,
CharLoginNoInstances = 76,
CharLoginFailed = 77,
CharLoginDisabled = 78,
CharLoginNoCharacter = 79,
CharLoginLockedForTransfer = 80,
CharLoginLockedByBilling = 81,
CharLoginLockedByMobileAh = 82,
CharLoginTemporaryGmLock = 83,
CharLoginLockedByCharacterUpgrade = 84,
CharLoginLockedByRevokedCharacterUpgrade = 85,
CharLoginLockedByRevokedVasTransaction = 86,
CharLoginLockedByRestriction = 87,
CharLoginLockedForRealmPlaytype = 88,
CharNameSuccess = 85,
CharNameFailure = 86,
CharNameNoName = 87,
CharNameTooShort = 88,
CharNameTooLong = 89,
CharNameInvalidCharacter = 90,
CharNameMixedLanguages = 91,
CharNameProfane = 92,
CharNameReserved = 93,
CharNameInvalidApostrophe = 94,
CharNameMultipleApostrophes = 95,
CharNameThreeConsecutive = 96,
CharNameInvalidSpace = 97,
CharNameConsecutiveSpaces = 98,
CharNameRussianConsecutiveSilentCharacters = 99,
CharNameRussianSilentCharacterAtBeginningOrEnd = 100,
CharNameDeclensionDoesntMatchBaseName = 101,
CharNameSpacesDisallowed = 102,
CharNameSuccess = 89,
CharNameFailure = 90,
CharNameNoName = 91,
CharNameTooShort = 92,
CharNameTooLong = 93,
CharNameInvalidCharacter = 94,
CharNameMixedLanguages = 95,
CharNameProfane = 96,
CharNameReserved = 97,
CharNameInvalidApostrophe = 98,
CharNameMultipleApostrophes = 99,
CharNameThreeConsecutive = 100,
CharNameInvalidSpace = 101,
CharNameConsecutiveSpaces = 102,
CharNameRussianConsecutiveSilentCharacters = 103,
CharNameRussianSilentCharacterAtBeginningOrEnd = 104,
CharNameDeclensionDoesntMatchBaseName = 105,
CharNameSpacesDisallowed = 106
}
public enum CharacterUndeleteResult
+96 -3
View File
@@ -1491,7 +1491,13 @@ namespace Framework.Constants
OneshotStandVar0 = 991,
OneshotFlycustomspell01 = 992,
OneshotSpelleffectDecay = 993,
CreatureSpecial = 994,
StateCreatureSpecial = 994,
OneshotWareact01 = 1001,
OneshotFlycustomspell04 = 1004,
OneshotTalkSubdued = 1005,
StateEmotetalk = 1006,
StateWainteraction = 1007,
OneshotTakeOffStart = 1009,
}
public enum GlyphSlotType
@@ -1715,6 +1721,75 @@ namespace Framework.Constants
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
{
Disabled = 0x01 // Prestige levels with this flag won't be included to calculate max prestigelevel.
@@ -2129,6 +2204,23 @@ namespace Framework.Constants
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
{
None = 0x00,
@@ -2426,7 +2518,7 @@ namespace Framework.Constants
ContentTuningPvpItemLevelDamageScaling = 15,
}
public enum BattlePetSpeciesFlags : ushort
public enum BattlePetSpeciesFlags : int
{
NoRename = 0x01,
WellKnown = 0x02,
@@ -2443,7 +2535,8 @@ namespace Framework.Constants
NoLicenseRequired = 0x1000,
AddsAllowedWithBoss = 0x2000,
HideUntilLearned = 0x4000,
MatchPlayerHighPetLevel = 0x8000
MatchPlayerHighPetLevel = 0x8000,
NoWildPetAddsAllowed = 0x10000,
}
public enum SpellVisualEffectNameType
+27 -13
View File
@@ -13,7 +13,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
namespace Framework.Constants
{
@@ -48,24 +48,24 @@ namespace Framework.Constants
{
None = 0, // White chat bubble. Default
Vendor = 1, // Brown bag
TaxiNode = 2, // White wing
Taxinode = 2, // White wing
Trainer = 3, // Brown book
SpiritHealer = 4, // Golden interaction wheel (with red center)
Binder = 5, // Golden interaction wheel
Banker = 6, // Brown bag (with gold coin in lower corner)
PetitionVendor = 7, // White chat bubble (with "..." inside)
TabardVendor = 8, // White tabard
BattleMaster = 9, // Two crossed swords
Battlemaster = 9, // Two crossed swords
Auctioneer = 10, // Stack of gold coins
TalentMaster = 11, // White chat bubble
StableMaster = 12, // White chat bubble
Stablemaster = 12, // White chat bubble
PetSpecializationMaster = 13, /*DEPRECATED*/ // White chat bubble
GuildBanker = 14, /*NYI*/ // White chat bubble
SpellClick = 15, /*NYI*/ // White chat bubble
GuildBanker = 14, // White chat bubble
Spellclick = 15, // White chat bubble
DisableXPGain = 16, // White chat bubble
EnableXPGain = 17, // 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
ArtifactRespec = 21, /*NYI*/ // White chat bubble
CemeterySelect = 22, /*DEPRECATED*/ // White chat bubble
@@ -73,25 +73,33 @@ namespace Framework.Constants
GlyphMaster = 24, /*DEPRECATED*/ // White chat bubble
QueueScenario = 25, /*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
GarrisonTradeskill = 29, /*NYI*/ // White chat bubble
GarrisonTradeskillNpc = 29, /*NYI*/ // White chat bubble
GarrisonRecruitment = 30, /*NYI*/ // White chat bubble
AdventureMap = 31, /*NYI*/ // White chat bubble
GarrisonTalent = 32, // White chat bubble
ContributionCollector = 33, /*NYI*/ // White chat bubble
Transmogrify = 34, // Purple helm
AzeriteRespec = 35, // White chat bubble
IslandsMission = 36, /*NYI*/ // White chat bubble
IslandsMissionNpc = 36, /*NYI*/ // White chat bubble
UIItemInteraction = 37, /*NYI*/ // White chat bubble
WorldMap = 38, /*NYI*/ // White chat bubble
Soulbind = 39, /*NYI*/ // White chat bubble
ChromieTime = 40, /*NYI*/ // White chat bubble
CovenantPreview = 41, /*NYI*/ // White chat bubble
ChromieTimeNpc = 40, /*NYI*/ // White chat bubble
CovenantPreviewNpc = 41, /*NYI*/ // White chat bubble
RuneforgeLegendaryCrafting = 42, /*NYI*/ // White chat bubble
NewPlayerGuide = 43, /*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
}
@@ -162,4 +170,10 @@ namespace Framework.Constants
Item = 0,
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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
using System;
namespace Framework.Constants
{
@@ -60,6 +62,7 @@ namespace Framework.Constants
WorldPvp = 4,
}
[Flags]
public enum GroupFlags
{
None = 0x00,
@@ -71,6 +74,7 @@ namespace Framework.Constants
OnePersonParty = 0x020, // Script_IsOnePersonParty()
EveryoneAssistant = 0x040, // Script_IsEveryoneAssistant()
GuildGroup = 0x100,
CrossFaction = 0x200,
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 const byte BagStart = 19;
public const byte BagEnd = 23;
public const byte ItemStart = 23;
public const byte ItemEnd = 51;
public const byte BagStart = 30;
public const byte BagEnd = 34;
public const byte BankItemStart = 51;
public const byte BankItemEnd = 79;
public const byte BankBagStart = 79;
public const byte BankBagEnd = 86;
public const byte ReagentBagStart = 34;
public const byte ReagentBagEnd = 35;
public const byte BuyBackStart = 86;
public const byte BuyBackEnd = 98;
public const byte ReagentStart = 98;
public const byte ReagentEnd = 196;
public const byte ChildEquipmentStart = 196;
public const byte ChildEquipmentEnd = 199;
public const byte ItemStart = 35;
public const byte ItemEnd = 63;
public const byte BankItemStart = 63;
public const byte BankItemEnd = 91;
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 DefaultSize = 16;
}
enum EquipableSpellSlots
{
OffensiveSlot1 = 211,
OffensiveSlot2 = 212,
OffensiveSlot3 = 213,
OffensiveSlot4 = 214,
UtilitySlot1 = 215,
DefensiveSlot1 = 216,
MobilitySlot1 = 217
}
public struct EquipmentSlot
{
public const byte Start = 0;
@@ -462,6 +498,20 @@ namespace Framework.Constants
RaidHeroicExtended = 84,
RaidMythicExtended = 85,
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
}
@@ -537,7 +587,13 @@ namespace Framework.Constants
RangedRight = 26,
Quiver = 27,
Relic = 28,
Max = 29
ProfessionTool = 29,
ProfessionGear = 30,
EquipableSpellOffensive = 31,
EquipableSpellUtility = 32,
EquipableSpellDefensive = 33,
EquipableSpellMobility = 34,
Max
}
public enum VisibleEquipmentSlot
@@ -586,7 +642,8 @@ namespace Framework.Constants
Glyph = 16,
BattlePets = 17,
WowToken = 18,
Max = 19
Profession = 19,
Max
}
public enum ItemSubClassConsumable
@@ -601,7 +658,7 @@ namespace Framework.Constants
Bandage = 7,
ConsumableOther = 8,
VantusRune = 9,
Max = 10
Max
}
public enum ItemSubClassContainer
@@ -617,7 +674,8 @@ namespace Framework.Constants
InscriptionContainer = 8,
TackleContainer = 9,
CookingContainer = 10,
Max = 11
ReagentContainer = 11,
Max
}
public enum ItemSubClassWeapon
@@ -664,7 +722,7 @@ namespace Framework.Constants
Other = 9,
MultipleStats = 10,
ArtifactRelic = 11,
Max = 12
Max
}
public enum ItemSubClassArmor
@@ -681,14 +739,15 @@ namespace Framework.Constants
Totem = 9,
Sigil = 10,
Relic = 11,
Max = 12
Max
}
public enum ItemSubClassReagent
{
Reagent = 0,
Keystone = 1,
Max = 2
ContextToken = 2,
Max
}
public enum ItemSubClassProjectile
@@ -698,7 +757,7 @@ namespace Framework.Constants
Arrow = 2,
Bullet = 3,
Thrown = 4, // Obsolete
Max = 5
Max
}
public enum ItemSubClassTradeGoods
@@ -721,7 +780,9 @@ namespace Framework.Constants
WeaponEnchantment = 15,
Inscription = 16,
ExplosivesDevices = 17,
Max = 18
OptionalReagent = 18,
FinishingReagent = 19,
Max
}
public enum ItemSubclassItemEnhancement
@@ -740,7 +801,8 @@ namespace Framework.Constants
Weapon = 11,
TwoHandedWeapon = 12,
ShieldOffHand = 13,
Max = 14
Misc = 14,
Max
}
public enum ItemSubClassRecipe
@@ -804,7 +866,8 @@ namespace Framework.Constants
Holiday = 3,
Other = 4,
Mount = 5,
Max = 6
MountEquipment = 6,
Max
}
public enum ItemSubClassGlyph
@@ -836,6 +899,25 @@ namespace Framework.Constants
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
{
Poor = 0, //Grey
@@ -1144,6 +1226,11 @@ namespace Framework.Constants
NotInNPE = 110,// Not available during the tutorial
ItemCooldown = 111,// Item is not ready yet.
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
+11
View File
@@ -111,4 +111,15 @@ namespace Framework.Constants
Master = 3, // Item Can Only Be Distributed By Group Loot Master.
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,
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 const Expansion CurrentExpansion = Expansion.ShadowLands;
public const Expansion CurrentExpansion = Expansion.Dragonflight;
public const int MaxTalentTiers = 7;
public const int MaxTalentColumns = 3;
@@ -35,7 +35,7 @@ namespace Framework.Constants
public const int ReqPrimaryTreeTalents = 31;
public const int ExploredZonesSize = 192;
public const ulong MaxMoneyAmount = 99999999999UL;
public const int MaxActionButtons = 132;
public const int MaxActionButtons = 180;
public const int MaxActionButtonActionValue = 0x00FFFFFF + 1;
public const int MaxDailyQuests = 25;
@@ -55,8 +55,6 @@ namespace Framework.Constants
public const int MaxRunes = 7;
public const int MaxRechargingRunes = 3;
public const int CustomDisplaySize = 3;
public const int ArtifactsAllWeaponsGeneralWeaponEquippedPassive = 197886;
public const int MaxArtifactTier = 1;
@@ -152,7 +150,9 @@ namespace Framework.Constants
Com = 0x08, // Commentator
Dev = 0x10,
BossSound = 0x20, // Plays "RaidBossEmoteWarning" sound on raid boss emote/whisper
Mobile = 0x40
Mobile = 0x40,
Guide = 0x1000,
Newcomer = 0x2000
}
public enum DrunkenState
@@ -558,7 +558,7 @@ namespace Framework.Constants
// first slot for item stored (in any way in player items data)
Start = 0,
// last+1 slot for item stored (in any way in player items data)
End = 199,
End = 218,
Count = (End - Start)
}
@@ -753,7 +753,9 @@ namespace Framework.Constants
FailedAffectingCombat = 5,
FailedCantRemoveTalent = 6,
FailedCantDoThatChallengeModeActive = 7,
FailedRestArea = 8
FailedRestArea = 8,
UnspentTalentPoints = 9,
InPvpMatch = 10
}
public enum TutorialsFlag
File diff suppressed because it is too large Load Diff
@@ -528,10 +528,34 @@ namespace Framework.Constants
ModHealingTakenFromCaster = 504,
ModPlayerChoiceRerolls = 505, // NYI
DisableInertia = 506, // NYI
Unk507 = 507,
ModDamageTakenFromCasterByLabel = 507,
Unk508 = 508,
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
}
@@ -473,8 +473,8 @@ namespace Framework.Constants
BadTargets = 13,
PvpTargetWhileUnflagged = 14,
CantBeCharmed = 15,
CantBeDisenchanted = 16,
CantBeDisenchantedSkill = 17,
CantBeSalvaged = 16,
CantBeSalvagedSkill = 17,
CantBeEnchanted = 18,
CantBeMilled = 19,
CantBeProspected = 20,
@@ -767,13 +767,16 @@ namespace Framework.Constants
IneligibleWeaponAppearance = 307,
PlayerCondition = 308,
NotWhileChromieTimed = 309,
OptionalReagents = 310,
CraftingReagents = 310,
SpectatorOrCommentator = 311,
SoulbindConduitLearnFailedInvalidCovenant = 312,
ShadowlandsRidingRequirement = 313,
NotInMageTower = 314,
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)
SpellCastOk = Success
@@ -1357,7 +1360,45 @@ namespace Framework.Constants
YouHaveOtherWaysToSummonPocopoc = 635, // You Have Other Ways To Summon Pocopoc While In Zereth Mortis.
RequiresMoreSyllabicRecall = 636, // Requires More Syllabic Recall.
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.
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
@@ -1468,7 +1509,8 @@ namespace Framework.Constants
Unk78 = 78,
Unk91 = 91,
Unk100 = 100,
DemonHunter = 107
DemonHunter = 107,
Evoker = 224
}
[Flags]
@@ -2434,8 +2476,23 @@ namespace Framework.Constants
ModifyKeystone2 = 285,
GrantBattlepetExperience = 286,
SetGarrisonFollowerLevel = 287,
Unk288 = 288,
Unk289 = 289,
CraftItem = 288, // Miscvalue[0] = Craftingdataid
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
}
+2 -1
View File
@@ -164,6 +164,7 @@ namespace Framework.Constants
ArcaneCharges,
Fury,
Pain,
Essence,
Armor, // ARMOR..RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
ResistanceHoly,
ResistanceFire,
@@ -183,7 +184,7 @@ namespace Framework.Constants
ResistanceStart = Armor,
ResistanceEnd = ResistanceArcane + 1,
PowerStart = Mana,
PowerEnd = Pain + 1
PowerEnd = Essence + 1
}
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 = ?");
// 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
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 = ?");
// 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
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");
// ChrCustomizationChoice.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE, "SELECT Name, ID, ChrCustomizationOptionID, ChrCustomizationReqID, SortOrder, UiOrderIndex, " +
"Flags, AddedInPatch, SwatchColor1, SwatchColor2 FROM chr_customization_choice");
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE, "SELECT Name, ID, ChrCustomizationOptionID, ChrCustomizationReqID, " +
"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 = ?");
// ChrCustomizationDisplayInfo.db2
@@ -240,7 +240,7 @@ namespace Framework.Database
// ChrCustomizationElement.db2
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_ELEMENT, "SELECT ID, ChrCustomizationChoiceID, RelatedChrCustomizationChoiceID, " +
"ChrCustomizationGeosetID, ChrCustomizationSkinnedModelID, ChrCustomizationMaterialID, ChrCustomizationBoneSetID, " +
"ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID, ChrCustItemGeoModifyID FROM chr_customization_element");
"ChrCustomizationCondModelID, ChrCustomizationDisplayInfoID, ChrCustItemGeoModifyID, ChrCustomizationVoiceID FROM chr_customization_element");
// ChrCustomizationOption.db2
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 = ?");
// 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
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");
// 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
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, " +
"HelmetAnimScalingRaceID, TransmogrifyDisabledSlotMask, UnalteredVisualCustomizationRaceID, AlteredFormCustomizeOffsetFallback1, " +
"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");
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, " +
@@ -285,7 +286,7 @@ namespace Framework.Database
" WHERE locale = ?");
// 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
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, " +
"AnimReplacementSetID, Flags, StateSpellVisualKitID, PlayerOverrideScale, PetInstanceScale, UnarmedWeaponType, MountPoofSpellVisualKitID, " +
"DissolveEffectID, Gender, DissolveOutEffectID, CreatureModelMinLod, TextureVariationFileDataID1, TextureVariationFileDataID2, " +
"TextureVariationFileDataID3 FROM creature_display_info");
"TextureVariationFileDataID3, TextureVariationFileDataID4 FROM creature_display_info");
// CreatureDisplayInfoExtra.db2
PrepareStatement(HotfixStatements.SEL_CREATURE_DISPLAY_INFO_EXTRA, "SELECT ID, DisplayRaceID, DisplaySexID, DisplayClassID, Flags, BakeMaterialResourcesID, " +
@@ -348,14 +349,15 @@ namespace Framework.Database
// CurrencyTypes.db2
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 = ?");
// Curve.db2
PrepareStatement(HotfixStatements.SEL_CURVE, "SELECT ID, Type, Flags FROM curve");
// 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
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 = ?");
// DungeonEncounter.db2
PrepareStatement(HotfixStatements.SEL_DUNGEON_ENCOUNTER, "SELECT Name, ID, MapID, DifficultyID, OrderIndex, CompleteWorldStateID, Bit, CreatureDisplayID, " +
"Flags, SpellIconFileID, Faction FROM dungeon_encounter");
PrepareStatement(HotfixStatements.SEL_DUNGEON_ENCOUNTER, "SELECT Name, ID, MapID, DifficultyID, OrderIndex, CompleteWorldStateID, Bit, Flags, " +
"SpellIconFileID, Faction FROM dungeon_encounter");
PrepareStatement(HotfixStatements.SEL_DUNGEON_ENCOUNTER_LOCALE, "SELECT ID, Name_lang FROM dungeon_encounter_locale WHERE locale = ?");
// DurabilityCosts.db2
@@ -404,15 +406,15 @@ namespace Framework.Database
// Faction.db2
PrepareStatement(HotfixStatements.SEL_FACTION, "SELECT ID, ReputationRaceMask1, ReputationRaceMask2, ReputationRaceMask3, ReputationRaceMask4, Name, " +
"Description, ReputationIndex, ParentFactionID, Expansion, FriendshipRepID, Flags, ParagonFactionID, ReputationClassMask1, " +
"ReputationClassMask2, ReputationClassMask3, ReputationClassMask4, ReputationFlags1, ReputationFlags2, ReputationFlags3, ReputationFlags4, " +
"ReputationBase1, ReputationBase2, ReputationBase3, ReputationBase4, ReputationMax1, ReputationMax2, ReputationMax3, ReputationMax4, " +
"ParentFactionMod1, ParentFactionMod2, ParentFactionCap1, ParentFactionCap2 FROM faction");
"Description, ReputationIndex, ParentFactionID, Expansion, FriendshipRepID, Flags, ParagonFactionID, RenownFactionID, RenownCurrencyID, " +
"ReputationClassMask1, ReputationClassMask2, ReputationClassMask3, ReputationClassMask4, ReputationFlags1, ReputationFlags2, " +
"ReputationFlags3, ReputationFlags4, ReputationBase1, ReputationBase2, ReputationBase3, ReputationBase4, ReputationMax1, ReputationMax2, " +
"ReputationMax3, ReputationMax4, ParentFactionMod1, ParentFactionMod2, ParentFactionCap1, ParentFactionCap2 FROM faction");
PrepareStatement(HotfixStatements.SEL_FACTION_LOCALE, "SELECT ID, Name_lang, Description_lang FROM faction_locale WHERE locale = ?");
// FactionTemplate.db2
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
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
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
PrepareStatement(HotfixStatements.SEL_GUILD_COLOR_BACKGROUND, "SELECT ID, Red, Blue, Green FROM guild_color_background");
@@ -556,7 +563,7 @@ namespace Framework.Database
// Item.db2
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
PrepareStatement(HotfixStatements.SEL_ITEM_APPEARANCE, "SELECT ID, DisplayType, ItemDisplayInfoID, DefaultIconFileDataID, UiOrder, PlayerConditionID FROM item_appearance");
@@ -684,14 +691,14 @@ namespace Framework.Database
"StatPercentageOfSocket2, StatPercentageOfSocket3, StatPercentageOfSocket4, StatPercentageOfSocket5, StatPercentageOfSocket6, " +
"StatPercentageOfSocket7, StatPercentageOfSocket8, StatPercentageOfSocket9, StatPercentageOfSocket10, StatPercentEditor1, StatPercentEditor2, " +
"StatPercentEditor3, StatPercentEditor4, StatPercentEditor5, StatPercentEditor6, StatPercentEditor7, StatPercentEditor8, StatPercentEditor9, " +
"StatPercentEditor10, Stackable, MaxCount, RequiredAbility, SellPrice, BuyPrice, VendorStackCount, PriceVariance, PriceRandomValue, Flags1, " +
"Flags2, Flags3, Flags4, FactionRelated, ModifiedCraftingReagentItemID, ContentTuningID, PlayerLevelToItemLevelCurveID, " +
"ItemNameDescriptionID, RequiredTransmogHoliday, RequiredHoliday, GemProperties, SocketMatchEnchantmentId, TotemCategoryID, InstanceBound, " +
"ZoneBound1, ZoneBound2, ItemSet, LockID, PageID, ItemDelay, MinFactionID, RequiredSkillRank, RequiredSkill, ItemLevel, AllowableClass, " +
"ArtifactID, SpellWeight, SpellWeightCategory, SocketType1, SocketType2, SocketType3, SheatheType, Material, PageMaterialID, Bonding, " +
"DamageDamageType, StatModifierBonusStat1, StatModifierBonusStat2, StatModifierBonusStat3, StatModifierBonusStat4, StatModifierBonusStat5, " +
"StatModifierBonusStat6, StatModifierBonusStat7, StatModifierBonusStat8, StatModifierBonusStat9, StatModifierBonusStat10, ContainerSlots, " +
"MinReputation, RequiredPVPMedal, RequiredPVPRank, RequiredLevel, InventoryType, OverallQualityID FROM item_sparse");
"StatPercentEditor10, Stackable, MaxCount, MinReputation, RequiredAbility, SellPrice, BuyPrice, VendorStackCount, PriceVariance, " +
"PriceRandomValue, Flags1, Flags2, Flags3, Flags4, FactionRelated, ModifiedCraftingReagentItemID, ContentTuningID, " +
"PlayerLevelToItemLevelCurveID, ItemNameDescriptionID, RequiredTransmogHoliday, RequiredHoliday, GemProperties, SocketMatchEnchantmentId, " +
"TotemCategoryID, InstanceBound, ZoneBound1, ZoneBound2, ItemSet, LockID, PageID, ItemDelay, MinFactionID, RequiredSkillRank, RequiredSkill, " +
"ItemLevel, AllowableClass, ArtifactID, SpellWeight, SpellWeightCategory, SocketType1, SocketType2, SocketType3, SheatheType, Material, " +
"PageMaterialID, Bonding, DamageDamageType, StatModifierBonusStat1, StatModifierBonusStat2, StatModifierBonusStat3, StatModifierBonusStat4, " +
"StatModifierBonusStat5, StatModifierBonusStat6, StatModifierBonusStat7, StatModifierBonusStat8, StatModifierBonusStat9, " +
"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" +
" FROM item_sparse_locale WHERE locale = ?");
@@ -720,7 +727,7 @@ namespace Framework.Database
// JournalInstance.db2
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 = ?");
// JournalTier.db2
@@ -774,7 +781,7 @@ namespace Framework.Database
// Map.db2
PrepareStatement(HotfixStatements.SEL_MAP, "SELECT ID, Directory, MapName, MapDescription0, MapDescription1, PvpShortDescription, PvpLongDescription, " +
"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, " +
"PvpLongDescription_lang FROM map_locale WHERE locale = ?");
@@ -805,7 +812,7 @@ namespace Framework.Database
// MountCapability.db2
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
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, " +
"PhaseID, PhaseGroupID, Flags, ChrSpecializationIndex, ChrSpecializationRole, ModifierTreeID, PowerType, PowerTypeComp, PowerTypeValue, " +
"WeaponSubclassMask, MaxGuildLevel, MinGuildLevel, MaxExpansionTier, MinExpansionTier, MinPVPRank, MaxPVPRank, ContentTuningID, CovenantID, " +
"SkillID1, SkillID2, SkillID3, SkillID4, MinSkill1, MinSkill2, MinSkill3, MinSkill4, MaxSkill1, MaxSkill2, MaxSkill3, MaxSkill4, " +
"MinFactionID1, MinFactionID2, MinFactionID3, MinReputation1, MinReputation2, MinReputation3, PrevQuestID1, PrevQuestID2, PrevQuestID3, " +
"PrevQuestID4, CurrQuestID1, CurrQuestID2, CurrQuestID3, CurrQuestID4, CurrentCompletedQuestID1, CurrentCompletedQuestID2, " +
"TraitNodeEntryLogic, SkillID1, SkillID2, SkillID3, SkillID4, MinSkill1, MinSkill2, MinSkill3, MinSkill4, MaxSkill1, MaxSkill2, MaxSkill3, " +
"MaxSkill4, MinFactionID1, MinFactionID2, MinFactionID3, MinReputation1, MinReputation2, MinReputation3, PrevQuestID1, PrevQuestID2, " +
"PrevQuestID3, PrevQuestID4, CurrQuestID1, CurrQuestID2, CurrQuestID3, CurrQuestID4, CurrentCompletedQuestID1, CurrentCompletedQuestID2, " +
"CurrentCompletedQuestID3, CurrentCompletedQuestID4, SpellID1, SpellID2, SpellID3, SpellID4, ItemID1, ItemID2, ItemID3, ItemID4, ItemCount1, " +
"ItemCount2, ItemCount3, ItemCount4, Explored1, Explored2, Time1, Time2, AuraSpellID1, AuraSpellID2, AuraSpellID3, AuraSpellID4, AuraStacks1, " +
"AuraStacks2, AuraStacks3, AuraStacks4, Achievement1, Achievement2, Achievement3, Achievement4, AreaID1, AreaID2, AreaID3, AreaID4, " +
"LfgStatus1, LfgStatus2, LfgStatus3, LfgStatus4, LfgCompare1, LfgCompare2, LfgCompare3, LfgCompare4, LfgValue1, LfgValue2, LfgValue3, " +
"LfgValue4, CurrencyID1, CurrencyID2, CurrencyID3, CurrencyID4, CurrencyCount1, CurrencyCount2, CurrencyCount3, CurrencyCount4, " +
"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 = ?");
// PowerDisplay.db2
@@ -884,7 +893,7 @@ namespace Framework.Database
// PvpTalent.db2
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 = ?");
// 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 = ?");
// 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
PrepareStatement(HotfixStatements.SEL_QUEST_XP, "SELECT ID, Difficulty1, Difficulty2, Difficulty3, Difficulty4, Difficulty5, Difficulty6, Difficulty7, " +
@@ -965,14 +974,17 @@ namespace Framework.Database
// SkillLine.db2
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" +
" FROM skill_line_locale WHERE locale = ?");
// SkillLineAbility.db2
PrepareStatement(HotfixStatements.SEL_SKILL_LINE_ABILITY, "SELECT RaceMask, ID, SkillLine, Spell, MinSkillLineRank, ClassMask, SupercedesSpell, " +
"AcquireMethod, TrivialSkillLineRankHigh, TrivialSkillLineRankLow, Flags, NumSkillUps, UniqueBit, TradeSkillCategoryID, SkillupSkillLineID" +
" FROM skill_line_ability");
PrepareStatement(HotfixStatements.SEL_SKILL_LINE_ABILITY, "SELECT RaceMask, AbilityVerb, AbilityAllVerb, ID, SkillLine, Spell, MinSkillLineRank, ClassMask, " +
"SupercedesSpell, AcquireMethod, TrivialSkillLineRankHigh, TrivialSkillLineRankLow, Flags, NumSkillUps, UniqueBit, TradeSkillCategoryID, " +
"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
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
PrepareStatement(HotfixStatements.SEL_SOUND_KIT, "SELECT ID, SoundType, VolumeFloat, Flags, MinDistance, DistanceCutoff, EAXDef, SoundKitAdvancedID, " +
"VolumeVariationPlus, VolumeVariationMinus, PitchVariationPlus, PitchVariationMinus, DialogType, PitchAdjust, BusOverwriteID, MaxInstances" +
" FROM sound_kit");
"VolumeVariationPlus, VolumeVariationMinus, PitchVariationPlus, PitchVariationMinus, DialogType, PitchAdjust, BusOverwriteID, MaxInstances, " +
"SoundMixGroupID FROM sound_kit");
// SpecializationSpells.db2
PrepareStatement(HotfixStatements.SEL_SPECIALIZATION_SPELLS, "SELECT Description, ID, SpecID, SpellID, OverridesSpellID, DisplayOrder" +
@@ -1000,8 +1012,8 @@ namespace Framework.Database
// SpellAuraRestrictions.db2
PrepareStatement(HotfixStatements.SEL_SPELL_AURA_RESTRICTIONS, "SELECT ID, DifficultyID, CasterAuraState, TargetAuraState, ExcludeCasterAuraState, " +
"ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, SpellID" +
" FROM spell_aura_restrictions");
"ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, CasterAuraType, TargetAuraType, " +
"ExcludeCasterAuraType, ExcludeTargetAuraType, SpellID FROM spell_aura_restrictions");
// SpellCastTimes.db2
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");
// SpellCooldowns.db2
PrepareStatement(HotfixStatements.SEL_SPELL_COOLDOWNS, "SELECT ID, DifficultyID, CategoryRecoveryTime, RecoveryTime, StartRecoveryTime, SpellID" +
" FROM spell_cooldowns");
PrepareStatement(HotfixStatements.SEL_SPELL_COOLDOWNS, "SELECT ID, DifficultyID, CategoryRecoveryTime, RecoveryTime, StartRecoveryTime, AuraSpellID, " +
"SpellID FROM spell_cooldowns");
// SpellDuration.db2
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");
// SpellItemEnchantment.db2
PrepareStatement(HotfixStatements.SEL_SPELL_ITEM_ENCHANTMENT, "SELECT ID, Name, HordeName, EffectArg1, EffectArg2, EffectArg3, EffectScalingPoints1, " +
"EffectScalingPoints2, EffectScalingPoints3, IconFileDataID, MinItemLevel, MaxItemLevel, TransmogUseConditionID, TransmogCost, " +
"EffectPointsMin1, EffectPointsMin2, EffectPointsMin3, ItemVisual, Flags, RequiredSkillID, RequiredSkillRank, ItemLevel, Charges, Effect1, " +
"Effect2, Effect3, ScalingClass, ScalingClassRestricted, ConditionID, MinLevel, MaxLevel FROM spell_item_enchantment");
PrepareStatement(HotfixStatements.SEL_SPELL_ITEM_ENCHANTMENT, "SELECT ID, Name, HordeName, Duration, EffectArg1, EffectArg2, EffectArg3, " +
"EffectScalingPoints1, EffectScalingPoints2, EffectScalingPoints3, IconFileDataID, MinItemLevel, MaxItemLevel, TransmogUseConditionID, " +
"TransmogCost, EffectPointsMin1, EffectPointsMin2, EffectPointsMin3, ItemVisual, Flags, RequiredSkillID, RequiredSkillRank, ItemLevel, " +
"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 = ?");
// SpellItemEnchantmentCondition.db2
@@ -1083,7 +1095,7 @@ namespace Framework.Database
// SpellPower.db2
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
PrepareStatement(HotfixStatements.SEL_SPELL_POWER_DIFFICULTY, "SELECT ID, DifficultyID, OrderIndex FROM spell_power_difficulty");
@@ -1104,7 +1116,10 @@ namespace Framework.Database
// SpellReagents.db2
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
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");
// 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" +
" FROM spell_x_spell_visual");
@@ -1221,7 +1236,7 @@ namespace Framework.Database
"Region2Z, ID, UiMapID, OrderIndex, MapID, AreaID, WmoDoodadPlacementID, WmoGroupID FROM ui_map_assignment");
// 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");
// UiMapXMapArt.db2
@@ -1417,6 +1432,7 @@ namespace Framework.Database
SEL_CHR_CUSTOMIZATION_OPTION_LOCALE,
SEL_CHR_CUSTOMIZATION_REQ,
SEL_CHR_CUSTOMIZATION_REQ_LOCALE,
SEL_CHR_CUSTOMIZATION_REQ_CHOICE,
@@ -1551,6 +1567,8 @@ namespace Framework.Database
SEL_GLYPH_REQUIRED_SPEC,
SEL_GOSSIP_NPC_OPTION,
SEL_GUILD_COLOR_BACKGROUND,
SEL_GUILD_COLOR_BORDER,
@@ -1800,6 +1818,7 @@ namespace Framework.Database
SEL_SKILL_LINE_LOCALE,
SEL_SKILL_LINE_ABILITY,
SEL_SKILL_LINE_ABILITY_LOCALE,
SEL_SKILL_RACE_CLASS_INFO,
+108 -5
View File
@@ -2758,7 +2758,7 @@ namespace Game.Achievements
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;
});
@@ -2880,7 +2880,7 @@ namespace Game.Achievements
if (pvpTier == null)
return false;
if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.GetSize())
if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[pvpTier.BracketID];
@@ -2918,7 +2918,7 @@ namespace Game.Achievements
}
case ModifierTreeType.PlayerPvpTierInBracketEqualOrGreaterThan: // 239
{
if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.GetSize())
if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[secondaryAsset];
@@ -3475,7 +3475,7 @@ namespace Game.Achievements
if (pvpTier == null)
return false;
if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.GetSize())
if (pvpTier.BracketID >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[pvpTier.BracketID];
@@ -3486,7 +3486,7 @@ namespace Game.Achievements
}
case ModifierTreeType.PlayerBestWeeklyWinPvpTierInBracketEqualOrGreaterThan: // 325
{
if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.GetSize())
if (secondaryAsset >= referencePlayer.m_activePlayerData.PvpInfo.Size())
return false;
var pvpInfo = referencePlayer.m_activePlayerData.PvpInfo[secondaryAsset];
@@ -3518,6 +3518,109 @@ namespace Game.Achievements
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:
return false;
}
+2 -2
View File
@@ -113,7 +113,7 @@ namespace Game
public string BuildItemAuctionMailSubject(AuctionMailType type, AuctionPosting auction)
{
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)
@@ -1998,7 +1998,7 @@ namespace Game
public class SubclassFilter
{
public FilterType SubclassMask;
public uint[] InvTypes = new uint[ItemConst.MaxItemSubclassTotal];
public ulong[] InvTypes = new ulong[ItemConst.MaxItemSubclassTotal];
}
public enum FilterType : uint
@@ -860,12 +860,12 @@ namespace Game.BattleGrounds
public ushort GetMinPlayersPerTeam()
{
return BattlemasterEntry.MinPlayers;
return (ushort)BattlemasterEntry.MinPlayers;
}
public ushort GetMaxPlayersPerTeam()
{
return BattlemasterEntry.MaxPlayers;
return (ushort)BattlemasterEntry.MaxPlayers;
}
public byte GetMinLevel()
+40 -1
View File
@@ -656,7 +656,7 @@ namespace Game
var pMenuItemBounds = Global.ObjectMgr.GetGossipMenuItemsMapBounds(cond.SourceGroup);
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);
return true;
@@ -2442,6 +2442,45 @@ namespace Game
if (condition.CovenantID != 0 && player.m_playerData.CovenantID != condition.CovenantID)
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;
}
+19 -7
View File
@@ -164,6 +164,7 @@ namespace Game.DataStorage
GlyphBindableSpellStorage = ReadDB2<GlyphBindableSpellRecord>("GlyphBindableSpell.db2", HotfixStatements.SEL_GLYPH_BINDABLE_SPELL);
GlyphPropertiesStorage = ReadDB2<GlyphPropertiesRecord>("GlyphProperties.db2", HotfixStatements.SEL_GLYPH_PROPERTIES);
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);
GuildColorBorderStorage = ReadDB2<GuildColorBorderRecord>("GuildColorBorder.db2", HotfixStatements.SEL_GUILD_COLOR_BORDER);
GuildColorEmblemStorage = ReadDB2<GuildColorEmblemRecord>("GuildColorEmblem.db2", HotfixStatements.SEL_GUILD_COLOR_EMBLEM);
@@ -401,13 +402,13 @@ namespace Game.DataStorage
}
// Check loaded DB2 files proper version
if (!AreaTableStorage.ContainsKey(14083) || // last area added in 9.2.7 (45114)
!CharTitlesStorage.ContainsKey(727) || // last char title added in 9.2.7 (45114)
!GemPropertiesStorage.ContainsKey(3922) || // last gem property added in 9.2.7 (45114)
!ItemStorage.ContainsKey(199202) || // last item added in 9.2.7 (45114)
!ItemExtendedCostStorage.ContainsKey(7316) || // last item extended cost added in 9.2.7 (45114)
!MapStorage.ContainsKey(2559) || // last map added in 9.2.7 (45114)
!SpellNameStorage.ContainsKey(387936)) // last spell added in 9.2.7 (45114)
if (!CliDB.AreaTableStorage.ContainsKey(14618) || // last area added in 10.0.2 (46741)
!CliDB.CharTitlesStorage.ContainsKey(749) || // last char title added in 10.0.2 (46741)
!CliDB.GemPropertiesStorage.ContainsKey(4028) || // last gem property added in 10.0.2 (46741)
!CliDB.ItemStorage.ContainsKey(202712) || // last item added in 10.0.2 (46741)
!CliDB.ItemExtendedCostStorage.ContainsKey(7862) || // last item extended cost added in 10.0.2 (46741)
!CliDB.MapStorage.ContainsKey(2582) || // last map added in 10.0.2 (46741)
!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.");
Global.WorldMgr.ShutdownServ(10, ShutdownMask.Force, ShutdownExitCode.Error);
@@ -562,6 +563,7 @@ namespace Game.DataStorage
public static DB6Storage<GlyphBindableSpellRecord> GlyphBindableSpellStorage;
public static DB6Storage<GlyphPropertiesRecord> GlyphPropertiesStorage;
public static DB6Storage<GlyphRequiredSpecRecord> GlyphRequiredSpecStorage;
public static DB6Storage<GossipNPCOptionRecord> GossipNPCOptionStorage;
public static DB6Storage<GuildColorBackgroundRecord> GuildColorBackgroundStorage;
public static DB6Storage<GuildColorBorderRecord> GuildColorBorderStorage;
public static DB6Storage<GuildColorEmblemRecord> GuildColorEmblemStorage;
@@ -799,6 +801,10 @@ namespace Game.DataStorage
return row.Druid;
case Class.DemonHunter:
return row.DemonHunter;
case Class.Evoker:
return row.Evoker;
case Class.Adventurer:
return row.Adventurer;
default:
break;
}
@@ -834,6 +840,10 @@ namespace Game.DataStorage
return row.Druid;
case (int)Class.DemonHunter:
return row.DemonHunter;
case (int)Class.Evoker:
return row.Evoker;
case (int)Class.Adventurer:
return row.Adventurer;
case -1:
case -7:
return row.Item;
@@ -851,6 +861,8 @@ namespace Game.DataStorage
return row.DamageReplaceStat;
case -9:
return row.DamageSecondary;
case -10:
return row.ManaConsumable;
default:
break;
}
+8 -6
View File
@@ -118,7 +118,9 @@ namespace Game.DataStorage
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.");
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);
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);
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);
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
@@ -220,7 +222,7 @@ namespace Game.DataStorage
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();
MultiMap<uint, ItemBonusTreeNodeRecord> _itemBonusTrees = new();
Dictionary<uint, ItemChildEquipmentRecord> _itemChildEquipment = new();
ItemClassRecord[] _itemClassByOldEnum = new ItemClassRecord[19];
ItemClassRecord[] _itemClassByOldEnum = new ItemClassRecord[20];
List<uint> _itemsWithCurrencyCost = new();
MultiMap<uint, ItemLimitCategoryConditionRecord> _itemCategoryConditions = new();
MultiMap<uint, ItemLevelSelectorQualityRecord> _itemLevelQualitySelectorQualities = new();
+4 -3
View File
@@ -47,6 +47,7 @@ namespace Game.DataStorage
public sealed class BattlePetBreedQualityRecord
{
public uint Id;
public int MaxQualityRoll;
public float StateMultiplier;
public sbyte QualityEnum;
}
@@ -68,7 +69,7 @@ namespace Game.DataStorage
public uint SummonSpellID;
public int IconFileDataID;
public sbyte PetTypeEnum;
public ushort Flags;
public int Flags;
public sbyte SourceTypeEnum;
public int CardUIModelSceneID;
public int LoadoutUIModelSceneID;
@@ -96,8 +97,8 @@ namespace Game.DataStorage
public byte MinLevel;
public byte MaxLevel;
public sbyte RatedPlayers;
public byte MinPlayers;
public byte MaxPlayers;
public sbyte MinPlayers;
public int MaxPlayers;
public sbyte GroupsAllowed;
public sbyte MaxGroupSize;
public ushort HolidayWorldState;
+14 -5
View File
@@ -44,8 +44,8 @@ namespace Game.DataStorage
public uint Id;
public long RaceMask;
public sbyte ChrClassID;
public sbyte Purpose;
public sbyte Unused910;
public int Purpose;
public sbyte ItemContext;
public bool IsForNewCharacter() { return Purpose == 9; }
}
@@ -131,6 +131,7 @@ namespace Game.DataStorage
public uint Id;
public uint ChrCustomizationOptionID;
public uint ChrCustomizationReqID;
public int ChrCustomizationVisReqID;
public ushort SortOrder;
public ushort UiOrderIndex;
public int Flags;
@@ -159,6 +160,7 @@ namespace Game.DataStorage
public int ChrCustomizationCondModelID;
public int ChrCustomizationDisplayInfoID;
public int ChrCustItemGeoModifyID;
public int ChrCustomizationVoiceID;
}
public sealed class ChrCustomizationOptionRecord
@@ -181,9 +183,11 @@ namespace Game.DataStorage
public sealed class ChrCustomizationReqRecord
{
public uint Id;
public string ReqSource;
public int Flags;
public int ClassMask;
public int AchievementID;
public int QuestID;
public int OverrideArchive; // -1: allow any, otherwise must match OverrideArchive cvar
public uint ItemModifiedAppearanceID;
@@ -223,6 +227,8 @@ namespace Game.DataStorage
public uint Id;
public int ChrRacesID;
public int ChrModelID;
public int Sex;
public int AllowedTransmogSlots;
}
public sealed class ChrRacesRecord
@@ -273,6 +279,7 @@ namespace Game.DataStorage
public float AlteredFormCustomizeRotationFallback;
public float[] Unknown910_1 = new float[3];
public float[] Unknown910_2 = new float[3];
public int Unknown1000;
public sbyte BaseLanguage;
public sbyte CreatureType;
public sbyte MaleModelFallbackSex;
@@ -312,7 +319,7 @@ namespace Game.DataStorage
public uint SoundID; // Sound ID (voiceover for cinematic)
public float OriginFacing; // Orientation in map used for basis for M2 co
public uint FileDataID; // Model
public int Unknown915;
public uint ConversationID;
}
public sealed class CinematicSequencesRecord
@@ -409,7 +416,7 @@ namespace Game.DataStorage
public sbyte Gender;
public int DissolveOutEffectID;
public sbyte CreatureModelMinLod;
public int[] TextureVariationFileDataID = new int[3];
public int[] TextureVariationFileDataID = new int[4];
}
public sealed class CreatureDisplayInfoExtraRecord
@@ -542,6 +549,8 @@ namespace Game.DataStorage
public int XpQuestDifficulty;
public int AwardConditionID;
public int MaxQtyWorldStateID;
public uint RechargingAmountPerCycle;
public uint RechargingCycleDurationMS;
public int[] Flags = new int[2];
}
@@ -554,9 +563,9 @@ namespace Game.DataStorage
public sealed class CurvePointRecord
{
public uint Id;
public Vector2 Pos;
public Vector2 PreSLSquishPos;
public uint Id;
public ushort CurveID;
public byte OrderIndex;
}
@@ -73,7 +73,6 @@ namespace Game.DataStorage
public int OrderIndex;
public int CompleteWorldStateID;
public sbyte Bit;
public int CreatureDisplayID;
public int Flags;
public int SpellIconFileID;
public int Faction;
+12 -8
View File
@@ -29,8 +29,10 @@ namespace Game.DataStorage
public ushort ParentFactionID;
public byte Expansion;
public uint FriendshipRepID;
public byte Flags;
public int Flags;
public ushort ParagonFactionID;
public int RenownFactionID;
public int RenownCurrencyID;
public short[] ReputationClassMask = new short[4];
public ushort[] ReputationFlags = new ushort[4];
public int[] ReputationBase = new int[4];
@@ -47,14 +49,16 @@ namespace Game.DataStorage
public sealed class FactionTemplateRecord
{
static int MAX_FACTION_RELATIONS = 8;
public uint Id;
public ushort Faction;
public ushort Flags;
public byte FactionGroup;
public byte FriendGroup;
public byte EnemyGroup;
public ushort[] Enemies = new ushort[4];
public ushort[] Friend = new ushort[4];
public ushort[] Enemies = new ushort[MAX_FACTION_RELATIONS];
public ushort[] Friend = new ushort[MAX_FACTION_RELATIONS];
// helpers
public bool IsFriendlyTo(FactionTemplateRecord entry)
@@ -64,10 +68,10 @@ namespace Game.DataStorage
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)
return false;
for (int i = 0; i < 4; ++i)
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Friend[i] == entry.Faction)
return true;
}
@@ -80,10 +84,10 @@ namespace Game.DataStorage
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)
return true;
for (int i = 0; i < 4; ++i)
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Friend[i] == entry.Faction)
return false;
}
@@ -92,7 +96,7 @@ namespace Game.DataStorage
public bool IsHostileToPlayers() { return (EnemyGroup & (byte)FactionMasks.Player) != 0; }
public bool IsNeutralToAll()
{
for (int i = 0; i < 4; ++i)
for (int i = 0; i < MAX_FACTION_RELATIONS; ++i)
if (Enemies[i] != 0)
return false;
return EnemyGroup == 0 && FriendGroup == 0;
+21 -1
View File
@@ -270,7 +270,7 @@ namespace Game.DataStorage
public ushort UiTextureKitID;
public int GarrTalentTreeType;
public int PlayerConditionID;
public sbyte FeatureTypeIndex;
public byte FeatureTypeIndex;
public sbyte FeatureSubtypeIndex;
public int CurrencyID;
}
@@ -312,6 +312,26 @@ namespace Game.DataStorage
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 uint Id;
@@ -47,6 +47,8 @@ namespace Game.DataStorage
public float DeathKnight;
public float Monk;
public float DemonHunter;
public float Evoker;
public float Adventurer;
}
public sealed class GtBattlePetXPRecord
@@ -128,6 +130,8 @@ namespace Game.DataStorage
public float DeathKnight;
public float Monk;
public float DemonHunter;
public float Evoker;
public float Adventurer;
public float Item;
public float Consumable;
public float Gem1;
@@ -136,6 +140,7 @@ namespace Game.DataStorage
public float Health;
public float DamageReplaceStat;
public float DamageSecondary;
public float ManaConsumable;
}
public sealed class GtXpRecord
+4 -3
View File
@@ -59,6 +59,7 @@ namespace Game.DataStorage
public byte ItemGroupSoundsID;
public int ContentTuningID;
public int ModifiedCraftingReagentItemID;
public int CraftingQualityID;
}
public sealed class ItemAppearanceRecord
@@ -215,7 +216,7 @@ namespace Game.DataStorage
public byte ArenaBracket; // arena slot restrictions (min slot value)
public byte Flags;
public byte MinFactionID;
public byte MinReputation;
public int MinReputation;
public byte RequiredAchievement; // required personal arena rating
public uint[] ItemID = new uint[ItemConst.MaxItemExtCostItems]; // required item id
public ushort[] ItemCount = new ushort[ItemConst.MaxItemExtCostItems]; // required count of 1st item
@@ -305,7 +306,7 @@ namespace Game.DataStorage
public byte OverallQualityID;
public int ExpansionID;
public ushort MinFactionID;
public byte MinReputation;
public int MinReputation;
public int AllowableClass;
public sbyte RequiredLevel;
public ushort RequiredSkill;
@@ -356,6 +357,7 @@ namespace Game.DataStorage
public int[] StatPercentEditor = new int[ItemConst.MaxStats];
public uint Stackable;
public uint MaxCount;
public uint MinReputation;
public uint RequiredAbility;
public uint SellPrice;
public uint BuyPrice;
@@ -395,7 +397,6 @@ namespace Game.DataStorage
public byte DamageType;
public sbyte[] StatModifierBonusStat = new sbyte[ItemConst.MaxStats];
public byte ContainerSlots;
public byte MinReputation;
public byte RequiredPVPMedal;
public byte RequiredPVPRank;
public sbyte RequiredLevel;
@@ -65,7 +65,6 @@ namespace Game.DataStorage
public int ButtonFileDataID;
public int ButtonSmallFileDataID;
public int LoreFileDataID;
public byte OrderIndex;
public int Flags;
public ushort AreaID;
}
+4 -1
View File
@@ -51,6 +51,7 @@ namespace Game.DataStorage
public short WindSettingsID;
public int ZmpFileDataID;
public int WdtFileDataID;
public int NavigationMaxDistance;
public uint[] Flags = new uint[3];
// Helpers
@@ -98,6 +99,7 @@ namespace Game.DataStorage
case 1642:
case 1643:
case 2222:
case 2444:
return true;
default:
return false;
@@ -107,7 +109,7 @@ namespace Game.DataStorage
public bool IsDynamicDifficultyMap() { return GetFlags().HasFlag(MapFlags.DynamicDifficulty); }
public bool IsFlexLocking() { return GetFlags().HasFlag(MapFlags.FlexibleRaidLocking); }
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 MapFlags2 GetFlags2() { return (MapFlags2)Flags[1]; }
@@ -213,6 +215,7 @@ namespace Game.DataStorage
public uint ModSpellAuraID;
public short ReqMapID;
public int PlayerConditionID;
public int FlightCapabilityID;
}
public sealed class MountTypeXCapabilityRecord
+11 -6
View File
@@ -99,6 +99,7 @@ namespace Game.DataStorage
public byte MaxPVPRank;
public uint ContentTuningID;
public int CovenantID;
public uint TraitNodeEntryLogic;
public ushort[] SkillID = new ushort[4];
public ushort[] MinSkill = new ushort[4];
public ushort[] MaxSkill = new ushort[4];
@@ -123,6 +124,9 @@ namespace Game.DataStorage
public uint[] CurrencyCount = new uint[4];
public uint[] QuestKillMonster = new uint[6];
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
@@ -141,12 +145,12 @@ namespace Game.DataStorage
public string CostGlobalStringTag;
public uint Id;
public PowerType PowerTypeEnum;
public sbyte MinPower;
public short MaxBasePower;
public sbyte CenterPower;
public sbyte DefaultPower;
public sbyte DisplayModifier;
public short RegenInterruptTimeMS;
public int MinPower;
public int MaxBasePower;
public int CenterPower;
public int DefaultPower;
public int DisplayModifier;
public int RegenInterruptTimeMS;
public float RegenPeace;
public float RegenCombat;
public short Flags;
@@ -197,6 +201,7 @@ namespace Game.DataStorage
public int ActionBarSpellID;
public int PvpTalentCategoryID;
public int LevelRequired;
public int PlayerConditionID;
}
public sealed class PvpTalentCategoryRecord
+2 -1
View File
@@ -31,7 +31,7 @@ namespace Game.DataStorage
public LocalizedString InfoName;
public sbyte Type;
public int Modifiers;
public ushort Profession;
public int Profession;
}
public sealed class QuestLineXQuestRecord
@@ -69,6 +69,7 @@ namespace Game.DataStorage
{
public uint Id;
public ushort UniqueBitFlag;
public int UiQuestDetailsTheme;
}
public sealed class QuestXPRecord
+22 -7
View File
@@ -97,6 +97,8 @@ namespace Game.DataStorage
public int ParentTierIndex;
public ushort Flags;
public int SpellBookSpellID;
public int ExpansionNameSharedStringID;
public int HordeExpansionNameSharedStringID;
public SkillLineFlags GetFlags() => (SkillLineFlags)Flags;
}
@@ -104,6 +106,8 @@ namespace Game.DataStorage
public sealed class SkillLineAbilityRecord
{
public long RaceMask;
public string AbilityVerb;
public string AbilityAllVerb;
public uint Id;
public ushort SkillLine;
public uint Spell;
@@ -146,7 +150,7 @@ namespace Game.DataStorage
public uint Id;
public uint SoundType;
public float VolumeFloat;
public ushort Flags;
public int Flags;
public float MinDistance;
public float DistanceCutoff;
public byte EAXDef;
@@ -159,6 +163,7 @@ namespace Game.DataStorage
public float PitchAdjust;
public ushort BusOverwriteID;
public byte MaxInstances;
public uint SoundMixGroupID;
}
public sealed class SpecializationSpellsRecord
@@ -194,15 +199,19 @@ namespace Game.DataStorage
public sealed class SpellAuraRestrictionsRecord
{
public uint Id;
public byte DifficultyID;
public byte CasterAuraState;
public byte TargetAuraState;
public byte ExcludeCasterAuraState;
public byte ExcludeTargetAuraState;
public uint DifficultyID;
public int CasterAuraState;
public int TargetAuraState;
public int ExcludeCasterAuraState;
public int ExcludeTargetAuraState;
public uint CasterAuraSpell;
public uint TargetAuraSpell;
public uint ExcludeCasterAuraSpell;
public uint ExcludeTargetAuraSpell;
public int CasterAuraType;
public int TargetAuraType;
public int ExcludeCasterAuraType;
public int ExcludeTargetAuraType;
public uint SpellID;
}
@@ -219,7 +228,7 @@ namespace Game.DataStorage
public uint SpellID;
public byte FacingCasterFlags;
public ushort MinFactionID;
public sbyte MinReputation;
public int MinReputation;
public ushort RequiredAreasID;
public byte RequiredAuraVision;
public ushort RequiresSpellFocus;
@@ -266,6 +275,7 @@ namespace Game.DataStorage
public uint CategoryRecoveryTime;
public uint RecoveryTime;
public uint StartRecoveryTime;
public uint AuraSpellID;
public uint SpellID;
}
@@ -340,6 +350,7 @@ namespace Game.DataStorage
public uint Id;
public string Name;
public string HordeName;
public int Duration;
public uint[] EffectArg = new uint[ItemConst.MaxItemEnchantmentEffects];
public float[] EffectScalingPoints = new float[ItemConst.MaxItemEnchantmentEffects];
public uint IconFileDataID;
@@ -439,6 +450,7 @@ namespace Game.DataStorage
public int AltPowerBarID;
public float PowerCostPct;
public float PowerCostMaxPct;
public float OptionalCostPct;
public float PowerPctPerSecond;
public PowerType PowerType;
public uint RequiredAuraSpellID;
@@ -495,6 +507,8 @@ namespace Game.DataStorage
public uint SpellID;
public int[] Reagent = new int[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
@@ -638,6 +652,7 @@ namespace Game.DataStorage
public byte DifficultyID;
public uint SpellVisualID;
public float Probability;
public int Flags;
public int Priority;
public int SpellIconFileID;
public int ActiveIconFileID;
@@ -61,6 +61,7 @@ namespace Game.DataStorage
public int ParentUiMapID;
public int OrderIndex;
public int ChildUiMapID;
public int PlayerConditionID;
public int OverrideHighlightFileDataID;
public int OverrideHighlightAtlasID;
public int Flags;
+3 -2
View File
@@ -106,7 +106,7 @@ namespace Game.Entities
DeleteFromDB(trans);
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]} ");
byte index = 0;
@@ -187,7 +187,8 @@ namespace Game.Entities
SetObjectScale(1.0f);
SetDisplayId(field.Read<uint>(5));
StringArray items = new(field.Read<string>(6), ' ');
for (uint index = 0; index < EquipmentSlot.End; ++index)
if (items.Length == m_corpseData.Items.GetSize())
for (uint index = 0; index < m_corpseData.Items.GetSize(); ++index)
SetItem(index, uint.Parse(items[(int)index]));
SetRace(field.Read<byte>(7));
+149 -86
View File
@@ -30,47 +30,58 @@ namespace Game.Misc
{
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);
// Find a free new id - script case
if (menuItemId == -1)
if (orderIndex == -1)
{
menuItemId = 0;
orderIndex = 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 itr = bounds.MaxBy(a => a.OptionId);
var itr = bounds.MaxBy(a => a.OrderIndex);
if (itr != null)
menuItemId = (int)(itr.OptionId + 1);
orderIndex = (int)(itr.OrderIndex + 1);
}
if (!_menuItems.Empty())
{
foreach (var item in _menuItems)
foreach (var pair in _menuItems)
{
if (item.Key > menuItemId)
if (pair.Value.OrderIndex > orderIndex)
break;
menuItemId = (int)item.Key + 1;
orderIndex = (int)pair.Value.OrderIndex + 1;
}
}
}
if (gossipOptionId == 0)
gossipOptionId = -((int)_menuId * 100 + orderIndex);
GossipMenuItem menuItem = new();
menuItem.GossipOptionID = gossipOptionId;
menuItem.OrderIndex = (uint)orderIndex;
menuItem.OptionNpc = optionNpc;
menuItem.Message = message;
menuItem.IsCoded = coded;
menuItem.OptionText = optionText;
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.Action = action;
menuItem.BoxMessage = boxMessage;
menuItem.BoxMoney = boxMoney;
_menuItems[(uint)menuItemId] = menuItem;
return (uint)menuItemId;
_menuItems.Add((uint)orderIndex, menuItem);
return (uint)orderIndex;
}
/// <summary>
@@ -89,79 +100,104 @@ namespace Game.Misc
return;
/// 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)
return;
AddMenuItem(gossipMenuItems, sender, action);
}
public void AddMenuItem(GossipMenuItems menuItem, uint sender, uint action)
{
// Store texts for localization.
string strOptionText, strBoxText;
BroadcastTextRecord optionBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItems.OptionBroadcastTextId);
BroadcastTextRecord boxBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(gossipMenuItems.BoxBroadcastTextId);
BroadcastTextRecord optionBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(menuItem.OptionBroadcastTextId);
BroadcastTextRecord boxBroadcastText = CliDB.BroadcastTextStorage.LookupByKey(menuItem.BoxBroadcastTextId);
// OptionText
if (optionBroadcastText != null)
strOptionText = Global.DB2Mgr.GetBroadcastTextValue(optionBroadcastText, GetLocale());
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
if (boxBroadcastText != null)
strBoxText = Global.DB2Mgr.GetBroadcastTextValue(boxBroadcastText, GetLocale());
else
strBoxText = gossipMenuItems.BoxText;
// Check need of localization.
if (boxBroadcastText == null)
{
strBoxText = menuItem.BoxText;
// Find localizations from database.
GossipMenuItemsLocale gossipMenuLocale = Global.ObjectMgr.GetGossipMenuItemsLocale(menuId, menuItemId);
if (GetLocale() != Locale.enUS)
{
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((int)gossipMenuItems.OptionId, gossipMenuItems.OptionNpc, strOptionText, sender, action, strBoxText, gossipMenuItems.BoxMoney, gossipMenuItems.BoxCoded);
AddGossipMenuItemData(gossipMenuItems.OptionId, gossipMenuItems.ActionMenuId, gossipMenuItems.ActionPoiId);
AddMenuItem(menuItem.GossipOptionID, (int)menuItem.OrderIndex, menuItem.OptionNpc, strOptionText, menuItem.Language, menuItem.Flags,
menuItem.GossipNpcOptionID, menuItem.BoxCoded, menuItem.BoxMoney, strBoxText, menuItem.SpellID, (int)menuItem.OverrideIconID, sender, action);
AddGossipMenuItemData(menuItem.OrderIndex, menuItem.ActionMenuID, menuItem.ActionPoiID);
}
public void AddGossipMenuItemData(uint menuItemId, uint gossipActionMenuId, uint gossipActionPoi)
{
GossipMenuItemData itemData = new();
itemData.GossipActionMenuId = gossipActionMenuId;
itemData.GossipActionPoi = gossipActionPoi;
_menuItemData[menuItemId] = itemData;
GossipMenuItem menuItem = _menuItems[menuItemId];
menuItem.ActionMenuID = gossipActionMenuId;
menuItem.ActionPoiID = gossipActionPoi;
}
public uint GetMenuItemSender(uint menuItemId)
public GossipMenuItem GetItem(int gossipOptionId)
{
if (_menuItems.ContainsKey(menuItemId))
return _menuItems.LookupByKey(menuItemId).Sender;
else
return _menuItems.Values.FirstOrDefault(item => item.GossipOptionID == gossipOptionId);
}
GossipMenuItem GetItemByIndex(uint orderIndex)
{
return _menuItems.LookupByKey(orderIndex);
}
public uint GetMenuItemSender(uint orderIndex)
{
GossipMenuItem item = GetItemByIndex(orderIndex);
if (item != null)
return item.Sender;
return 0;
}
public uint GetMenuItemAction(uint menuItemId)
public uint GetMenuItemAction(uint orderIndex)
{
if (_menuItems.ContainsKey(menuItemId))
return _menuItems.LookupByKey(menuItemId).Action;
else
GossipMenuItem item = GetItemByIndex(orderIndex);
if (item != null)
return item.Action;
return 0;
}
public bool IsMenuItemCoded(uint menuItemId)
public bool IsMenuItemCoded(uint orderIndex)
{
if (_menuItems.ContainsKey(menuItemId))
return _menuItems.LookupByKey(menuItemId).IsCoded;
else
GossipMenuItem item = GetItemByIndex(orderIndex);
if (item != null)
return item.BoxCoded;
return false;
}
public void ClearMenu()
{
_menuItems.Clear();
_menuItemData.Clear();
}
public void SetMenuId(uint menu_id) { _menuId = menu_id; }
@@ -179,23 +215,12 @@ namespace Game.Misc
return _menuItems.Empty();
}
public GossipMenuItem GetItem(uint id)
{
return _menuItems.LookupByKey(id);
}
public GossipMenuItemData GetItemData(uint indexId)
{
return _menuItemData.LookupByKey(indexId);
}
public Dictionary<uint, GossipMenuItem> GetMenuItems()
public SortedDictionary<uint, GossipMenuItem> GetMenuItems()
{
return _menuItems;
}
Dictionary<uint, GossipMenuItem> _menuItems = new();
Dictionary<uint, GossipMenuItemData> _menuItemData = new();
SortedDictionary<uint, GossipMenuItem> _menuItems = new();
uint _menuId;
Locale _locale;
}
@@ -245,18 +270,21 @@ namespace Game.Misc
if (text != null)
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();
GossipMenuItem item = pair.Value;
opt.ClientOption = (int)pair.Key;
opt.GossipOptionID = item.GossipOptionID;
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.OptionLanguage = item.Language;
opt.Text = item.Message; // text for gossip item
opt.Confirm = item.BoxMessage; // accept text (related to money) pop up box, 2.0.3
opt.Flags = item.Flags;
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.SpellID = item.SpellID;
opt.OverrideIconID = item.OverrideIconID;
packet.GossipOptions.Add(opt);
}
@@ -404,6 +432,14 @@ namespace Game.Misc
packet.PortraitTurnInName = quest.PortraitTurnInName;
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)
{
QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id);
@@ -432,6 +468,7 @@ namespace Game.Misc
packet.DisplayPopup = displayPopup;
packet.QuestFlags[0] = (uint)(quest.Flags & (WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoAccept) ? ~QuestFlags.AutoAccept : ~QuestFlags.None));
packet.QuestFlags[1] = (uint)quest.FlagsEx;
packet.QuestFlags[2] = (uint)quest.FlagsEx2;
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
@@ -488,6 +525,14 @@ namespace Game.Misc
packet.PortraitTurnInName = quest.PortraitTurnInName;
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)
{
QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id);
@@ -513,7 +558,10 @@ namespace Game.Misc
// Is there a better way? what about game objects?
Creature creature = ObjectAccessor.GetCreature(_session.GetPlayer(), npcGUID);
if (creature)
{
packet.QuestGiverCreatureID = creature.GetEntry();
offer.QuestGiverCreatureID = creature.GetCreatureTemplate().Entry;
}
offer.QuestID = quest.Id;
offer.AutoLaunched = autoLaunched;
@@ -524,6 +572,7 @@ namespace Game.Misc
offer.QuestFlags[0] = (uint)quest.Flags;
offer.QuestFlags[1] = (uint)quest.FlagsEx;
offer.QuestFlags[2] = (uint)quest.FlagsEx2;
packet.PortraitTurnIn = quest.QuestTurnInPortrait;
packet.PortraitGiver = quest.QuestGiverPortrait;
@@ -553,6 +602,13 @@ namespace Game.Misc
packet.CompletionText = quest.RequestItemsText;
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)
{
QuestTemplateLocale localeData = Global.ObjectMgr.GetQuestLocale(quest.Id);
@@ -586,6 +642,7 @@ namespace Game.Misc
packet.QuestFlags[0] = (uint)quest.Flags;
packet.QuestFlags[1] = (uint)quest.FlagsEx;
packet.QuestFlags[2] = (uint)quest.FlagsEx2;
packet.SuggestPartyMembers = quest.SuggestedPlayers;
// incomplete: FD
@@ -687,20 +744,26 @@ namespace Game.Misc
public class GossipMenuItem
{
public int GossipOptionID;
public uint OrderIndex;
public GossipOptionNpc OptionNpc;
public bool IsCoded;
public string Message;
public string OptionText;
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 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
@@ -721,18 +784,23 @@ namespace Game.Misc
public class GossipMenuItems
{
public uint MenuId;
public uint OptionId;
public uint MenuID;
public int GossipOptionID;
public uint OrderIndex;
public GossipOptionNpc OptionNpc;
public string OptionText;
public uint OptionBroadcastTextId;
public uint Language;
public uint ActionMenuId;
public uint ActionPoiId;
public GossipOptionFlags Flags;
public uint ActionMenuID;
public uint ActionPoiID;
public int? GossipNpcOptionID;
public bool BoxCoded;
public uint BoxMoney;
public string BoxText;
public uint BoxBroadcastTextId;
public int? SpellID;
public int? OverrideIconID;
public List<Condition> Conditions = new();
}
@@ -741,11 +809,6 @@ namespace Game.Misc
public int FriendshipFactionID;
}
public class GossipMenuItemAddon
{
public int? GarrTalentTreeID;
}
public class PointOfInterest
{
public uint Id;
+21 -4
View File
@@ -2422,8 +2422,9 @@ namespace Game.Entities
if (!item)
return;
OpenHeartForge openHeartForge = new();
openHeartForge.ForgeGUID = GetGUID();
GameObjectInteraction openHeartForge = new();
openHeartForge.ObjectGUID = GetGUID();
openHeartForge.InteractionType = PlayerInteractionType.AzeriteForge;
player.SendPacket(openHeartForge);
break;
}
@@ -2438,9 +2439,25 @@ namespace Game.Entities
if (!player)
return;
GameObjectUILink gameObjectUILink = new();
GameObjectInteraction gameObjectUILink = new();
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);
return;
}
@@ -231,6 +231,9 @@ namespace Game.Entities
[FieldOffset(68)]
public clientmodel ClientModel;
[FieldOffset(68)]
public craftingTable CraftingTable;
[FieldOffset(68)]
public raw Raw;
@@ -768,6 +771,7 @@ namespace Game.Entities
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 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
@@ -909,6 +913,13 @@ namespace Game.Entities
public uint floatOnWater; // 7 floatOnWater, enum { false, true, }; Default: false
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 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
@@ -1179,7 +1190,7 @@ namespace Game.Entities
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 DifficultyHeroic; // 2 Difficulty Heroic, 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 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 CustomizationScope; // 4 Customization Scope, int, Min value: 0, Max value: 2147483647, Default value: 0
}
public struct destructiblebuilding
@@ -1490,6 +1502,7 @@ namespace Game.Entities
public uint WhenAvailable; // 0 When Available, References: GameObjectDisplayInfo, 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 ExpansionLevel; // 3 Expansion Level, int, Min value: 0, Max value: 2147483647, Default value: 0
}
public struct clientmodel
@@ -1499,6 +1512,11 @@ namespace Game.Entities
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 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
}
@@ -147,7 +147,7 @@ namespace Game.Entities
SetUpdateFieldValue(ref m_values.ModifyValue(m_azeriteEmpoweredItemData).ModifyValue(m_azeriteEmpoweredItemData.Selections, i), 0);
_bonusData = new BonusData(GetTemplate());
foreach (uint bonusListID in (List<uint>)m_itemData.BonusListIDs)
foreach (uint bonusListID in GetBonusListIDs())
_bonusData.AddBonusList(bonusListID);
}
+31 -9
View File
@@ -187,7 +187,7 @@ namespace Game.Entities
ss.Clear();
foreach (int bonusListID in (List<uint>)m_itemData.BonusListIDs)
foreach (int bonusListID in GetBonusListIDs())
ss.Append($"{bonusListID} ");
stmt.AddValue(++index, ss.ToString());
@@ -802,7 +802,11 @@ namespace Game.Entities
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)
{
@@ -1603,7 +1607,13 @@ namespace Game.Entities
-1, // INVTYPE_THROWN
EquipmentSlot.MainHand, // INVTYPE_RANGEDRIGHT
-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)
@@ -2075,17 +2085,22 @@ namespace Game.Entities
return 0;
}
public List<uint> GetBonusListIDs() { return m_itemData.ItemBonusKey.GetValue().BonusListIDs; }
public void AddBonuses(uint bonusListID)
{
var bonusListIDs = (List<uint>)m_itemData.BonusListIDs;
var bonusListIDs = GetBonusListIDs();
if (bonusListIDs.Contains(bonusListID))
return;
var bonuses = Global.DB2Mgr.GetItemBonusList(bonusListID);
if (bonuses != null)
{
bonusListIDs.Add(bonusListID);
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.BonusListIDs), bonusListIDs);
ItemBonusKey itemBonusKey = new();
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)
_bonusData.AddBonus(bonus.BonusType, bonus.Value);
@@ -2098,9 +2113,12 @@ namespace Game.Entities
if (bonusListIDs == null)
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);
SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)_bonusData.AppearanceModID);
@@ -2108,7 +2126,9 @@ namespace Game.Entities
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());
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))
return false;
return true;
case ItemSubClassContainer.ReagentContainer:
return pProto.IsCraftingReagent();
default:
return false;
}
@@ -67,6 +67,29 @@ namespace Game.Entities
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 T _value;
@@ -380,6 +403,8 @@ namespace Game.Entities
((IHasChangesMask)updateField._value).ClearChangesMask();
}
public void ClearChangesMask(UpdateFieldString updateField) { }
public void ClearChangesMask<U>(OptionalUpdateField<U> updateField) where U : new()
{
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 HasSpline = unit.IsSplineEnabled();
bool HasInertia = unit.m_movementInfo.inertia.HasValue;
bool HasAdvFlying = unit.m_movementInfo.advFlying.HasValue;
data.WritePackedGuid(GetGUID()); // MoverGUID
@@ -312,11 +313,17 @@ namespace Game.Entities
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.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)
{
data.WriteUInt32(unit.m_movementInfo.jump.fallTime); // Time
@@ -352,6 +359,24 @@ namespace Game.Entities
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.FlushBits();
@@ -425,6 +450,7 @@ namespace Game.Entities
bool hasFaceMovementDir = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasFaceMovementDir);
bool hasFollowsTerrain = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasFollowsTerrain);
bool hasUnk1 = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk1);
bool hasUnk2 = false;
bool hasTargetRollPitchYaw = areaTriggerTemplate != null && areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasTargetRollPitchYaw);
bool hasScaleCurveID = createProperties != null && createProperties.ScaleCurveId != 0;
bool hasMorphCurveID = createProperties != null && createProperties.MorphCurveId != 0;
@@ -435,6 +461,7 @@ namespace Game.Entities
bool hasAreaTriggerPolygon = createProperties != null && shape.IsPolygon();
bool hasAreaTriggerCylinder = shape.IsCylinder();
bool hasDisk = shape.IsDisk();
bool hasBoundedPlane = shape.IsBoudedPlane();
bool hasAreaTriggerSpline = areaTrigger.HasSplines();
bool hasOrbit = areaTrigger.HasOrbit();
bool hasMovementScript = false;
@@ -445,6 +472,7 @@ namespace Game.Entities
data.WriteBit(hasFaceMovementDir);
data.WriteBit(hasFollowsTerrain);
data.WriteBit(hasUnk1);
data.WriteBit(hasUnk2);
data.WriteBit(hasTargetRollPitchYaw);
data.WriteBit(hasScaleCurveID);
data.WriteBit(hasMorphCurveID);
@@ -455,6 +483,7 @@ namespace Game.Entities
data.WriteBit(hasAreaTriggerPolygon);
data.WriteBit(hasAreaTriggerCylinder);
data.WriteBit(hasDisk);
data.WriteBit(hasBoundedPlane);
data.WriteBit(hasAreaTriggerSpline);
data.WriteBit(hasOrbit);
data.WriteBit(hasMovementScript);
@@ -540,6 +569,17 @@ namespace Game.Entities
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)
// *data << *areaTrigger.GetMovementScript(); // AreaTriggerMovementScriptInfo
@@ -3745,6 +3785,7 @@ namespace Game.Entities
public Inertia? inertia;
public JumpInfo jump;
public float stepUpStartElevation { get; set; }
public AdvFlying? advFlying;
public MovementInfo()
{
@@ -3810,7 +3851,7 @@ namespace Game.Entities
}
public struct Inertia
{
public ObjectGuid guid;
public int id;
public Position force;
public uint lifetime;
}
@@ -3828,6 +3869,12 @@ namespace Game.Entities
public float cosAngle;
public float xyspeed;
}
// advflying
public struct AdvFlying
{
public float forwardVelocity;
public float upVelocity;
}
}
public class MovementForce
@@ -328,7 +328,7 @@ namespace Game.Entities
return;
}
List<uint> bonusListIDs = item.m_itemData.BonusListIDs;
List<uint> bonusListIDs = item.GetBonusListIDs();
foreach (uint bonusId in bonusListIDs)
{
if (bonusId != data.bonusId)
+10 -17
View File
@@ -1363,7 +1363,7 @@ namespace Game.Entities
eqSet.Data.AssignedSpecIndex = result.Read<int>(5);
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);
if (guid != 0)
@@ -1400,7 +1400,7 @@ namespace Game.Entities
eqSet.Data.IgnoreMask = result.Read<uint>(4);
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);
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.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++, GetGUID().GetCounter());
@@ -2312,7 +2312,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.SetIcon);
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]);
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.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());
}
else
@@ -2351,7 +2351,7 @@ namespace Game.Entities
stmt.AddValue(j++, eqSet.Data.SetIcon);
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]);
for (int i = 0; i < eqSet.Data.Enchants.Length; ++i)
@@ -2680,15 +2680,6 @@ namespace Game.Entities
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)
//Other way is to saves m_team into characters table.
SetFactionForRace(GetRace());
@@ -2982,6 +2973,8 @@ namespace Game.Entities
long now = GameTime.GetGameTime();
long logoutTime = logout_time;
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.LogoutTime), logoutTime);
// since last logout (in seconds)
uint time_diff = (uint)(now - logoutTime);
@@ -3431,7 +3424,7 @@ namespace Game.Entities
ss.Clear();
// cache equipment...
for (byte i = 0; i < InventorySlots.BagEnd; ++i)
for (byte i = 0; i < InventorySlots.ReagentBagEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
@@ -3577,7 +3570,7 @@ namespace Game.Entities
ss.Clear();
// cache equipment...
for (byte i = 0; i < InventorySlots.BagEnd; ++i)
for (byte i = 0; i < InventorySlots.ReagentBagEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
@@ -294,6 +294,7 @@ namespace Game.Entities
public CreatePosition createPosition;
public CreatePosition? createPositionNPE;
public ItemContext itemContext;
public List<PlayerCreateInfoItem> item = new();
public List<uint> customSpells = new();
public List<uint>[] castSpells = new List<uint>[(int)PlayerCreateMode.Max];
+75 -19
View File
@@ -1219,42 +1219,41 @@ namespace Game.Entities
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(titem_id, itemContext);
var bonusListIDs = Global.DB2Mgr.GetDefaultItemBonusTree(itemId, context);
InventoryResult msg;
// 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)
break;
Item item = EquipNewItem(eDest, titem_id, itemContext, true);
Item item = EquipNewItem(eDest, itemId, context, true);
item.SetBonuses(bonusListIDs);
AutoUnequipOffhandIfNeed();
titem_amount--;
--amount;
}
if (titem_amount == 0)
if (amount == 0)
return true; // equipped
// attempt store
List<ItemPosCount> sDest = new();
// 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)
{
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
}
// 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;
}
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);
// remove item dependent auras and casts (only weapon and armor slots)
if (slot < EquipmentSlot.End)
if (slot < ProfessionSlots.End)
{
// update expertise
if (slot == EquipmentSlot.MainHand)
@@ -2789,10 +2788,18 @@ namespace Game.Entities
if (slot < EquipmentSlot.End)
return true;
// profession equipment
if (slot >= ProfessionSlots.Start && slot < ProfessionSlots.End)
return true;
// bag equip slots
if (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd)
return true;
// reagent bag equip slots
if (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd)
return true;
// backpack slots
if (slot >= InventorySlots.ItemStart && slot < InventorySlots.ItemStart + GetInventorySlotCount())
return true;
@@ -3010,7 +3017,7 @@ namespace Game.Entities
// if current back slot non-empty search oldest or free
if (m_items[slot] != null)
{
long oldest_time = m_activePlayerData.BuybackTimestamp[0];
ulong oldest_time = m_activePlayerData.BuybackTimestamp[0];
uint oldest_slot = InventorySlots.BuyBackStart;
for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i)
@@ -3022,7 +3029,7 @@ namespace Game.Entities
break;
}
long i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
ulong i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
if (oldest_time > i_time)
{
oldest_time = i_time;
@@ -3473,7 +3480,7 @@ namespace Game.Entities
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 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)
{
@@ -4523,10 +4530,16 @@ namespace Game.Entities
uint freeSlotCount = 0;
if (location.HasFlag(ItemSearchLocation.Equipment))
{
for (byte i = EquipmentSlot.Start; i < EquipmentSlot.End; ++i)
if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount;
for (byte i = ProfessionSlots.Start; i < ProfessionSlots.End; ++i)
if (!GetItemByPos(InventorySlots.Bag0, i))
++freeSlotCount;
}
if (location.HasFlag(ItemSearchLocation.Inventory))
{
int inventoryEnd = InventorySlots.ItemStart + GetInventorySlotCount();
@@ -4565,9 +4578,20 @@ namespace Game.Entities
}
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)
if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount;
}
return freeSlotCount;
}
@@ -4608,7 +4632,8 @@ namespace Game.Entities
public Bag GetBagByPos(byte bag)
{
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);
if (item != null)
@@ -4624,6 +4649,8 @@ namespace Game.Entities
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BankBagStart && slot < InventorySlots.BankBagEnd))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd))
return true;
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)
@@ -4712,8 +4739,12 @@ namespace Game.Entities
{
if (bag == InventorySlots.Bag0 && (slot < EquipmentSlot.End))
return true;
if (bag == InventorySlots.Bag0 && (slot >= ProfessionSlots.Start && slot < ProfessionSlots.End))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BagStart && slot < InventorySlots.BagEnd))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentBagStart && slot < InventorySlots.ReagentBagEnd))
return true;
return false;
}
byte FindEquipSlot(Item item, uint slot, bool swap)
@@ -5246,8 +5277,10 @@ namespace Game.Entities
{
AddTemporarySpell(artifactPowerRank.SpellID);
LearnedSpells learnedSpells = new();
LearnedSpellInfo learnedSpellInfo = new();
learnedSpellInfo.SpellID = artifactPowerRank.SpellID;
learnedSpells.SuppressMessaging = true;
learnedSpells.SpellID.Add(artifactPowerRank.SpellID);
learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(learnedSpells);
}
else if (!apply)
@@ -6314,6 +6347,14 @@ namespace Game.Entities
if (!callback(item))
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))
@@ -6379,6 +6420,21 @@ namespace Game.Entities
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)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
@@ -6471,7 +6527,7 @@ namespace Game.Entities
ForEachItem(ItemSearchLocation.Everywhere, item =>
{
ItemTemplate itemTemplate = item.GetTemplate();
if (itemTemplate != null)
if (itemTemplate != null && itemTemplate.GetInventoryType() < InventoryType.ProfessionTool)
{
ushort dest;
if (item.IsEquipped())
@@ -3114,14 +3114,5 @@ namespace Game.Entities
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)
if (learning && IsInWorld)
{
LearnedSpells packet = new();
packet.SpellID.Add(spellId);
packet.SuppressMessaging = suppressMessaging;
SendPacket(packet);
LearnedSpells learnedSpells = new();
LearnedSpellInfo learnedSpellInfo = new();
learnedSpellInfo.SpellID = spellId;
learnedSpells.SuppressMessaging = suppressMessaging;
learnedSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(learnedSpells);
}
// learn all disabled higher ranks and required spells (recursive)
@@ -3046,8 +3048,10 @@ namespace Game.Entities
void SendSupercededSpell(uint oldSpell, uint newSpell)
{
SupercededSpells supercededSpells = new();
supercededSpells.SpellID.Add(newSpell);
supercededSpells.Superceded.Add(oldSpell);
LearnedSpellInfo learnedSpellInfo = new();
learnedSpellInfo.SpellID = newSpell;
learnedSpellInfo.Superceded = (int)oldSpell;
supercededSpells.ClientLearnedSpellData.Add(learnedSpellInfo);
SendPacket(supercededSpells);
}
@@ -698,6 +698,11 @@ namespace Game.Entities
if (HasPvpTalent(talentID, GetActiveTalentGroup()))
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]);
if (talent != null)
{
+130 -146
View File
@@ -296,7 +296,7 @@ namespace Game.Entities
// original items
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
// 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)
{
for (byte i = 0; i < EquipmentSlot.End; ++i)
for (byte i = EquipmentSlot.Start; i < InventorySlots.BankBagEnd; ++i)
{
if (m_items[i] == null)
continue;
@@ -693,23 +693,7 @@ namespace Game.Entities
m_items[i].DestroyForPlayer(target);
}
for (byte i = InventorySlots.BagStart; i < InventorySlots.BagEnd; ++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)
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
if (m_items[i] == null)
continue;
@@ -2329,7 +2313,7 @@ namespace Game.Entities
{
switch (gossipMenuItem.OptionNpc)
{
case GossipOptionNpc.TaxiNode:
case GossipOptionNpc.Taxinode:
if (GetSession().SendLearnNewTaxiNode(creature))
return;
break;
@@ -2337,7 +2321,7 @@ namespace Game.Entities
if (!IsDead())
canTalk = false;
break;
case GossipOptionNpc.BattleMaster:
case GossipOptionNpc.Battlemaster:
if (!creature.CanInteractWithBattleMaster(this, false))
canTalk = false;
break;
@@ -2347,7 +2331,7 @@ namespace Game.Entities
if (!creature.CanResetTalents(this))
canTalk = false;
break;
case GossipOptionNpc.StableMaster:
case GossipOptionNpc.Stablemaster:
case GossipOptionNpc.PetSpecializationMaster:
if (GetClass() != Class.Hunter)
canTalk = false;
@@ -2376,32 +2360,32 @@ namespace Game.Entities
canTalk = false; // Deprecated
break;
case GossipOptionNpc.GuildBanker:
case GossipOptionNpc.SpellClick:
case GossipOptionNpc.WorldPVPQueue:
case GossipOptionNpc.Spellclick:
case GossipOptionNpc.WorldPvPQueue:
case GossipOptionNpc.LFGDungeon:
case GossipOptionNpc.ArtifactRespec:
case GossipOptionNpc.QueueScenario:
case GossipOptionNpc.GarrisonArchitect:
case GossipOptionNpc.GarrisonMission:
case GossipOptionNpc.GarrisonMissionNpc:
case GossipOptionNpc.ShipmentCrafter:
case GossipOptionNpc.GarrisonTradeskill:
case GossipOptionNpc.GarrisonTradeskillNpc:
case GossipOptionNpc.GarrisonRecruitment:
case GossipOptionNpc.AdventureMap:
case GossipOptionNpc.GarrisonTalent:
case GossipOptionNpc.ContributionCollector:
case GossipOptionNpc.IslandsMission:
case GossipOptionNpc.IslandsMissionNpc:
case GossipOptionNpc.UIItemInteraction:
case GossipOptionNpc.WorldMap:
case GossipOptionNpc.Soulbind:
case GossipOptionNpc.ChromieTime:
case GossipOptionNpc.CovenantPreview:
case GossipOptionNpc.ChromieTimeNpc:
case GossipOptionNpc.CovenantPreviewNpc:
case GossipOptionNpc.RuneforgeLegendaryCrafting:
case GossipOptionNpc.NewPlayerGuide:
case GossipOptionNpc.RuneforgeLegendaryUpgrade:
case GossipOptionNpc.CovenantRenown:
case GossipOptionNpc.CovenantRenownNpc:
break; // NYI
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;
break;
}
@@ -2421,45 +2405,7 @@ namespace Game.Entities
}
if (canTalk)
{
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);
}
menu.GetGossipMenu().AddMenuItem(gossipMenuItem, gossipMenuItem.MenuID, gossipMenuItem.OrderIndex);
}
}
public void SendPreparedGossip(WorldObject source)
@@ -2486,7 +2432,7 @@ namespace Game.Entities
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();
@@ -2494,7 +2440,7 @@ namespace Game.Entities
if (menuId != gossipMenu.GetMenuId())
return;
GossipMenuItem item = gossipMenu.GetItem(gossipListId);
GossipMenuItem item = gossipMenu.GetItem(gossipOptionId);
if (item == null)
return;
@@ -2510,10 +2456,6 @@ namespace Game.Entities
}
}
GossipMenuItemData menuItemData = gossipMenu.GetItemData(gossipListId);
if (menuItemData == null)
return;
long cost = item.BoxMoney;
if (!HasEnoughMoney(cost))
{
@@ -2522,51 +2464,37 @@ namespace Game.Entities
return;
}
switch (gossipOptionNpc)
{
case GossipOptionNpc.None:
{
if (menuItemData.GossipActionPoi != 0)
PlayerTalkClass.SendPointOfInterest(menuItemData.GossipActionPoi);
if (item.ActionPoiID != 0)
PlayerTalkClass.SendPointOfInterest(item.ActionPoiID);
if (menuItemData.GossipActionMenuId != 0)
if (item.ActionMenuID != 0)
{
PrepareGossipMenu(source, menuItemData.GossipActionMenuId);
PrepareGossipMenu(source, item.ActionMenuID);
SendPreparedGossip(source);
}
break;
}
// types that have their dedicated open opcode dont send WorldPackets::NPC::GossipOptionNPCInteraction
bool handled = true;
switch (gossipOptionNpc)
{
case GossipOptionNpc.Vendor:
GetSession().SendListInventory(guid);
break;
case GossipOptionNpc.TaxiNode:
case GossipOptionNpc.Taxinode:
GetSession().SendTaxiMenu(source.ToCreature());
break;
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;
case GossipOptionNpc.SpiritHealer:
if (IsDead())
source.ToCreature().CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask)
.SetOriginalCaster(GetGUID()));
break;
case GossipOptionNpc.Binder:
PlayerTalkClass.SendCloseGossip();
SetBindPoint(guid);
break;
case GossipOptionNpc.Banker:
GetSession().SendShowBank(guid);
source.CastSpell(source.ToCreature(), 17251, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCaster(GetGUID()));
handled = false;
break;
case GossipOptionNpc.PetitionVendor:
PlayerTalkClass.SendCloseGossip();
GetSession().SendPetitionShowList(guid);
break;
case GossipOptionNpc.TabardVendor:
PlayerTalkClass.SendCloseGossip();
GetSession().SendTabardVendorActivate(guid);
break;
case GossipOptionNpc.BattleMaster:
case GossipOptionNpc.Battlemaster:
{
BattlegroundTypeId bgTypeId = Global.BattlegroundMgr.GetBattleMasterBG(source.GetEntry());
@@ -2586,13 +2514,25 @@ namespace Game.Entities
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.Talents);
break;
case GossipOptionNpc.StableMaster:
case GossipOptionNpc.Stablemaster:
GetSession().SendStablePet(guid);
break;
case GossipOptionNpc.PetSpecializationMaster:
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.PetTalents);
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:
PlayerTalkClass.SendCloseGossip();
CastSpell(null, PlayerConst.SpellExperienceEliminated, true);
@@ -2603,9 +2543,6 @@ namespace Game.Entities
RemoveAurasDueToSpell(PlayerConst.SpellExperienceEliminated);
RemovePlayerFlag(PlayerFlags.NoXPGain);
break;
case GossipOptionNpc.Mailbox:
GetSession().SendShowMailBox(guid);
break;
case GossipOptionNpc.SpecializationMaster:
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, 0, SpecResetType.Specialization);
@@ -2614,22 +2551,74 @@ namespace Game.Entities
PlayerTalkClass.SendCloseGossip();
SendRespecWipeConfirm(guid, 0, SpecResetType.Glyphs);
break;
case GossipOptionNpc.GarrisonTalent:
{
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);
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;
}
case GossipOptionNpc.Transmogrify:
GetSession().SendOpenTransmogrifier(guid);
break;
case GossipOptionNpc.AzeriteRespec:
PlayerTalkClass.SendCloseGossip();
GetSession().SendAzeriteRespecNPC(guid);
break;
default:
break;
if (!handled)
{
if (item.GossipNpcOptionID.HasValue)
{
GossipMenuAddon addon = Global.ObjectMgr.GetGossipMenuAddon(menuId);
GossipOptionNPCInteraction npcInteraction = new();
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);
}
}
}
ModifyMoney(-cost);
@@ -2916,8 +2905,11 @@ namespace Game.Entities
}
public void SetBindPoint(ObjectGuid guid)
{
BinderConfirm packet = new(guid);
SendPacket(packet);
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = guid;
npcInteraction.InteractionType = PlayerInteractionType.Binder;
npcInteraction.Success = true;
SendPacket(npcInteraction);
}
public void SendBindPointUpdate()
{
@@ -4021,7 +4013,7 @@ namespace Game.Entities
corpse.SetDisplayId(GetNativeDisplayId());
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)
{
@@ -6240,7 +6232,6 @@ namespace Game.Entities
packet.Reason = victim ? PlayerLogXPReason.Kill : PlayerLogXPReason.NoKill;
packet.Amount = (int)xp;
packet.GroupBonus = group_rate;
packet.ReferAFriendBonusType = (byte)(recruitAFriend ? 1 : 0);
SendPacket(packet);
uint nextLvlXP = GetXPForNextLevel();
@@ -7238,7 +7229,7 @@ namespace Game.Entities
{
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)
continue;
@@ -7246,23 +7237,7 @@ namespace Game.Entities
m_items[i].BuildCreateUpdateBlockForPlayer(data, target);
}
for (byte i = InventorySlots.BagStart; i < InventorySlots.BankBagEnd; ++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)
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
if (m_items[i] == null)
continue;
@@ -7392,9 +7367,18 @@ namespace Game.Entities
}
//Helpers
public void AddGossipItem(GossipOptionNpc icon, string message, uint sender, uint action) { PlayerTalkClass.GetGossipMenu().AddMenuItem(-1, icon, message, sender, action, "", 0); }
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); }
public void AddGossipItem(GossipOptionNpc optionNpc, string text, uint sender, uint action)
{
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)
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, // Monk
0.9720f, // Druid
0.9830f // Demon Hunter
0.9830f, // Demon Hunter
0.9880f, // Evoker
1.0f, // Adventurer
};
// 1 1 k cx
@@ -1670,7 +1672,9 @@ namespace Game.Entities
0.0f, // Warlock
90.6425f, // Monk
0.0f, // Druid
65.631440f // Demon Hunter
65.631440f, // Demon Hunter
0.0f, // Evoker
0.0f, // Adventurer
};
public void UpdateParryPercentage()
@@ -1708,7 +1712,9 @@ namespace Game.Entities
150.375940f, // Warlock
145.560408f, // Monk
116.890707f, // Druid
145.560408f // Demon Hunter
145.560408f, // Demon Hunter
145.560408f, // Evoker
0.0f, // Adventurer
};
public void UpdateDodgePercentage()
+5
View File
@@ -301,6 +301,11 @@ namespace Game.Entities
{
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)
+140 -124
View File
@@ -380,6 +380,8 @@ namespace Game
if (!result.IsEmpty())
{
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;
do
{
@@ -418,6 +420,7 @@ namespace Game
temp[raceID] = new Dictionary<byte, Tuple<byte, byte>>();
temp[raceID][classID] = Tuple.Create(activeExpansionLevel, accountExpansionLevel);
minRequirementForClass[classID] = Math.Min(minRequirementForClass[classID], activeExpansionLevel);
++count;
}
@@ -434,6 +437,7 @@ namespace Game
classAvailability.ClassID = class_.Key;
classAvailability.ActiveExpansionLevel = class_.Value.Item1;
classAvailability.AccountExpansionLevel = class_.Value.Item2;
classAvailability.MinActiveExpansionLevel = minRequirementForClass[class_.Key];
raceClassAvailability.Classes.Add(classAvailability);
}
@@ -530,6 +534,15 @@ namespace Game
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)
{
return _playerChoices.LookupByKey(choiceId);
@@ -578,9 +591,10 @@ namespace Game
gossipMenuItemsStorage.Clear();
// 0 1 2 3 4 5 6 7 8 9 10 11
SQLResult result = DB.World.Query("SELECT MenuID, OptionID, OptionNpc, OptionText, OptionBroadcastTextID, Language, ActionMenuID, ActionPoiID, BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID " +
"FROM gossip_menu_option ORDER BY MenuID, OptionID");
// 0 1 2 3 4 5 6 7 8 9 10
SQLResult result = DB.World.Query("SELECT MenuID, GossipOptionID, OptionID, OptionNpc, OptionText, OptionBroadcastTextID, Language, Flags, ActionMenuID, ActionPoiID, GossipNpcOptionID, " +
//11 12 13 14 15 16
"BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID, SpellID, OverrideIconID FROM gossip_menu_option ORDER BY MenuID, OptionID");
if (result.IsEmpty())
{
@@ -588,26 +602,40 @@ namespace Game
return;
}
Dictionary<int, uint> optionToNpcOption = new();
foreach (var (_, npcOption) in CliDB.GossipNPCOptionStorage)
optionToNpcOption[npcOption.GossipOptionID] = npcOption.Id;
do
{
GossipMenuItems gMenuItem = new();
gMenuItem.MenuId = result.Read<uint>(0);
gMenuItem.OptionId = result.Read<uint>(1);
gMenuItem.OptionNpc = (GossipOptionNpc)result.Read<byte>(2);
gMenuItem.OptionText = result.Read<string>(3);
gMenuItem.OptionBroadcastTextId = result.Read<uint>(4);
gMenuItem.Language = result.Read<uint>(5);
gMenuItem.ActionMenuId = result.Read<uint>(6);
gMenuItem.ActionPoiId = result.Read<uint>(7);
gMenuItem.BoxCoded = result.Read<bool>(8);
gMenuItem.BoxMoney = result.Read<uint>(9);
gMenuItem.BoxText = result.Read<string>(10);
gMenuItem.BoxBroadcastTextId = result.Read<uint>(11);
gMenuItem.MenuID = result.Read<uint>(0);
gMenuItem.GossipOptionID = result.Read<int>(1);
gMenuItem.OrderIndex = result.Read<uint>(2);
gMenuItem.OptionNpc = (GossipOptionNpc)result.Read<byte>(3);
gMenuItem.OptionText = result.Read<string>(4);
gMenuItem.OptionBroadcastTextId = result.Read<uint>(5);
gMenuItem.Language = result.Read<uint>(6);
gMenuItem.Flags = (GossipOptionFlags)result.Read<int>(7);
gMenuItem.ActionMenuID = result.Read<uint>(8);
gMenuItem.ActionPoiID = result.Read<uint>(9);
if (!result.IsNull(10))
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)
{
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;
}
@@ -615,47 +643,71 @@ namespace Game
{
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;
}
}
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;
}
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");
gMenuItem.ActionMenuId = 0;
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;
}
if (gMenuItem.ActionPoiId != 0)
if (gMenuItem.ActionPoiID != 0)
{
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");
gMenuItem.ActionPoiId = 0;
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;
}
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");
gMenuItem.ActionPoiId = 0;
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;
}
}
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 (!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;
}
}
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());
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");
}
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()
{
@@ -791,10 +807,6 @@ namespace Game
{
return _gossipMenuAddonStorage.LookupByKey(menuId);
}
public GossipMenuItemAddon GetGossipMenuItemAddon(uint menuId, uint optionId)
{
return _gossipMenuItemAddonStorage.LookupByKey(Tuple.Create(menuId, optionId));
}
public PointOfInterest GetPointOfInterest(uint id)
{
return pointsOfInterestStorage.LookupByKey(id);
@@ -3392,7 +3404,7 @@ namespace Game
var gossipMenuItems = GetGossipMenuItemsMapBounds(gossipMenuId);
var gossipOptionItr = gossipMenuItems.Find(entry =>
{
return entry.OptionId == gossipOptionIndex;
return entry.OrderIndex == gossipOptionIndex;
});
if (gossipOptionItr == null)
@@ -4999,6 +5011,12 @@ namespace Game
0.00f, // INVTYPE_RANGEDRIGHT
0.00f, // INVTYPE_QUIVER
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[]
@@ -5944,9 +5962,6 @@ namespace Game
//Player
public void LoadPlayerInfo()
{
for (uint race = 0; race < (int)Race.Max; ++race)
_playerInfo[race] = new PlayerInfo[(int)Class.Max];
var time = Time.GetMSTime();
// 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.");
}
_playerInfo[currentrace][currentclass] = info;
_playerInfo[Tuple.Create((Race)currentrace, (Class)currentclass)] = info;
++count;
} while (result.NextRow());
@@ -6092,9 +6107,11 @@ namespace Game
if (!characterLoadout.RaceMask.HasAnyFlag(SharedConst.GetMaskForRace(raceIndex)))
continue;
PlayerInfo playerInfo = _playerInfo[(int)raceIndex][characterLoadout.ChrClassID];
var playerInfo = _playerInfo.LookupByKey(Tuple.Create((Race)raceIndex, (Class)characterLoadout.ChrClassID));
if (playerInfo != null)
{
playerInfo.itemContext = (ItemContext)characterLoadout.ItemContext;
foreach (ItemTemplate itemTemplate in items)
{
// BuyCount by default
@@ -6200,11 +6217,11 @@ namespace Game
{
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)
info.skills.Add(rcInfo);
}
@@ -6251,14 +6268,14 @@ namespace Game
{
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];
if (info != null)
PlayerInfo playerInfo = _playerInfo.LookupByKey(Tuple.Create(raceIndex, classIndex));
if (playerInfo != null)
{
info.customSpells.Add(spellId);
playerInfo.customSpells.Add(spellId);
++count;
}
// 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))
{
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)
{
info.castSpells[playerCreateMode].Add(spellId);
@@ -6350,20 +6367,20 @@ namespace Game
uint count = 0;
do
{
uint currentrace = result.Read<uint>(0);
if (currentrace >= (int)Race.Max)
Race currentrace = (Race)result.Read<uint>(0);
if (currentrace >= Race.Max)
{
Log.outError(LogFilter.Sql, "Wrong race {0} in `playercreateinfo_action` table, ignoring.", currentrace);
continue;
}
uint currentclass = result.Read<uint>(1);
if (currentclass >= (int)Class.Max)
Class currentclass = (Class)result.Read<uint>(1);
if (currentclass >= Class.Max)
{
Log.outError(LogFilter.Sql, "Wrong class {0} in `playercreateinfo_action` table, ignoring.", currentclass);
continue;
}
PlayerInfo info = _playerInfo[currentrace][currentclass];
PlayerInfo info = _playerInfo.LookupByKey(Tuple.Create(currentrace, currentclass));
if (info != null)
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)
raceStatModifiers[i] = new short[(int)Stats.Max];
// 0 1 2 3 4
SQLResult result = DB.World.Query("SELECT race, str, agi, sta, inte FROM player_racestats");
if (result.IsEmpty())
@@ -6393,15 +6409,15 @@ namespace Game
do
{
uint currentrace = result.Read<uint>(0);
if (currentrace >= (int)Race.Max)
Race currentrace = (Race)result.Read<uint>(0);
if (currentrace >= Race.Max)
{
Log.outError(LogFilter.Sql, $"Wrong race {currentrace} in `player_racestats` table, ignoring.");
continue;
}
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());
@@ -6418,8 +6434,8 @@ namespace Game
do
{
uint currentclass = result.Read<byte>(0);
if (currentclass >= (int)Class.Max)
Class currentclass = (Class)result.Read<byte>(0);
if (currentclass >= Class.Max)
{
Log.outError(LogFilter.Sql, "Wrong class {0} in `player_classlevelstats` table, ignoring.", currentclass);
continue;
@@ -6438,14 +6454,14 @@ namespace Game
for (var race = 0; race < raceStatModifiers.Length; ++race)
{
var pInfo = _playerInfo[race][currentclass];
if (pInfo == null)
var playerInfo = _playerInfo.LookupByKey(Tuple.Create((Race)race, currentclass));
if (playerInfo == null)
continue;
if (pInfo.levelInfo[currentlevel - 1] == null)
pInfo.levelInfo[currentlevel - 1] = new PlayerLevelInfo();
if (playerInfo.levelInfo[currentlevel - 1] == null)
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++)
levelinfo.stats[i] = (ushort)(result.Read<ushort>(i + 2) + raceStatModifiers[race][i]);
@@ -6455,38 +6471,38 @@ namespace Game
} while (result.NextRow());
// 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
if (!CliDB.ChrRacesStorage.ContainsKey(race) || _playerInfo[race][0] == null)
if (!CliDB.ChrRacesStorage.ContainsKey(race))
continue;
for (uint _class = 0; _class < (int)Class.Max; ++_class)
for (Class _class = 0; _class < Class.Max; ++_class)
{
// skip non existed classes
if (CliDB.ChrClassesStorage.LookupByKey(_class) == null || _playerInfo[race][_class] == null)
if (CliDB.ChrClassesStorage.LookupByKey(_class) == null)
continue;
PlayerInfo pInfo = _playerInfo[race][_class];
if (pInfo == null)
var playerInfo = _playerInfo.LookupByKey(Tuple.Create(race, _class));
if (playerInfo == null)
continue;
// 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;
// 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;
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;
if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.Legion && _class == (int)Class.DemonHunter)
if (WorldConfig.GetIntValue(WorldCfg.Expansion) < (int)Expansion.Legion && _class == Class.DemonHunter)
continue;
// 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);
Global.WorldMgr.StopNow();
@@ -6496,10 +6512,10 @@ namespace Game
// fill level gaps
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);
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)
{
if (_playerInfo[race][class_] == null)
var playerInfo = _playerInfo.LookupByKey(Tuple.Create((Race)race, (Class)class_));
if (playerInfo == null)
return;
if (count > 0)
_playerInfo[race][class_].item.Add(new PlayerCreateInfoItem(itemId, (uint)count));
playerInfo.item.Add(new PlayerCreateInfoItem(itemId, (uint)count));
else
{
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);
var items = _playerInfo[race][class_].item;
items.RemoveAll(item => { return item.item_id == itemId; });
playerInfo.item.RemoveAll(item => item.item_id == itemId);
}
}
@@ -6584,7 +6600,7 @@ namespace Game
if (classId >= Class.Max)
return null;
var info = _playerInfo[(int)raceId][(int)classId];
var info = _playerInfo.LookupByKey(Tuple.Create(raceId, classId));
if (info == null)
return null;
@@ -6613,7 +6629,7 @@ namespace Game
if (level < 1 || race >= Race.Max || _class >= Class.Max)
return null;
PlayerInfo pInfo = _playerInfo[(int)race][(int)_class];
PlayerInfo pInfo = _playerInfo.LookupByKey(Tuple.Create(race, _class));
if (pInfo == null)
return null;
@@ -6626,7 +6642,7 @@ namespace Game
PlayerLevelInfo BuildPlayerLevelInfo(Race race, Class _class, uint 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)
{
@@ -10911,7 +10927,6 @@ namespace Game
MultiMap<uint, GossipMenus> gossipMenusStorage = new();
MultiMap<uint, GossipMenuItems> gossipMenuItemsStorage = new();
Dictionary<uint, GossipMenuAddon> _gossipMenuAddonStorage = new();
Dictionary<Tuple<uint, uint>, GossipMenuItemAddon> _gossipMenuItemAddonStorage = new();
Dictionary<uint, PointOfInterest> pointsOfInterestStorage = new();
//Creature
@@ -10946,7 +10961,7 @@ namespace Game
Dictionary<uint, ItemTemplate> ItemTemplateStorage = new();
//Player
PlayerInfo[][] _playerInfo = new PlayerInfo[(int)Race.Max][];
Dictionary<Tuple<Race, Class>, PlayerInfo> _playerInfo = new();
//Faction Change
public Dictionary<uint, uint> FactionChangeAchievements = new();
@@ -12007,6 +12022,7 @@ namespace Game
public byte ClassID;
public byte ActiveExpansionLevel;
public byte AccountExpansionLevel;
public byte MinActiveExpansionLevel;
}
public class RaceClassAvailability
@@ -86,6 +86,7 @@ namespace Game
SetTimeZoneInformation packet = new();
packet.ServerTimeTZ = "Europe/Paris";
packet.GameTimeTZ = "Europe/Paris";
packet.ServerRegionalTZ = "Europe/Paris";
SendPacket(packet);//enabled it
}
+5 -1
View File
@@ -246,7 +246,11 @@ namespace Game
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)
{
m_currentBankerGUID = guid;
ShowBank packet = new();
packet.Guid = guid;
SendPacket(packet);
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = guid;
npcInteraction.InteractionType = PlayerInteractionType.Banker;
npcInteraction.Success = true;
SendPacket(npcInteraction);
}
}
}
+5 -4
View File
@@ -45,10 +45,11 @@ namespace Game
void SendBlackMarketOpenResult(ObjectGuid guid, Creature auctioneer)
{
BlackMarketOpenResult packet = new();
packet.Guid = guid;
packet.Enable = Global.BlackMarketMgr.IsEnabled();
SendPacket(packet);
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = guid;
npcInteraction.InteractionType = PlayerInteractionType.BlackMarketAuctioneer;
npcInteraction.Success = Global.BlackMarketMgr.IsEnabled();
SendPacket(npcInteraction);
}
[WorldPacketHandler(ClientOpcodes.BlackMarketRequestItems)]
+79 -17
View File
@@ -192,6 +192,15 @@ namespace Game
if (req.ItemModifiedAppearanceID != 0 && !GetCollectionMgr().HasItemAppearance(req.ItemModifiedAppearanceID).PermAppearance)
return false;
if (req.QuestID != 0)
{
if (!_player)
return false;
if (!_player.IsQuestRewarded((uint)req.QuestID))
return false;
}
if (checkRequiredDependentChoices)
{
var requiredChoices = Global.DB2Mgr.GetRequiredCustomizationChoices(req.Id);
@@ -318,14 +327,14 @@ namespace Game
RaceUnlockRequirement raceExpansionRequirement = Global.ObjectMgr.GetRaceUnlockRequirement(charCreate.CreateInfo.RaceId);
if (raceExpansionRequirement == null)
{
Log.outError(LogFilter.Player, $"Account {GetAccountId()} tried to create character with unavailable race {charCreate.CreateInfo.RaceId}");
SendCharCreate(ResponseCodes.AccountCreateFailed);
Log.outError(LogFilter.Cheat, $"Account {GetAccountId()} tried to create character with unavailable race {charCreate.CreateInfo.RaceId}");
SendCharCreate(ResponseCodes.CharCreateFailed);
return;
}
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);
return;
}
@@ -338,18 +347,33 @@ namespace Game
// return;
//}
// prevent character creating Expansion class without Expansion account
ClassAvailability classExpansionRequirement = Global.ObjectMgr.GetClassExpansionRequirement(charCreate.CreateInfo.RaceId, charCreate.CreateInfo.ClassId);
if (classExpansionRequirement == null)
// prevent character creating Expansion race without Expansion account
ClassAvailability raceClassExpansionRequirement = Global.ObjectMgr.GetClassExpansionRequirement(charCreate.CreateInfo.RaceId, charCreate.CreateInfo.ClassId);
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())
{
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;
}
if (classExpansionRequirement.ActiveExpansionLevel > (int)GetExpansion() || classExpansionRequirement.AccountExpansionLevel > (int)GetAccountExpansion())
}
else
{
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);
return;
}
@@ -450,9 +474,14 @@ namespace Game
int demonHunterReqLevel = WorldConfig.GetIntValue(WorldCfg.CharacterCreatingMinLevelForDemonHunter);
bool hasDemonHunterReqLevel = demonHunterReqLevel == 0;
uint evokerReqLevel = WorldConfig.GetUIntValue(WorldCfg.CharacterCreatingMinLevelForEvoker);
bool hasEvokerReqLevel = (evokerReqLevel == 0);
bool allowTwoSideAccounts = !Global.WorldMgr.IsPvPRealm() || HasPermission(RBACPermissions.TwoSideCharacterCreation);
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)
{
@@ -461,8 +490,9 @@ namespace Game
{
Team team = Player.TeamForRace(createInfo.RaceId);
byte accRace = result1.Read<byte>(1);
byte accClass = result1.Read<byte>(2);
if (checkDemonHunterReqs)
if (checkClassLevelReqs)
{
if (!hasDemonHunterReqLevel)
{
@@ -470,7 +500,16 @@ namespace Game
if (accLevel >= demonHunterReqLevel)
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
// @todo what to if account already has characters of both races?
@@ -489,17 +528,18 @@ namespace Game
// search same race for cinematic or same class if need
// @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())
break;
accRace = result1.Read<byte>(1);
accClass = result1.Read<byte>(2);
if (!haveSameRace)
haveSameRace = createInfo.RaceId == (Race)accRace;
if (checkDemonHunterReqs)
if (checkClassLevelReqs)
{
if (!hasDemonHunterReqLevel)
{
@@ -507,11 +547,33 @@ namespace Game
if (acc_level >= demonHunterReqLevel)
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);
return;
@@ -520,7 +582,7 @@ namespace Game
// Check name uniqueness in the same step as saving to database
if (Global.CharacterCacheStorage.GetCharacterCacheByName(createInfo.Name) != null)
{
SendCharCreate(ResponseCodes.CharCreateNameInUse);
SendCharCreate(ResponseCodes.CharCreateDracthyrDuplicate);
return;
}
@@ -580,7 +642,7 @@ namespace Game
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_CREATE_INFO);
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));
}));
}
+2 -2
View File
@@ -808,8 +808,8 @@ namespace Game
gems[i] = gem;
gemData[i].ItemId = gem.GetEntry();
gemData[i].Context = (byte)gem.m_itemData.Context;
for (int b = 0; b < ((List<uint>)gem.m_itemData.BonusListIDs).Count && b < 16; ++b)
gemData[i].BonusListIDs[b] = (ushort)((List<uint>)gem.m_itemData.BonusListIDs)[b];
for (int b = 0; b < gem.GetBonusListIDs().Count && b < 16; ++b)
gemData[i].BonusListIDs[b] = (ushort)gem.GetBonusListIDs()[b];
gemProperties[i] = CliDB.GemPropertiesStorage.LookupByKey(gem.GetTemplate().GetGemProperties());
}
+5 -3
View File
@@ -682,9 +682,11 @@ namespace Game
public void SendShowMailBox(ObjectGuid guid)
{
ShowMailbox packet = new();
packet.PostmasterGUID = guid;
SendPacket(packet);
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = guid;
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.DataStorage;
using Game.Entities;
using Game.Misc;
using Game.Networking;
using Game.Networking.Packets;
using System;
@@ -48,9 +49,11 @@ namespace Game
public void SendTabardVendorActivate(ObjectGuid guid)
{
PlayerTabardVendorActivate packet = new();
packet.Vendor = guid;
SendPacket(packet);
NPCInteractionOpenResult npcInteraction = new();
npcInteraction.Npc = guid;
npcInteraction.InteractionType = PlayerInteractionType.TabardVendor;
npcInteraction.Success = true;
SendPacket(npcInteraction);
}
[WorldPacketHandler(ClientOpcodes.TrainerList, Processing = PacketProcessing.Inplace)]
@@ -172,7 +175,8 @@ namespace Game
[WorldPacketHandler(ClientOpcodes.GossipSelectOption)]
void HandleGossipSelectOption(GossipSelectOption packet)
{
if (GetPlayer().PlayerTalkClass.GetGossipMenu().GetItem(packet.GossipIndex) == null)
GossipMenuItem gossipMenuItem = _player.PlayerTalkClass.GetGossipMenu().GetItem(packet.GossipOptionID);
if (gossipMenuItem == null)
return;
// Prevent cheating on C# scripted menus
@@ -224,26 +228,26 @@ namespace Game
{
if (unit != null)
{
if (!unit.GetAI().OnGossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode))
GetPlayer().OnGossipSelect(unit, packet.GossipIndex, packet.GossipID);
if (!unit.GetAI().OnGossipSelectCode(_player, packet.GossipID, gossipMenuItem.OrderIndex, packet.PromotionCode))
GetPlayer().OnGossipSelect(unit, packet.GossipOptionID, packet.GossipID);
}
else
{
if (!go.GetAI().OnGossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode))
_player.OnGossipSelect(go, packet.GossipIndex, packet.GossipID);
if (!go.GetAI().OnGossipSelectCode(_player, packet.GossipID, gossipMenuItem.OrderIndex, packet.PromotionCode))
_player.OnGossipSelect(go, packet.GossipOptionID, packet.GossipID);
}
}
else
{
if (unit != null)
{
if (!unit.GetAI().OnGossipSelect(_player, packet.GossipID, packet.GossipIndex))
GetPlayer().OnGossipSelect(unit, packet.GossipIndex, packet.GossipID);
if (!unit.GetAI().OnGossipSelect(_player, packet.GossipID, gossipMenuItem.OrderIndex))
GetPlayer().OnGossipSelect(unit, packet.GossipOptionID, packet.GossipID);
}
else
{
if (!go.GetAI().OnGossipSelect(_player, packet.GossipID, packet.GossipIndex))
GetPlayer().OnGossipSelect(go, packet.GossipIndex, packet.GossipID);
if (!go.GetAI().OnGossipSelect(_player, packet.GossipID, gossipMenuItem.OrderIndex))
GetPlayer().OnGossipSelect(go, packet.GossipOptionID, packet.GossipID);
}
}
}
@@ -342,7 +342,11 @@ namespace Game
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(),
item.GetItemRandomBonusListId(), item.GetModifier(ItemModifier.TimewalkerLevel), item.GetModifier(ItemModifier.ArtifactKnowledgeLevel),
item.GetContext(), item.m_itemData.BonusListIDs);
item.GetContext(), item.GetBonusListIDs());
VoidItem voidItem;
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)
Cypher.Assert(!CliDB.MapStorage.LookupByKey(mapId).Instanceable());
transport.InInstance = false;
}
else
transport.InInstance = CliDB.MapStorage.LookupByKey(transport.MapIds.First()).Instanceable();
transport.TotalPathTime = totalTime;
}
@@ -424,6 +420,12 @@ namespace Game.Maps
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 _);
if (startingPosition == null)
{
@@ -435,7 +437,6 @@ namespace Game.Maps
Transport trans = new();
// ...at first waypoint
uint mapId = tInfo.PathLegs.First().MapId;
float x = startingPosition.GetPositionX();
float y = startingPosition.GetPositionY();
float z = startingPosition.GetPositionZ();
@@ -448,16 +449,6 @@ namespace Game.Maps
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)
trans.SetMap(map);
if (instanceMap != null)
@@ -536,7 +527,6 @@ namespace Game.Maps
public List<TransportPathEvent> Events = new();
public HashSet<uint> MapIds = new();
public bool InInstance;
public Position ComputePosition(uint time, out TransportMovementState moveState, out int legIndex)
{
@@ -784,12 +784,12 @@ namespace Game.Networking.Packets
public struct AuctionListFilterSubClass
{
public int ItemSubclass;
public uint InvTypeMask;
public ulong InvTypeMask;
public AuctionListFilterSubClass(WorldPacket data)
{
InvTypeMask = data.ReadUInt64();
ItemSubclass = data.ReadInt32();
InvTypeMask = data.ReadUInt32();
}
}
@@ -138,6 +138,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt8(classAvailability.ClassID);
_worldPacket.WriteUInt8(classAvailability.ActiveExpansionLevel);
_worldPacket.WriteUInt8(classAvailability.AccountExpansionLevel);
_worldPacket.WriteUInt8(classAvailability.MinActiveExpansionLevel);
}
}
@@ -166,7 +167,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt16(SuccessInfo.NumPlayersAlliance.Value);
if(SuccessInfo.ExpansionTrialExpiration.HasValue)
_worldPacket.WriteInt32(SuccessInfo.ExpansionTrialExpiration.Value);
_worldPacket.WriteInt64(SuccessInfo.ExpansionTrialExpiration.Value);
foreach (VirtualRealmInfo virtualRealm in SuccessInfo.VirtualRealms)
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 ushort? NumPlayersHorde; // number of horde 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
{
@@ -34,25 +34,6 @@ namespace Game.Networking.Packets
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
{
public AzeriteEssenceUnlockMilestone(WorldPacket packet) : base(packet) { }
@@ -141,19 +122,4 @@ namespace Game.Networking.Packets
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 WeeklyPlayed;
public int WeeklyWon;
public int RoundsSeasonPlayed;
public int RoundsSeasonWon;
public int RoundsWeeklyPlayed;
public int RoundsWeeklyWon;
public int BestWeeklyRating;
public int LastWeeksBestRating;
public int BestSeasonRating;
public int PvpTierID;
public int Unused3;
public int WeeklyBestWinPvpTierID;
public int Unused4;
public int Rank;
public bool Disqualified;
@@ -593,12 +596,15 @@ namespace Game.Networking.Packets
data.WriteInt32(Unused2);
data.WriteInt32(WeeklyPlayed);
data.WriteInt32(WeeklyWon);
data.WriteInt32(RoundsSeasonPlayed);
data.WriteInt32(RoundsSeasonWon);
data.WriteInt32(RoundsWeeklyPlayed);
data.WriteInt32(RoundsWeeklyWon);
data.WriteInt32(BestWeeklyRating);
data.WriteInt32(LastWeeksBestRating);
data.WriteInt32(BestSeasonRating);
data.WriteInt32(PvpTierID);
data.WriteInt32(Unused3);
data.WriteInt32(WeeklyBestWinPvpTierID);
data.WriteInt32(Unused4);
data.WriteInt32(Rank);
data.WriteBit(Disqualified);
@@ -33,21 +33,6 @@ namespace Game.Networking.Packets
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
{
public BlackMarketRequestItems(WorldPacket packet) : base(packet) { }
@@ -44,12 +44,14 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(IsNewPlayerRestrictionSkipped);
_worldPacket.WriteBit(IsNewPlayerRestricted);
_worldPacket.WriteBit(IsNewPlayer);
_worldPacket.WriteBit(IsTrialAccountRestricted);
_worldPacket.WriteBit(DisabledClassesMask.HasValue);
_worldPacket.WriteBit(IsAlliedRacesCreationAllowed);
_worldPacket.WriteInt32(Characters.Count);
_worldPacket.WriteInt32(MaxCharacterLevel);
_worldPacket.WriteInt32(RaceUnlockData.Count);
_worldPacket.WriteInt32(UnlockedConditionalAppearances.Count);
_worldPacket.WriteInt32(RaceLimitDisables.Count);
if (DisabledClassesMask.HasValue)
_worldPacket.WriteUInt32(DisabledClassesMask.Value);
@@ -57,6 +59,9 @@ namespace Game.Networking.Packets
foreach (UnlockedConditionalAppearance unlockedConditionalAppearance in UnlockedConditionalAppearances)
unlockedConditionalAppearance.Write(_worldPacket);
foreach (RaceLimitDisableInfo raceLimitDisableInfo in RaceLimitDisables)
raceLimitDisableInfo.Write(_worldPacket);
foreach (CharacterInfo charInfo in Characters)
charInfo.Write(_worldPacket);
@@ -69,6 +74,7 @@ namespace Game.Networking.Packets
public bool IsNewPlayerRestrictionSkipped; // allows client to skip new player restrictions
public bool IsNewPlayerRestricted; // forbids using level boost and class trials
public bool IsNewPlayer; // forbids hero classes and allied races
public bool IsTrialAccountRestricted;
public bool IsAlliedRacesCreationAllowed;
public int MaxCharacterLevel = 1;
@@ -77,6 +83,7 @@ namespace Game.Networking.Packets
public List<CharacterInfo> Characters = new(); // all characters on the list
public List<RaceUnlock> RaceUnlockData = new(); //
public List<UnlockedConditionalAppearance> UnlockedConditionalAppearances = new();
public List<RaceLimitDisableInfo> RaceLimitDisables = new();
public class CharacterInfo
{
@@ -147,11 +154,11 @@ namespace Game.Networking.Packets
var spec = Global.DB2Mgr.GetChrSpecializationByIndex(ClassId, fields.Read<byte>(21));
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].DisplayId = equipment.NextUInt32();
@@ -190,9 +197,9 @@ namespace Game.Networking.Packets
visualItem.Write(data);
data.WriteInt64(LastPlayedTime);
data.WriteUInt16(SpecID);
data.WriteUInt32(Unknown703);
data.WriteUInt32(LastLoginVersion);
data.WriteInt16(SpecID);
data.WriteInt32(Unknown703);
data.WriteInt32(LastLoginVersion);
data.WriteUInt32(Flags4);
data.WriteInt32(MailSenders.Count);
data.WriteInt32(MailSenderTypes.Count);
@@ -244,16 +251,16 @@ namespace Game.Networking.Packets
public bool FirstLogin;
public byte unkWod61x;
public long LastPlayedTime;
public ushort SpecID;
public uint Unknown703;
public uint LastLoginVersion;
public short SpecID;
public int Unknown703;
public int LastLoginVersion;
public uint OverrideSelectScreenFileDataID;
public uint PetCreatureDisplayId;
public uint PetExperienceLevel;
public uint PetCreatureFamilyId;
public bool BoostInProgress; // @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<uint> MailSenderTypes = new();
@@ -311,6 +318,24 @@ namespace Game.Networking.Packets
public int AchievementID;
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
@@ -500,6 +525,7 @@ namespace Game.Networking.Packets
RaceOrFactionChangeInfo.Guid = _worldPacket.ReadPackedGuid();
RaceOrFactionChangeInfo.SexID = (Gender)_worldPacket.ReadUInt8();
RaceOrFactionChangeInfo.RaceID = (Race)_worldPacket.ReadUInt8();
RaceOrFactionChangeInfo.InitialRaceID = (Race)_worldPacket.ReadUInt8();
var customizationCount = _worldPacket.ReadUInt32();
RaceOrFactionChangeInfo.Name = _worldPacket.ReadString(nameLength);
@@ -851,6 +877,7 @@ namespace Game.Networking.Packets
{
var customizationCount = _worldPacket.ReadUInt32();
NewSex = _worldPacket.ReadUInt8();
CustomizedRace = _worldPacket.ReadInt32();
for (var i = 0; i < customizationCount; ++i)
{
@@ -866,6 +893,7 @@ namespace Game.Networking.Packets
public byte NewSex;
public Array<ChrCustomizationChoice> Customizations = new(50);
public int CustomizedRace;
}
public class BarberShopResult : ServerPacket
@@ -902,7 +930,6 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt8((byte)Reason);
_worldPacket.WriteInt32(Amount);
_worldPacket.WriteFloat(GroupBonus);
_worldPacket.WriteUInt8(ReferAFriendBonusType);
}
public ObjectGuid Victim;
@@ -910,7 +937,6 @@ namespace Game.Networking.Packets
public PlayerLogXPReason Reason;
public int Amount;
public float GroupBonus;
public byte ReferAFriendBonusType; // 1 - 300% of normal XP; 2 - 150% of normal XP
}
class TitleEarned : ServerPacket
@@ -1105,6 +1131,7 @@ namespace Game.Networking.Packets
public class CharRaceOrFactionChangeInfo
{
public Race RaceID = Race.None;
public Race InitialRaceID = Race.None;
public Gender SexID = Gender.None;
public ObjectGuid Guid;
public bool FactionChange;
@@ -31,7 +31,7 @@ namespace Game.Networking.Packets
public override void Read()
{
Language = (Language)_worldPacket.ReadInt32();
uint len = _worldPacket.ReadBits<uint>(9);
uint len = _worldPacket.ReadBits<uint>(11);
Text = _worldPacket.ReadString(len);
}
@@ -47,7 +47,7 @@ namespace Game.Networking.Packets
{
Language = (Language)_worldPacket.ReadInt32();
uint targetLen = _worldPacket.ReadBits<uint>(9);
uint textLen = _worldPacket.ReadBits<uint>(9);
uint textLen = _worldPacket.ReadBits<uint>(11);
Target = _worldPacket.ReadString(targetLen);
Text = _worldPacket.ReadString(textLen);
}
@@ -66,7 +66,7 @@ namespace Game.Networking.Packets
Language = (Language)_worldPacket.ReadInt32();
ChannelGUID = _worldPacket.ReadPackedGuid();
uint targetLen = _worldPacket.ReadBits<uint>(9);
uint textLen = _worldPacket.ReadBits<uint>(9);
uint textLen = _worldPacket.ReadBits<uint>(11);
Target = _worldPacket.ReadString(targetLen);
Text = _worldPacket.ReadString(textLen);
}
@@ -112,7 +112,7 @@ namespace Game.Networking.Packets
public override void Read()
{
uint len = _worldPacket.ReadBits<uint>(9);
uint len = _worldPacket.ReadBits<uint>(11);
Text = _worldPacket.ReadString(len);
}
@@ -125,7 +125,7 @@ namespace Game.Networking.Packets
public override void Read()
{
uint len = _worldPacket.ReadBits<uint>(9);
uint len = _worldPacket.ReadBits<uint>(11);
Text = _worldPacket.ReadString(len);
}
@@ -138,7 +138,7 @@ namespace Game.Networking.Packets
public override void Read()
{
uint len = _worldPacket.ReadBits<uint>(9);
uint len = _worldPacket.ReadBits<uint>(11);
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()
{
Guid = _worldPacket.ReadPackedGuid();
IsSoftInteract = _worldPacket.HasBit();
}
public ObjectGuid Guid;
public bool IsSoftInteract;
}
public class GameObjReportUse : ClientPacket
@@ -39,9 +41,11 @@ namespace Game.Networking.Packets
public override void Read()
{
Guid = _worldPacket.ReadPackedGuid();
IsSoftInteract = _worldPacket.HasBit();
}
public ObjectGuid Guid;
public bool IsSoftInteract;
}
class GameObjectDespawn : ServerPacket
@@ -136,22 +140,6 @@ namespace Game.Networking.Packets
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
{
public GameObjectPlaySpellVisual() : base(ServerOpcodes.GameObjectPlaySpellVisual) { }
@@ -181,4 +169,29 @@ namespace Game.Networking.Packets
public ObjectGuid ObjectGUID;
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);
}
}
}
@@ -317,22 +317,6 @@ namespace Game.Networking.Packets
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
public struct GarrisonPlotInfo
{
@@ -75,7 +75,9 @@ namespace Game.Networking.Packets
GuildData.Value.Write(_worldPacket);
if (AzeriteLevel.HasValue)
_worldPacket.WriteUInt32((uint)AzeriteLevel);
_worldPacket.WriteUInt32(AzeriteLevel.Value);
TalentTraits.Write(_worldPacket);
}
public PlayerModelDisplayInfo DisplayInfo;
@@ -83,7 +85,7 @@ namespace Game.Networking.Packets
public List<ushort> Talents = new();
public Array<ushort> PvpTalents = new(PlayerConst.MaxPvpTalentSlots, 0);
public InspectGuildData? GuildData;
public Array<PVPBracketData> Bracket = new(6, default);
public Array<PVPBracketData> Bracket = new(7, default);
public uint? AzeriteLevel;
public int ItemLevel;
public uint LifetimeHK;
@@ -91,6 +93,7 @@ namespace Game.Networking.Packets
public ushort TodayHK;
public ushort YesterdayHK;
public byte LifetimeMaxRank;
public TraitInspectInfo TalentTraits;
}
public class QueryInspectAchievements : ClientPacket
@@ -290,6 +293,7 @@ namespace Game.Networking.Packets
public void Write(WorldPacket data)
{
data.WriteUInt8(Bracket);
data.WriteInt32(Unused3);
data.WriteInt32(Rating);
data.WriteInt32(Rank);
data.WriteInt32(WeeklyPlayed);
@@ -302,6 +306,10 @@ namespace Game.Networking.Packets
data.WriteInt32(WeeklyBestWinPvpTierID);
data.WriteInt32(Unused1);
data.WriteInt32(Unused2);
data.WriteInt32(RoundsSeasonPlayed);
data.WriteInt32(RoundsSeasonWon);
data.WriteInt32(RoundsWeeklyPlayed);
data.WriteInt32(RoundsWeeklyWon);
data.WriteBit(Disqualified);
data.FlushBits();
}
@@ -318,10 +326,29 @@ namespace Game.Networking.Packets
public int WeeklyBestWinPvpTierID;
public int Unused1;
public int Unused2;
public int Unused3;
public int RoundsSeasonPlayed;
public int RoundsSeasonWon;
public int RoundsWeeklyPlayed;
public int RoundsWeeklyWon;
public byte Bracket;
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 uint Index;
+65 -1
View File
@@ -20,6 +20,7 @@ using Framework.Dynamic;
using Game.Entities;
using System.Collections.Generic;
using System.Linq;
using System;
namespace Game.Networking.Packets
{
@@ -429,14 +430,26 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(BattlePetBreedQuality);
_worldPacket.WriteInt32(BattlePetLevel);
_worldPacket.WritePackedGuid(ItemGUID);
_worldPacket.WriteInt32(Toasts.Count);
foreach (UiEventToast uiEventToast in Toasts)
uiEventToast.Write(_worldPacket);
_worldPacket.WriteBit(Pushed);
_worldPacket.WriteBit(Created);
_worldPacket.WriteBits((uint)DisplayText, 3);
_worldPacket.WriteBit(IsBonusRoll);
_worldPacket.WriteBit(IsEncounterLoot);
_worldPacket.WriteBit(CraftingData != null);
_worldPacket.WriteBit(FirstCraftOperationID.HasValue);
_worldPacket.FlushBits();
Item.Write(_worldPacket);
if (FirstCraftOperationID.HasValue)
_worldPacket.WriteUInt32(FirstCraftOperationID.Value);
if (CraftingData != null)
CraftingData.Write(_worldPacket);
}
public ObjectGuid PlayerGUID;
@@ -453,6 +466,9 @@ namespace Game.Networking.Packets
public uint BattlePetBreedQuality;
public int BattlePetLevel;
public ObjectGuid ItemGUID;
public List<UiEventToast> Toasts = new();
public CraftingData CraftingData;
public uint? FirstCraftOperationID;
public bool Pushed;
public DisplayType DisplayText;
public bool Created;
@@ -858,7 +874,7 @@ namespace Game.Networking.Packets
public ItemInstance(Item item)
{
ItemID = item.GetEntry();
List<uint> bonusListIds = item.m_itemData.BonusListIDs;
List<uint> bonusListIds = item.GetBonusListIDs();
if (!bonusListIds.Empty())
{
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 ItemEnchantData() { }
public ItemEnchantData(uint id, uint expiration, int charges, byte slot)
{
ID = id;
@@ -1093,4 +1145,16 @@ namespace Game.Networking.Packets
public ItemPurchaseRefundItem[] Items = new ItemPurchaseRefundItem[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()
{
Unit = _worldPacket.ReadPackedGuid();
IsSoftInteract = _worldPacket.HasBit();
}
public ObjectGuid Unit;
public bool IsSoftInteract;
}
public class LootResponse : ServerPacket
@@ -273,6 +275,9 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt32(MapID);
_worldPacket.WriteUInt32(RollTime);
_worldPacket.WriteUInt8((byte)ValidRolls);
foreach (var reason in LootRollIneligibleReason)
_worldPacket.WriteUInt32((uint)reason);
_worldPacket.WriteUInt8((byte)Method);
Item.Write(_worldPacket);
}
@@ -282,6 +287,7 @@ namespace Game.Networking.Packets
public uint RollTime;
public LootMethod Method;
public RollMask ValidRolls;
public Array<LootRollIneligibilityReason> LootRollIneligibleReason = new Array<LootRollIneligibilityReason>(4);
public LootItemData Item = new();
}
@@ -293,18 +293,6 @@ namespace Game.Networking.Packets
public float Delay = 0.0f;
}
class ShowMailbox : ServerPacket
{
public ShowMailbox() : base(ServerOpcodes.ShowMailbox) { }
public override void Write()
{
_worldPacket.WritePackedGuid(PostmasterGUID);
}
public ObjectGuid PostmasterGUID;
}
//Structs
public class MailAttachedItem
{
+26 -26
View File
@@ -58,21 +58,6 @@ namespace Game.Networking.Packets
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 InvalidatePlayer() : base(ServerOpcodes.InvalidatePlayer) { }
@@ -124,11 +109,13 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(WeeklyQuantity.HasValue);
_worldPacket.WriteBit(TrackedQuantity.HasValue);
_worldPacket.WriteBit(MaxQuantity.HasValue);
_worldPacket.WriteBit(Unused901.HasValue);
_worldPacket.WriteBit(TotalEarned.HasValue);
_worldPacket.WriteBit(SuppressChatLog);
_worldPacket.WriteBit(QuantityChange.HasValue);
_worldPacket.WriteBit(QuantityGainSource.HasValue);
_worldPacket.WriteBit(QuantityLostSource.HasValue);
_worldPacket.WriteBit(QuantityGainSource.HasValue);
_worldPacket.WriteBit(FirstCraftOperationID.HasValue);
_worldPacket.WriteBit(LastSpendTime.HasValue);
_worldPacket.FlushBits();
if (WeeklyQuantity.HasValue)
@@ -140,29 +127,38 @@ namespace Game.Networking.Packets
if (MaxQuantity.HasValue)
_worldPacket.WriteInt32(MaxQuantity.Value);
if (Unused901.HasValue)
_worldPacket.WriteInt32(Unused901.Value);
if (TotalEarned.HasValue)
_worldPacket.WriteInt32(TotalEarned.Value);
if (QuantityChange.HasValue)
_worldPacket.WriteInt32(QuantityChange.Value);
if (QuantityLostSource.HasValue)
_worldPacket.WriteInt32(QuantityLostSource.Value);
if (QuantityGainSource.HasValue)
_worldPacket.WriteInt32(QuantityGainSource.Value);
if (QuantityLostSource.HasValue)
_worldPacket.WriteInt32(QuantityLostSource.Value);
if (FirstCraftOperationID.HasValue)
_worldPacket.WriteUInt32(FirstCraftOperationID.Value);
if (LastSpendTime.HasValue)
_worldPacket.WriteInt64(LastSpendTime.Value);
}
public uint Type;
public int Quantity;
public uint Flags;
public List<UiEventToast> Toasts = new();
public int? WeeklyQuantity;
public int? TrackedQuantity;
public int? MaxQuantity;
public int? Unused901;
public int? TotalEarned;
public int? QuantityChange;
public int? QuantityGainSource;
public int? QuantityLostSource;
public uint? FirstCraftOperationID;
public long? LastSpendTime;
public bool SuppressChatLog;
}
@@ -209,7 +205,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(data.MaxWeeklyQuantity.HasValue);
_worldPacket.WriteBit(data.TrackedQuantity.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.FlushBits();
@@ -221,8 +218,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(data.TrackedQuantity.Value);
if (data.MaxQuantity.HasValue)
_worldPacket.WriteInt32(data.MaxQuantity.Value);
if (data.Unused901.HasValue)
_worldPacket.WriteInt32(data.Unused901.Value);
if (data.TotalEarned.HasValue)
_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? TrackedQuantity;
public int? MaxQuantity;
public int? Unused901;
public int? TotalEarned;
public long? LastSpendTime;
public byte Flags; // 0 = none,
}
}
@@ -106,6 +106,7 @@ namespace Game.Networking.Packets
data.ReadBit(); // HeightChangeFailed
data.ReadBit(); // RemoteTimeValid
bool hasInertia = data.HasBit();
bool hasAdvFlying = data.HasBit();
if (hasTransport)
ReadTransportInfo(data, ref movementInfo.transport);
@@ -113,13 +114,22 @@ namespace Game.Networking.Packets
if (hasInertia)
{
MovementInfo.Inertia inertia = new();
inertia.guid = data.ReadPackedGuid();
inertia.id = data.ReadInt32();
inertia.force = data.ReadPosition();
inertia.lifetime = data.ReadUInt32();
movementInfo.inertia = inertia;
}
if (hasAdvFlying)
{
MovementInfo.AdvFlying advFlying = new();
advFlying.forwardVelocity = data.ReadFloat();
advFlying.upVelocity = data.ReadFloat();
movementInfo.advFlying = advFlying;
}
if (hasFall)
{
movementInfo.jump.fallTime = data.ReadUInt32();
@@ -146,6 +156,7 @@ namespace Game.Networking.Packets
bool hasFallData = hasFallDirection || movementInfo.jump.fallTime != 0;
bool hasSpline = false; // todo 6.x send this infos
bool hasInertia = movementInfo.inertia.HasValue;
bool hasAdvFlying = movementInfo.advFlying.HasValue;
data.WritePackedGuid(movementInfo.Guid);
data.WriteUInt32((uint)movementInfo.GetMovementFlags());
@@ -176,6 +187,7 @@ namespace Game.Networking.Packets
data.WriteBit(false); // HeightChangeFailed
data.WriteBit(false); // RemoteTimeValid
data.WriteBit(hasInertia);
data.WriteBit(hasAdvFlying);
data.FlushBits();
if (hasTransportData)
@@ -183,11 +195,17 @@ namespace Game.Networking.Packets
if (hasInertia)
{
data.WritePackedGuid(movementInfo.inertia.Value.guid);
data.WriteInt32(movementInfo.inertia.Value.id);
data.WriteXYZ(movementInfo.inertia.Value.force);
data.WriteUInt32(movementInfo.inertia.Value.lifetime);
}
if (hasAdvFlying)
{
data.WriteFloat(movementInfo.advFlying.Value.forwardVelocity);
data.WriteFloat(movementInfo.advFlying.Value.upVelocity);
}
if (hasFallData)
{
data.WriteUInt32(movementInfo.jump.fallTime);
@@ -514,7 +532,7 @@ namespace Game.Networking.Packets
}
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;
}
@@ -555,7 +573,7 @@ namespace Game.Networking.Packets
}
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
@@ -1167,6 +1185,12 @@ namespace Game.Networking.Packets
public float InitVertSpeed;
}
public class SpeedRange
{
public float Min;
public float Max;
}
public class MoveStateChange
{
public MoveStateChange(ServerOpcodes messageId, uint sequenceIndex)
@@ -1180,12 +1204,13 @@ namespace Game.Networking.Packets
data.WriteUInt16((ushort)MessageID);
data.WriteUInt32(SequenceIndex);
data.WriteBit(Speed.HasValue);
data.WriteBit(SpeedRange != null);
data.WriteBit(KnockBack.HasValue);
data.WriteBit(VehicleRecID.HasValue);
data.WriteBit(CollisionHeight.HasValue);
data.WriteBit(@MovementForce != null);
data.WriteBit(MovementForceGUID.HasValue);
data.WriteBit(MovementInertiaGUID.HasValue);
data.WriteBit(MovementInertiaID.HasValue);
data.WriteBit(MovementInertiaLifetimeMs.HasValue);
data.FlushBits();
@@ -1195,6 +1220,12 @@ namespace Game.Networking.Packets
if (Speed.HasValue)
data.WriteFloat(Speed.Value);
if (SpeedRange != null)
{
data.WriteFloat(SpeedRange.Min);
data.WriteFloat(SpeedRange.Max);
}
if (KnockBack.HasValue)
{
data.WriteFloat(KnockBack.Value.HorzSpeed);
@@ -1216,8 +1247,8 @@ namespace Game.Networking.Packets
if (MovementForceGUID.HasValue)
data.WritePackedGuid(MovementForceGUID.Value);
if (MovementInertiaGUID.HasValue)
data.WritePackedGuid(MovementInertiaGUID.Value);
if (MovementInertiaID.HasValue)
data.WriteInt32(MovementInertiaID.Value);
if (MovementInertiaLifetimeMs.HasValue)
data.WriteUInt32(MovementInertiaLifetimeMs.Value);
@@ -1226,12 +1257,13 @@ namespace Game.Networking.Packets
public ServerOpcodes MessageID;
public uint SequenceIndex;
public float? Speed;
public SpeedRange SpeedRange;
public KnockBackInfo? KnockBack;
public int? VehicleRecID;
public CollisionHeightInfo? CollisionHeight;
public MovementForce MovementForce;
public ObjectGuid? MovementForceGUID;
public ObjectGuid? MovementInertiaGUID;
public int? MovementInertiaID;
public uint? MovementInertiaLifetimeMs;
}
}
+88 -67
View File
@@ -43,6 +43,23 @@ namespace Game.Networking.Packets
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 GossipMessagePkt() : base(ServerOpcodes.GossipMessage) { }
@@ -52,33 +69,20 @@ namespace Game.Networking.Packets
_worldPacket.WritePackedGuid(GossipGUID);
_worldPacket.WriteUInt32(GossipID);
_worldPacket.WriteInt32(FriendshipFactionID);
_worldPacket.WriteInt32(TextID);
_worldPacket.WriteInt32(GossipOptions.Count);
_worldPacket.WriteInt32(GossipText.Count);
foreach (ClientGossipOptions options in GossipOptions)
{
_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);
_worldPacket.WriteBits(options.Confirm.GetByteCount(), 12);
_worldPacket.WriteBits((byte)options.Status, 2);
_worldPacket.WriteBit(options.SpellID.HasValue);
_worldPacket.WriteBit(TextID.HasValue);
_worldPacket.WriteBit(TextID2.HasValue);
_worldPacket.FlushBits();
options.Treasure.Write(_worldPacket);
foreach (ClientGossipOptions options in GossipOptions)
options.Write(_worldPacket);
_worldPacket.WriteString(options.Text);
_worldPacket.WriteString(options.Confirm);
if (TextID.HasValue)
_worldPacket.WriteInt32(TextID.Value);
if (options.SpellID.HasValue)
_worldPacket.WriteInt32(options.SpellID.Value);
}
if (TextID2.HasValue)
_worldPacket.WriteInt32(TextID2.Value);
foreach (ClientGossipText text in GossipText)
text.Write(_worldPacket);
@@ -88,7 +92,8 @@ namespace Game.Networking.Packets
public int FriendshipFactionID;
public ObjectGuid GossipGUID;
public List<ClientGossipText> GossipText = new();
public int TextID;
public int? TextID;
public int? TextID2;
public uint GossipID;
}
@@ -100,18 +105,38 @@ namespace Game.Networking.Packets
{
GossipUnit = _worldPacket.ReadPackedGuid();
GossipID = _worldPacket.ReadUInt32();
GossipIndex = _worldPacket.ReadUInt32();
GossipOptionID = _worldPacket.ReadInt32();
uint length = _worldPacket.ReadBits<uint>(8);
PromotionCode = _worldPacket.ReadString(length);
}
public ObjectGuid GossipUnit;
public uint GossipIndex;
public int GossipOptionID;
public uint GossipID;
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 bool SuppressSound;
@@ -181,30 +206,6 @@ namespace Game.Networking.Packets
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
{
public GossipPOI() : base(ServerOpcodes.GossipPoi) { }
@@ -243,18 +244,6 @@ namespace Game.Networking.Packets
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
{
public TrainerBuySpell(WorldPacket packet) : base(packet) { }
@@ -344,16 +333,47 @@ namespace Game.Networking.Packets
public class ClientGossipOptions
{
public int ClientOption;
public int GossipOptionID;
public GossipOptionNpc OptionNPC;
public byte OptionFlags;
public int OptionCost;
public uint OptionLanguage;
public GossipOptionFlags Flags;
public int OrderIndex;
public GossipOptionStatus Status;
public string Text;
public string Confirm;
public string Text = "";
public string Confirm = "";
public TreasureLootList Treasure = new();
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
@@ -386,19 +406,20 @@ namespace Game.Networking.Packets
{
public void Write(WorldPacket data)
{
data.WriteInt32(MuID);
data.WriteInt32(Type);
data.WriteInt32(Quantity);
data.WriteUInt64(Price);
data.WriteInt32(MuID);
data.WriteInt32(Durability);
data.WriteInt32(StackCount);
data.WriteInt32(Quantity);
data.WriteInt32(ExtendedCostID);
data.WriteInt32(PlayerConditionFailed);
Item.Write(data);
data.WriteBits(Type, 3);
data.WriteBit(Locked);
data.WriteBit(DoNotFilterOnVendor);
data.WriteBit(Refundable);
data.FlushBits();
Item.Write(data);
}
public int MuID;
+66 -3
View File
@@ -197,6 +197,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt32(Info.Expansion);
_worldPacket.WriteInt32(Info.ManagedWorldStateID);
_worldPacket.WriteInt32(Info.QuestSessionBonus);
_worldPacket.WriteInt32(Info.QuestGiverCreatureID);
_worldPacket.WriteInt32(Info.ConditionalQuestDescription.Count);
_worldPacket.WriteInt32(Info.ConditionalQuestCompletionLog.Count);
foreach (QuestCompleteDisplaySpell rewardDisplaySpell in Info.RewardDisplaySpell)
rewardDisplaySpell.Write(_worldPacket);
@@ -243,6 +247,12 @@ namespace Game.Networking.Packets
_worldPacket.WriteString(Info.PortraitTurnInText);
_worldPacket.WriteString(Info.PortraitTurnInName);
_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.WriteInt32(PortraitGiverModelSceneID);
_worldPacket.WriteUInt32(PortraitTurnIn);
_worldPacket.WriteUInt32(QuestGiverCreatureID);
_worldPacket.WriteInt32(ConditionalRewardText.Count);
_worldPacket.WriteBits(QuestTitle.GetByteCount(), 9);
_worldPacket.WriteBits(RewardText.GetByteCount(), 12);
@@ -322,6 +334,10 @@ namespace Game.Networking.Packets
_worldPacket.WriteBits(PortraitGiverName.GetByteCount(), 8);
_worldPacket.WriteBits(PortraitTurnInText.GetByteCount(), 10);
_worldPacket.WriteBits(PortraitTurnInName.GetByteCount(), 8);
_worldPacket.FlushBits();
foreach (ConditionalQuestText conditionalQuestText in ConditionalRewardText)
conditionalQuestText.Write(_worldPacket);
_worldPacket.WriteString(QuestTitle);
_worldPacket.WriteString(RewardText);
@@ -335,12 +351,14 @@ namespace Game.Networking.Packets
public uint PortraitGiver;
public uint PortraitGiverMount;
public int PortraitGiverModelSceneID;
public uint QuestGiverCreatureID;
public string QuestTitle = "";
public string RewardText = "";
public string PortraitGiverText = "";
public string PortraitGiverName = "";
public string PortraitTurnInText = "";
public string PortraitTurnInName = "";
public List<ConditionalQuestText> ConditionalRewardText = new();
public QuestGiverOfferReward QuestData;
public uint QuestPackageID;
}
@@ -437,12 +455,15 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(PortraitTurnIn);
_worldPacket.WriteUInt32(QuestFlags[0]); // Flags
_worldPacket.WriteUInt32(QuestFlags[1]); // FlagsEx
_worldPacket.WriteUInt32(QuestFlags[2]); // FlagsEx
_worldPacket.WriteUInt32(SuggestedPartyMembers);
_worldPacket.WriteInt32(LearnSpells.Count);
_worldPacket.WriteInt32(DescEmotes.Count);
_worldPacket.WriteInt32(Objectives.Count);
_worldPacket.WriteInt32(QuestStartItemID);
_worldPacket.WriteInt32(QuestSessionBonus);
_worldPacket.WriteInt32(QuestGiverCreatureID);
_worldPacket.WriteInt32(ConditionalDescriptionText.Count);
foreach (uint spell in LearnSpells)
_worldPacket.WriteUInt32(spell);
@@ -483,13 +504,16 @@ namespace Game.Networking.Packets
_worldPacket.WriteString(PortraitGiverName);
_worldPacket.WriteString(PortraitTurnInText);
_worldPacket.WriteString(PortraitTurnInName);
foreach (ConditionalQuestText conditionalQuestText in ConditionalDescriptionText)
conditionalQuestText.Write(_worldPacket);
}
public ObjectGuid QuestGiverGUID;
public ObjectGuid InformUnit;
public uint QuestID;
public int QuestPackageID;
public uint[] QuestFlags = new uint[2];
public uint[] QuestFlags = new uint[3];
public uint SuggestedPartyMembers;
public QuestRewards Rewards = new();
public List<QuestObjectiveSimple> Objectives = new();
@@ -501,6 +525,7 @@ namespace Game.Networking.Packets
public int PortraitGiverModelSceneID;
public int QuestStartItemID;
public int QuestSessionBonus;
public int QuestGiverCreatureID;
public string PortraitGiverText = "";
public string PortraitGiverName = "";
public string PortraitTurnInText = "";
@@ -508,6 +533,7 @@ namespace Game.Networking.Packets
public string QuestTitle = "";
public string LogDescription = "";
public string DescriptionText = "";
public List<ConditionalQuestText> ConditionalDescriptionText = new();
public bool DisplayPopup;
public bool StartCheat;
public bool AutoLaunched;
@@ -526,6 +552,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(CompEmoteType);
_worldPacket.WriteUInt32(QuestFlags[0]);
_worldPacket.WriteUInt32(QuestFlags[1]);
_worldPacket.WriteUInt32(QuestFlags[2]);
_worldPacket.WriteUInt32(SuggestPartyMembers);
_worldPacket.WriteInt32(MoneyToGet);
_worldPacket.WriteInt32(Collect.Count);
@@ -547,8 +574,15 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(AutoLaunched);
_worldPacket.FlushBits();
_worldPacket.WriteUInt32(QuestGiverCreatureID);
_worldPacket.WriteInt32(ConditionalCompletionText.Count);
_worldPacket.WriteBits(QuestTitle.GetByteCount(), 9);
_worldPacket.WriteBits(CompletionText.GetByteCount(), 12);
_worldPacket.FlushBits();
foreach (ConditionalQuestText conditionalQuestText in ConditionalCompletionText)
conditionalQuestText.Write(_worldPacket);
_worldPacket.WriteString(QuestTitle);
_worldPacket.WriteString(CompletionText);
@@ -565,9 +599,10 @@ namespace Game.Networking.Packets
public List<QuestObjectiveCollect> Collect = new();
public List<QuestCurrency> Currency = new();
public int StatusFlags;
public uint[] QuestFlags = new uint[2];
public uint[] QuestFlags = new uint[3];
public string QuestTitle = "";
public string CompletionText = "";
public List<ConditionalQuestText> ConditionalCompletionText = new();
}
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 QuestInfo()
@@ -1008,7 +1067,10 @@ namespace Game.Networking.Packets
public int Expansion;
public int ManagedWorldStateID;
public int QuestSessionBonus;
public int QuestGiverCreatureID; // used to select ConditionalQuestText
public List<QuestObjective> Objectives = new();
public List<ConditionalQuestText> ConditionalQuestDescription = new();
public List<ConditionalQuestText> ConditionalQuestCompletionLog = new();
public uint[] RewardItems = new uint[SharedConst.QuestRewardItemCount];
public uint[] RewardAmount = new uint[SharedConst.QuestRewardItemCount];
public int[] ItemDrop = new int[SharedConst.QuestItemDropCount];
@@ -1144,6 +1206,7 @@ namespace Game.Networking.Packets
data.WriteUInt32(QuestID);
data.WriteUInt32(QuestFlags[0]); // Flags
data.WriteUInt32(QuestFlags[1]); // FlagsEx
data.WriteUInt32(QuestFlags[2]); // FlagsEx2
data.WriteUInt32(SuggestedPartyMembers);
data.WriteInt32(Emotes.Count);
@@ -1167,7 +1230,7 @@ namespace Game.Networking.Packets
public uint SuggestedPartyMembers = 0;
public QuestRewards Rewards = 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
@@ -22,7 +22,7 @@ namespace Game.Networking.Packets
{
public class InitializeFactions : ServerPacket
{
const ushort FactionCount = 400;
const ushort FactionCount = 443;
public InitializeFactions() : base(ServerOpcodes.InitializeFactions, ConnectionType.Instance) { }
@@ -30,7 +30,7 @@ namespace Game.Networking.Packets
{
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]);
}
@@ -72,7 +72,6 @@ namespace Game.Networking.Packets
public override void Write()
{
_worldPacket.WriteFloat(ReferAFriendBonus);
_worldPacket.WriteFloat(BonusFromAchievementSystem);
_worldPacket.WriteInt32(Faction.Count);
@@ -83,7 +82,6 @@ namespace Game.Networking.Packets
_worldPacket.FlushBits();
}
public float ReferAFriendBonus;
public float BonusFromAchievementSystem;
public List<FactionStandingData> Faction = new();
public bool ShowVisual;
+60 -36
View File
@@ -305,23 +305,13 @@ namespace Game.Networking.Packets
public override void Write()
{
_worldPacket.WriteInt32(SpellID.Count);
_worldPacket.WriteInt32(Superceded.Count);
_worldPacket.WriteInt32(FavoriteSpellID.Count);
_worldPacket.WriteInt32(ClientLearnedSpellData.Count);
foreach (var spellId in SpellID)
_worldPacket.WriteUInt32(spellId);
foreach (var spellId in Superceded)
_worldPacket.WriteUInt32(spellId);
foreach (var spellId in FavoriteSpellID)
_worldPacket.WriteInt32(spellId);
foreach (LearnedSpellInfo spell in ClientLearnedSpellData)
spell.Write(_worldPacket);
}
public List<uint> SpellID = new();
public List<uint> Superceded = new();
public List<int> FavoriteSpellID = new();
public List<LearnedSpellInfo> ClientLearnedSpellData = new();
}
public class LearnedSpells : ServerPacket
@@ -330,22 +320,16 @@ namespace Game.Networking.Packets
public override void Write()
{
_worldPacket.WriteInt32(SpellID.Count);
_worldPacket.WriteInt32(FavoriteSpellID.Count);
_worldPacket.WriteInt32(ClientLearnedSpellData.Count);
_worldPacket.WriteUInt32(SpecializationID);
foreach (uint spell in SpellID)
_worldPacket.WriteUInt32(spell);
foreach (int spell in FavoriteSpellID)
_worldPacket.WriteInt32(spell);
_worldPacket.WriteBit(SuppressMessaging);
_worldPacket.FlushBits();
foreach (LearnedSpellInfo spell in ClientLearnedSpellData)
spell.Write(_worldPacket);
}
public List<uint> SpellID = new();
public List<int> FavoriteSpellID = new();
public List<LearnedSpellInfo> ClientLearnedSpellData = new();
public uint SpecializationID;
public bool SuppressMessaging;
}
@@ -998,10 +982,12 @@ namespace Game.Networking.Packets
{
SpellClickUnitGuid = _worldPacket.ReadPackedGuid();
TryAutoDismount = _worldPacket.HasBit();
IsSoftInteract = _worldPacket.HasBit();
}
public ObjectGuid SpellClickUnitGuid;
public bool TryAutoDismount;
public bool IsSoftInteract;
}
class ResyncRunes : ServerPacket
@@ -1520,7 +1506,7 @@ namespace Game.Networking.Packets
{
public void Read(WorldPacket data)
{
Flags = (SpellCastTargetFlags)data.ReadBits<uint>(26);
Flags = (SpellCastTargetFlags)data.ReadBits<uint>(28);
if (data.HasBit())
SrcLocation = new();
@@ -1552,7 +1538,7 @@ namespace Game.Networking.Packets
public void Write(WorldPacket data)
{
data.WriteBits((uint)Flags, 26);
data.WriteBits((uint)Flags, 28);
data.WriteBit(SrcLocation != null);
data.WriteBit(DstLocation != null);
data.WriteBit(Orientation.HasValue);
@@ -1607,15 +1593,20 @@ namespace Game.Networking.Packets
public uint Quantity;
}
public struct SpellOptionalReagent
public struct SpellCraftingReagent
{
public int ItemID;
public int Slot;
public int DataSlotIndex;
public int Quantity;
public byte? Unknown_1000;
public void Read(WorldPacket data)
{
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 MovementInfo MoveUpdate;
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 ulong? CraftingOrderID;
public ObjectGuid CraftingNPC;
public uint[] Misc = new uint[2];
@@ -1658,21 +1650,25 @@ namespace Game.Networking.Packets
MissileTrajectory.Read(data);
CraftingNPC = data.ReadPackedGuid();
var optionalReagents = data.ReadUInt32();
var optionalCurrencies = data.ReadUInt32();
for (var i = 0; i < optionalReagents; ++i)
OptionalReagents[i].Read(data);
var optionalReagents = data.ReadUInt32();
for (var i = 0; i < optionalCurrencies; ++i)
OptionalCurrencies[i].Read(data);
SendCastFlags = data.ReadBits<uint>(5);
bool hasMoveUpdate = data.HasBit();
bool hasCraftingOrderID = data.HasBit();
var weightCount = data.ReadBits<uint>(2);
Target.Read(data);
if (hasCraftingOrderID)
CraftingOrderID = data.ReadUInt64();
for (var i = 0; i < optionalReagents; ++i)
OptionalReagents[i].Read(data);
if (hasMoveUpdate)
MoveUpdate = MovementExtensions.ReadMovementInfo(data);
@@ -1884,6 +1880,34 @@ namespace Game.Networking.Packets
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 float ModifierValue;
@@ -58,6 +58,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt16(MaxPlayerNameQueriesPerPacket);
_worldPacket.WriteInt16(PlayerNameQueryTelemetryInterval);
_worldPacket.WriteUInt32((uint)PlayerNameQueryInterval.TotalSeconds);
foreach (GameRuleValuePair gameRuleValue in GameRuleValues)
gameRuleValue.Write(_worldPacket);
@@ -70,6 +71,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(BpayStoreDisabledByParentalControls);
_worldPacket.WriteBit(ItemRestorationButtonEnabled);
_worldPacket.WriteBit(BrowserEnabled);
_worldPacket.WriteBit(SessionAlert.HasValue);
_worldPacket.WriteBit(RAFSystem.Enabled);
_worldPacket.WriteBit(RAFSystem.RecruitingEnabled);
@@ -78,6 +80,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(CommerceSystemEnabled);
_worldPacket.WriteBit(TutorialsEnabled);
_worldPacket.WriteBit(TwitterEnabled);
_worldPacket.WriteBit(Unk67);
_worldPacket.WriteBit(WillKickFromWorld);
_worldPacket.WriteBit(KioskModeEnabled);
@@ -86,6 +89,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(WarModeFeatureEnabled);
_worldPacket.WriteBit(ClubsEnabled);
_worldPacket.WriteBit(ClubsBattleNetClubTypeAllowed);
_worldPacket.WriteBit(ClubsCharacterClubTypeAllowed);
_worldPacket.WriteBit(ClubsPresenceUpdateEnabled);
_worldPacket.WriteBit(VoiceChatDisabledByParentalControl);
@@ -94,10 +98,14 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(IsMuted);
_worldPacket.WriteBit(ClubFinderEnabled);
_worldPacket.WriteBit(Unknown901CheckoutRelated);
_worldPacket.WriteBit(TextToSpeechFeatureEnabled);
_worldPacket.WriteBit(ChatDisabledByDefault);
_worldPacket.WriteBit(ChatDisabledByPlayer);
_worldPacket.WriteBit(LFGListCustomRequiresAuthenticator);
_worldPacket.WriteBit(AddonsDisabled);
_worldPacket.WriteBit(Unused1000);
_worldPacket.FlushBits();
{
@@ -164,6 +172,7 @@ namespace Game.Networking.Packets
public int ActiveSeason; // Currently active Classic season
public short MaxPlayerNameQueriesPerPacket = 50;
public short PlayerNameQueryTelemetryInterval = 600;
public TimeSpan PlayerNameQueryInterval = TimeSpan.FromSeconds(10);
public bool ItemRestorationButtonEnabled;
public bool CharUndeleteEnabled; // Implemented
public bool BpayStoreDisabledByParentalControls;
@@ -192,6 +201,8 @@ namespace Game.Networking.Packets
public bool ChatDisabledByDefault;
public bool ChatDisabledByPlayer;
public bool LFGListCustomRequiresAuthenticator;
public bool AddonsDisabled;
public bool Unused1000;
public SocialQueueConfig QuickJoinConfig;
public SquelchInfo Squelch;
@@ -264,6 +275,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(Unk14);
_worldPacket.WriteBit(WillKickFromWorld);
_worldPacket.WriteBit(IsExpansionPreorderInStore);
_worldPacket.WriteBit(KioskModeEnabled);
_worldPacket.WriteBit(CompetitiveModeEnabled);
_worldPacket.WriteBit(TrialBoostEnabled);
@@ -272,9 +284,12 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(LiveRegionCharacterCopyEnabled);
_worldPacket.WriteBit(LiveRegionAccountCopyEnabled);
_worldPacket.WriteBit(LiveRegionKeyBindingsCopyEnabled);
_worldPacket.WriteBit(Unknown901CheckoutRelated);
_worldPacket.WriteBit(EuropaTicketSystemStatus.HasValue);
_worldPacket.WriteBit(LaunchETA.HasValue);
_worldPacket.WriteBit(AddonsDisabled);
_worldPacket.WriteBit(Unused1000);
_worldPacket.FlushBits();
if (EuropaTicketSystemStatus.HasValue)
@@ -294,6 +309,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt32(GameRuleValues.Count);
_worldPacket.WriteInt16(MaxPlayerNameQueriesPerPacket);
_worldPacket.WriteInt16(PlayerNameQueryTelemetryInterval);
_worldPacket.WriteUInt32((uint)PlayerNameQueryInterval.TotalSeconds);
if (LaunchETA.HasValue)
_worldPacket.WriteInt32(LaunchETA.Value);
@@ -320,8 +336,10 @@ namespace Game.Networking.Packets
public bool LiveRegionCharacterListEnabled; // NYI
public bool LiveRegionCharacterCopyEnabled; // NYI
public bool LiveRegionAccountCopyEnabled; // NYI
public bool LiveRegionKeyBindingsCopyEnabled = false;
public bool Unknown901CheckoutRelated = false; // NYI
public bool LiveRegionKeyBindingsCopyEnabled;
public bool Unknown901CheckoutRelated; // NYI
public bool AddonsDisabled;
public bool Unused1000;
public EuropaTicketConfig? EuropaTicketSystemStatus;
public List<int> LiveRegionCharacterCopySourceRegions = new();
public uint TokenPollTimeSeconds; // NYI
@@ -337,6 +355,7 @@ namespace Game.Networking.Packets
public List<GameRuleValuePair> GameRuleValues = new();
public short MaxPlayerNameQueriesPerPacket = 50;
public short PlayerNameQueryTelemetryInterval = 600;
public TimeSpan PlayerNameQueryInterval = TimeSpan.FromSeconds(10);
public int? LaunchETA;
}
@@ -368,12 +387,18 @@ namespace Game.Networking.Packets
{
_worldPacket.WriteBits(ServerTimeTZ.GetByteCount(), 7);
_worldPacket.WriteBits(GameTimeTZ.GetByteCount(), 7);
_worldPacket.WriteBits(ServerRegionalTZ.GetByteCount(), 7);
_worldPacket.FlushBits();
_worldPacket.WriteString(ServerTimeTZ);
_worldPacket.WriteString(GameTimeTZ);
_worldPacket.WriteString(ServerRegionalTZ);
}
public string ServerTimeTZ;
public string GameTimeTZ;
public string ServerRegionalTZ;
}
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();
}
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
{
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)
{
if (player)
@@ -498,6 +585,20 @@ namespace Game
response.Info.PortraitTurnInText = PortraitTurnInText;
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)
{
var questTemplateLocale = Global.ObjectMgr.GetQuestLocale(Id);
@@ -596,6 +697,7 @@ namespace Game
response.Info.Expansion = Expansion;
response.Info.ManagedWorldStateID = ManagedWorldStateID;
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)
{
@@ -744,6 +846,12 @@ namespace Game
public string PortraitTurnInName = "";
public string QuestCompletionLog = "";
// quest_description_conditional
public List<QuestConditionalText> ConditionalQuestDescription = new();
// quest_completion_log_conditional
public List<QuestConditionalText> ConditionalQuestCompletionLog = new();
// quest_detais table
public uint[] DetailsEmote = new uint[SharedConst.QuestEmoteCount];
public uint[] DetailsEmoteDelay = new uint[SharedConst.QuestEmoteCount];
@@ -755,11 +863,17 @@ namespace Game
public uint EmoteOnIncompleteDelay;
public string RequestItemsText = "";
// quest_request_items_conditional
public List<QuestConditionalText> ConditionalRequestItemsText = new();
// quest_offer_reward table
public int[] OfferRewardEmote = new int[SharedConst.QuestEmoteCount];
public uint[] OfferRewardEmoteDelay = new uint[SharedConst.QuestEmoteCount];
public string OfferRewardText = "";
// quest_offer_reward_conditional
public List<QuestConditionalText> ConditionalOfferRewardText = new();
// quest_template_addon table (custom data)
public uint MaxLevel { 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 uint Id;
@@ -239,7 +239,6 @@ namespace Game
public void SendState(FactionState faction)
{
SetFactionStanding setFactionStanding = new();
setFactionStanding.ReferAFriendBonus = 0.0f;
setFactionStanding.BonusFromAchievementSystem = 0.0f;
if (faction != null)
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
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
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
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.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)
{
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
Values[WorldCfg.CharactersPerAccount] = GetDefaultValue("CharactersPerAccount", 50);
Values[WorldCfg.CharactersPerAccount] = GetDefaultValue("CharactersPerAccount", 60);
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]);
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.CharacterCreatingMinLevelForEvoker] = GetDefaultValue("CharacterCreating.MinLevelForEvoker", 50);
Values[WorldCfg.CharacterCreatingDisableAlliedRaceAchievementRequirement] = GetDefaultValue("CharacterCreating.DisableAlliedRaceAchievementRequirement", false);
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))
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())
return SpellCastResult.AffectingCombat;
}
@@ -5589,21 +5594,15 @@ namespace Game.Spells
if (spellEffectInfo.Effect == SpellEffectName.ChangeBattlepetQuality)
{
var qualityRecord = CliDB.BattlePetBreedQualityStorage.Values.FirstOrDefault(a1 => a1.MaxQualityRoll < spellEffectInfo.BasePoints);
BattlePetBreedQuality quality = BattlePetBreedQuality.Poor;
switch (spellEffectInfo.BasePoints)
{
case 85:
quality = BattlePetBreedQuality.Rare;
break;
case 75:
quality = BattlePetBreedQuality.Uncommon;
break;
default:
// Ignore Epic Battle-Stones
break;
}
if (qualityRecord != null)
quality = (BattlePetBreedQuality)qualityRecord.QualityEnum;
if (battlePet.PacketInfo.Quality >= (byte)quality)
return SpellCastResult.CantUpgradeBattlePet;
}
if (spellEffectInfo.Effect == SpellEffectName.GrantBattlepetLevel || spellEffectInfo.Effect == SpellEffectName.GrantBattlepetExperience)
@@ -6634,21 +6633,21 @@ namespace Game.Spells
{
Item item = m_targets.GetItemTarget();
if (!item)
return SpellCastResult.CantBeDisenchanted;
return SpellCastResult.CantBeSalvaged;
// prevent disenchanting in trade slot
if (item.GetOwnerGUID() != player.GetGUID())
return SpellCastResult.CantBeDisenchanted;
return SpellCastResult.CantBeSalvaged;
ItemTemplate itemProto = item.GetTemplate();
if (itemProto == null)
return SpellCastResult.CantBeDisenchanted;
return SpellCastResult.CantBeSalvaged;
ItemDisenchantLootRecord itemDisenchantLoot = item.GetDisenchantLoot(m_caster.ToPlayer());
if (itemDisenchantLoot == null)
return SpellCastResult.CantBeDisenchanted;
return SpellCastResult.CantBeSalvaged;
if (itemDisenchantLoot.SkillRequired > player.GetSkillValue(SkillType.Enchanting))
return SpellCastResult.LowCastlevel;
return SpellCastResult.CantBeSalvagedSkill;
break;
}
case SpellEffectName.Prospecting:
+79 -37
View File
@@ -2127,30 +2127,7 @@ namespace Game.Spells
}
// select enchantment duration
uint 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
uint duration = (uint)pEnchant.Duration;
// item can be in trade slot and have owner diff. from caster
Player item_owner = itemTarget.GetOwner();
@@ -5208,19 +5185,11 @@ namespace Game.Spells
if (unitTarget == null || !unitTarget.IsCreature())
return;
var quality = BattlePetBreedQuality.Poor;
switch (damage)
{
case 85:
quality = BattlePetBreedQuality.Rare;
break;
case 75:
quality = BattlePetBreedQuality.Uncommon;
break;
default:
// Ignore Epic Battle-Stones
break;
}
var qualityRecord = CliDB.BattlePetBreedQualityStorage.Values.FirstOrDefault(a1 => a1.MaxQualityRoll < damage);
BattlePetBreedQuality quality = BattlePetBreedQuality.Poor;
if (qualityRecord != null)
quality = (BattlePetBreedQuality)qualityRecord.QualityEnum;
playerCaster.GetSession().GetBattlePetMgr().ChangeBattlePetQuality(unitTarget.GetBattlePetCompanionGUID(), quality);
}
@@ -5634,6 +5603,79 @@ namespace Game.Spells
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
+24 -7
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);
if (offset.TotalMilliseconds == 0 || cooldownEntry == null)
if (cooldownMod.TotalMilliseconds == 0 || cooldownEntry == null)
return;
ModifySpellCooldown(cooldownEntry, cooldownMod, withoutCategoryCooldown);
}
void ModifySpellCooldown(CooldownEntry cooldownEntry, TimeSpan cooldownMod, bool withoutCategoryCooldown)
{
DateTime now = GameTime.GetSystemTime();
cooldownEntry.CooldownEnd += offset;
cooldownEntry.CooldownEnd += cooldownMod;
if (cooldownEntry.CategoryId != 0)
{
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
if (cooldownEntry.CooldownEnd < cooldownEntry.CategoryEnd)
@@ -537,7 +542,7 @@ namespace Game.Spells
if (cooldownEntry.CooldownEnd <= now)
{
_categoryCooldowns.Remove(cooldownEntry.CategoryId);
_spellCooldowns.Remove(spellId);
_spellCooldowns.Remove(cooldownEntry.SpellId);
}
Player playerOwner = GetPlayerOwner();
@@ -545,8 +550,8 @@ namespace Game.Spells
{
ModifyCooldown modifyCooldown = new();
modifyCooldown.IsPet = _owner != playerOwner;
modifyCooldown.SpellID = spellId;
modifyCooldown.DeltaTime = (int)offset.TotalMilliseconds;
modifyCooldown.SpellID = cooldownEntry.SpellId;
modifyCooldown.DeltaTime = (int)cooldownMod.TotalMilliseconds;
modifyCooldown.WithoutCategoryCooldown = withoutCategoryCooldown;
playerOwner.SendPacket(modifyCooldown);
}
@@ -570,6 +575,15 @@ namespace Game.Spells
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)
{
var entry = _spellCooldowns.LookupByKey(spellId);
@@ -635,6 +649,9 @@ namespace Game.Spells
if (_spellCooldowns.ContainsKey(spellInfo.Id))
return true;
if (spellInfo.CooldownAuraSpellId != 0 && _owner.HasAura(spellInfo.CooldownAuraSpellId))
return true;
uint category = 0;
GetCooldownDurations(spellInfo, itemId, ref category);
+58 -3
View File
@@ -120,6 +120,10 @@ namespace Game.Spells
TargetAuraSpell = _aura.TargetAuraSpell;
ExcludeCasterAuraSpell = _aura.ExcludeCasterAuraSpell;
ExcludeTargetAuraSpell = _aura.ExcludeTargetAuraSpell;
CasterAuraType = (AuraType)_aura.CasterAuraType;
TargetAuraType = (AuraType)_aura.TargetAuraType;
ExcludeCasterAuraType = (AuraType)_aura.ExcludeCasterAuraType;
ExcludeTargetAuraType = (AuraType)_aura.ExcludeTargetAuraType;
}
RequiredAreasID = -1;
@@ -161,6 +165,7 @@ namespace Game.Spells
RecoveryTime = _cooldowns.RecoveryTime;
CategoryRecoveryTime = _cooldowns.CategoryRecoveryTime;
StartRecoveryTime = _cooldowns.StartRecoveryTime;
CooldownAuraSpellId = _cooldowns.AuraSpellID;
}
EquippedItemClass = ItemClass.None;
@@ -2855,7 +2860,7 @@ namespace Game.Spells
}
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
{
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 =>
{
return aurEff.GetMiscValue() == (int)power.PowerType && aurEff.IsAffectingSpell(this);
@@ -3964,11 +3999,16 @@ namespace Game.Spells
public uint TargetAuraSpell { get; set; }
public uint ExcludeCasterAuraSpell { 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 uint RecoveryTime { get; set; }
public uint CategoryRecoveryTime { get; set; }
public uint StartRecoveryCategory { get; set; }
public uint StartRecoveryTime { get; set; }
public uint CooldownAuraSpellId { get; set; }
public SpellInterruptFlags InterruptFlags { get; set; }
public SpellAuraInterruptFlags AuraInterruptFlags { 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), // 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), // 288 SPELL_EFFECT_288
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 289 SPELL_EFFECT_289
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 288 SPELL_EFFECT_CRAFT_ITEM
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
+52 -46
View File
@@ -2471,17 +2471,19 @@ namespace Game.Entities
"AttributesEx4, AttributesEx5, AttributesEx6, AttributesEx7, AttributesEx8, AttributesEx9, AttributesEx10, AttributesEx11, AttributesEx12, AttributesEx13, " +
//19 20 21 22 23 24 25 26 27
"AttributesEx14, Stances, StancesNot, Targets, TargetCreatureType, RequiresSpellFocus, FacingCasterFlags, CasterAuraState, TargetAuraState, " +
//28 29 30 31 32 33 34
"ExcludeCasterAuraState, ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, CastingTimeIndex, " +
//35 36 37 38 39 40 41
//28 29 30 31 32 33
"ExcludeCasterAuraState, ExcludeTargetAuraState, CasterAuraSpell, TargetAuraSpell, ExcludeCasterAuraSpell, ExcludeTargetAuraSpell, " +
//34 35 36 37 38
"CasterAuraType, TargetAuraType, ExcludeCasterAuraType, ExcludeTargetAuraType, CastingTimeIndex, " +
//39 40 41 42 43 44 45
"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, " +
//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, " +
//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, " +
//72 73 74 75 76
//76 77 78 79 80
"DmgClass, PreventionType, AreaGroupId, SchoolMask, ChargeCategoryId FROM serverside_spell");
if (!spellsResult.IsEmpty())
@@ -2496,7 +2498,7 @@ namespace Game.Entities
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.CategoryId = spellsResult.Read<uint>(2);
@@ -2531,44 +2533,48 @@ namespace Game.Entities
spellInfo.TargetAuraSpell = spellsResult.Read<uint>(31);
spellInfo.ExcludeCasterAuraSpell = spellsResult.Read<uint>(32);
spellInfo.ExcludeTargetAuraSpell = spellsResult.Read<uint>(33);
spellInfo.CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(spellsResult.Read<uint>(34));
spellInfo.RecoveryTime = spellsResult.Read<uint>(35);
spellInfo.CategoryRecoveryTime = spellsResult.Read<uint>(36);
spellInfo.StartRecoveryCategory = spellsResult.Read<uint>(37);
spellInfo.StartRecoveryTime = spellsResult.Read<uint>(38);
spellInfo.InterruptFlags = (SpellInterruptFlags)spellsResult.Read<uint>(39);
spellInfo.AuraInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(40);
spellInfo.AuraInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(41);
spellInfo.ChannelInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(42);
spellInfo.ChannelInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(43);
spellInfo.ProcFlags = new ProcFlagsInit(spellsResult.Read<int>(44), spellsResult.Read<int>(45));
spellInfo.ProcChance = spellsResult.Read<uint>(46);
spellInfo.ProcCharges = spellsResult.Read<uint>(47);
spellInfo.ProcCooldown = spellsResult.Read<uint>(48);
spellInfo.ProcBasePPM = spellsResult.Read<float>(49);
spellInfo.MaxLevel = spellsResult.Read<uint>(50);
spellInfo.BaseLevel = spellsResult.Read<uint>(51);
spellInfo.SpellLevel = spellsResult.Read<uint>(52);
spellInfo.DurationEntry = CliDB.SpellDurationStorage.LookupByKey(spellsResult.Read<uint>(53));
spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(spellsResult.Read<uint>(54));
spellInfo.Speed = spellsResult.Read<float>(55);
spellInfo.LaunchDelay = spellsResult.Read<float>(56);
spellInfo.StackAmount = spellsResult.Read<uint>(57);
spellInfo.EquippedItemClass = (ItemClass)spellsResult.Read<int>(58);
spellInfo.EquippedItemSubClassMask = spellsResult.Read<int>(59);
spellInfo.EquippedItemInventoryTypeMask = spellsResult.Read<int>(60);
spellInfo.ContentTuningId = spellsResult.Read<uint>(61);
spellInfo.ConeAngle = spellsResult.Read<float>(63);
spellInfo.Width = spellsResult.Read<float>(64);
spellInfo.MaxTargetLevel = spellsResult.Read<uint>(65);
spellInfo.MaxAffectedTargets = spellsResult.Read<uint>(66);
spellInfo.SpellFamilyName = (SpellFamilyNames)spellsResult.Read<uint>(67);
spellInfo.SpellFamilyFlags = new FlagArray128(spellsResult.Read<uint>(68), spellsResult.Read<uint>(69), spellsResult.Read<uint>(70), spellsResult.Read<uint>(71));
spellInfo.DmgClass = (SpellDmgClass)spellsResult.Read<uint>(72);
spellInfo.PreventionType = (SpellPreventionType)spellsResult.Read<uint>(73);
spellInfo.RequiredAreasID = spellsResult.Read<int>(74);
spellInfo.SchoolMask = (SpellSchoolMask)spellsResult.Read<uint>(75);
spellInfo.ChargeCategoryId = spellsResult.Read<uint>(76);
spellInfo.CasterAuraType = (AuraType)spellsResult.Read<int>(34);
spellInfo.TargetAuraType = (AuraType)spellsResult.Read<int>(35);
spellInfo.ExcludeCasterAuraType = (AuraType)spellsResult.Read<int>(36);
spellInfo.ExcludeTargetAuraType = (AuraType)spellsResult.Read<int>(37);
spellInfo.CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(spellsResult.Read<uint>(38));
spellInfo.RecoveryTime = spellsResult.Read<uint>(39);
spellInfo.CategoryRecoveryTime = spellsResult.Read<uint>(40);
spellInfo.StartRecoveryCategory = spellsResult.Read<uint>(41);
spellInfo.StartRecoveryTime = spellsResult.Read<uint>(42);
spellInfo.InterruptFlags = (SpellInterruptFlags)spellsResult.Read<uint>(43);
spellInfo.AuraInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(44);
spellInfo.AuraInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(45);
spellInfo.ChannelInterruptFlags = (SpellAuraInterruptFlags)spellsResult.Read<uint>(46);
spellInfo.ChannelInterruptFlags2 = (SpellAuraInterruptFlags2)spellsResult.Read<uint>(47);
spellInfo.ProcFlags = new ProcFlagsInit(spellsResult.Read<int>(48), spellsResult.Read<int>(49));
spellInfo.ProcChance = spellsResult.Read<uint>(50);
spellInfo.ProcCharges = spellsResult.Read<uint>(51);
spellInfo.ProcCooldown = spellsResult.Read<uint>(52);
spellInfo.ProcBasePPM = spellsResult.Read<float>(53);
spellInfo.MaxLevel = spellsResult.Read<uint>(54);
spellInfo.BaseLevel = spellsResult.Read<uint>(55);
spellInfo.SpellLevel = spellsResult.Read<uint>(56);
spellInfo.DurationEntry = CliDB.SpellDurationStorage.LookupByKey(spellsResult.Read<uint>(57));
spellInfo.RangeEntry = CliDB.SpellRangeStorage.LookupByKey(spellsResult.Read<uint>(58));
spellInfo.Speed = spellsResult.Read<float>(59);
spellInfo.LaunchDelay = spellsResult.Read<float>(60);
spellInfo.StackAmount = spellsResult.Read<uint>(61);
spellInfo.EquippedItemClass = (ItemClass)spellsResult.Read<int>(62);
spellInfo.EquippedItemSubClassMask = spellsResult.Read<int>(63);
spellInfo.EquippedItemInventoryTypeMask = spellsResult.Read<int>(64);
spellInfo.ContentTuningId = spellsResult.Read<uint>(65);
spellInfo.ConeAngle = spellsResult.Read<float>(67);
spellInfo.Width = spellsResult.Read<float>(68);
spellInfo.MaxTargetLevel = spellsResult.Read<uint>(69);
spellInfo.MaxAffectedTargets = spellsResult.Read<uint>(70);
spellInfo.SpellFamilyName = (SpellFamilyNames)spellsResult.Read<uint>(71);
spellInfo.SpellFamilyFlags = new FlagArray128(spellsResult.Read<uint>(72), spellsResult.Read<uint>(73), spellsResult.Read<uint>(74), spellsResult.Read<uint>(75));
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);
-3
View File
@@ -890,9 +890,6 @@ namespace Game
Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu addon...");
Global.ObjectMgr.LoadGossipMenuAddon();
Log.outInfo(LogFilter.ServerLoading, "Loading Gossip menu item addon...");
Global.ObjectMgr.LoadGossipMenuItemAddon();
Log.outInfo(LogFilter.ServerLoading, "Loading Creature trainers...");
Global.ObjectMgr.LoadCreatureTrainers(); // must be after LoadGossipMenuItems
+4 -2
View File
@@ -3281,8 +3281,10 @@ namespace Scripts.Spells.Generic
Unit target = GetHitUnit();
if (target)
{
SpiritHealerConfirm spiritHealerConfirm = new();
spiritHealerConfirm.Unit = target.GetGUID();
NPCInteractionOpenResult spiritHealerConfirm = new();
spiritHealerConfirm.Npc = target.GetGUID();
spiritHealerConfirm.InteractionType = PlayerInteractionType.SpiritHealer;
spiritHealerConfirm.Success = true;
originalCaster.SendPacket(spiritHealerConfirm);
}
}
+19 -2
View File
@@ -806,9 +806,17 @@ CharactersPerAccount = 50
# CharactersPerRealm
# Description: Limit number of characters per account on this realm.
# 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
@@ -819,6 +827,15 @@ CharactersPerRealm = 50
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
# Description: Disable achievement requirements for allied race character creation