Core: Updated to 10.0.2
Port From (https://github.com/TrinityCore/TrinityCore/commit/e98e1283ea0034baf6be9aa2ffb386eb5582801b)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+1159
-1075
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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,15 +691,15 @@ 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");
|
||||
PrepareStatement(HotfixStatements.SEL_ITEM_SPARSE_LOCALE, "SELECT ID, Description_lang, Display3_lang, Display2_lang, Display1_lang, Display_lang" +
|
||||
"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 = ?");
|
||||
|
||||
// ItemSpec.db2
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,8 +187,9 @@ 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)
|
||||
SetItem(index, uint.Parse(items[(int)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));
|
||||
SetClass(field.Read<byte>(8));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GossipMenuItem menuItem = new();
|
||||
if (gossipOptionId == 0)
|
||||
gossipOptionId = -((int)_menuId * 100 + orderIndex);
|
||||
|
||||
GossipMenuItem menuItem = new();
|
||||
menuItem.GossipOptionID = gossipOptionId;
|
||||
menuItem.OrderIndex = (uint)orderIndex;
|
||||
menuItem.OptionNpc = optionNpc;
|
||||
menuItem.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 (gossipMenuLocale != null)
|
||||
ObjectManager.GetLocaleString(gossipMenuLocale.BoxText, GetLocale(), ref strBoxText);
|
||||
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 0;
|
||||
return _menuItems.Values.FirstOrDefault(item => item.GossipOptionID == gossipOptionId);
|
||||
}
|
||||
|
||||
public uint GetMenuItemAction(uint menuItemId)
|
||||
GossipMenuItem GetItemByIndex(uint orderIndex)
|
||||
{
|
||||
if (_menuItems.ContainsKey(menuItemId))
|
||||
return _menuItems.LookupByKey(menuItemId).Action;
|
||||
else
|
||||
return 0;
|
||||
return _menuItems.LookupByKey(orderIndex);
|
||||
}
|
||||
|
||||
public bool IsMenuItemCoded(uint menuItemId)
|
||||
public uint GetMenuItemSender(uint orderIndex)
|
||||
{
|
||||
if (_menuItems.ContainsKey(menuItemId))
|
||||
return _menuItems.LookupByKey(menuItemId).IsCoded;
|
||||
else
|
||||
return false;
|
||||
GossipMenuItem item = GetItemByIndex(orderIndex);
|
||||
if (item != null)
|
||||
return item.Sender;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint GetMenuItemAction(uint orderIndex)
|
||||
{
|
||||
GossipMenuItem item = GetItemByIndex(orderIndex);
|
||||
if (item != null)
|
||||
return item.Action;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool IsMenuItemCoded(uint orderIndex)
|
||||
{
|
||||
GossipMenuItem item = GetItemByIndex(orderIndex);
|
||||
if (item != null)
|
||||
return item.BoxCoded;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ClearMenu()
|
||||
{
|
||||
_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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,9 +802,13 @@ 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)
|
||||
public bool CanBeTraded(bool mail = false, bool trade = false)
|
||||
{
|
||||
if (m_lootGenerated)
|
||||
return 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
@@ -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)
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
if (item.ActionPoiID != 0)
|
||||
PlayerTalkClass.SendPointOfInterest(item.ActionPoiID);
|
||||
|
||||
if (item.ActionMenuID != 0)
|
||||
{
|
||||
PrepareGossipMenu(source, item.ActionMenuID);
|
||||
SendPreparedGossip(source);
|
||||
}
|
||||
|
||||
// types that have their dedicated open opcode dont send WorldPackets::NPC::GossipOptionNPCInteraction
|
||||
bool handled = true;
|
||||
switch (gossipOptionNpc)
|
||||
{
|
||||
case GossipOptionNpc.None:
|
||||
{
|
||||
if (menuItemData.GossipActionPoi != 0)
|
||||
PlayerTalkClass.SendPointOfInterest(menuItemData.GossipActionPoi);
|
||||
|
||||
if (menuItemData.GossipActionMenuId != 0)
|
||||
{
|
||||
PrepareGossipMenu(source, menuItemData.GossipActionMenuId);
|
||||
SendPreparedGossip(source);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case GossipOptionNpc.Vendor:
|
||||
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:
|
||||
case GossipOptionNpc.GarrisonTradeskillNpc: // NYI
|
||||
break;
|
||||
case GossipOptionNpc.GarrisonRecruitment: // NYI
|
||||
break;
|
||||
case GossipOptionNpc.ChromieTimeNpc: // NYI
|
||||
break;
|
||||
case GossipOptionNpc.RuneforgeLegendaryCrafting: // NYI
|
||||
break;
|
||||
case GossipOptionNpc.RuneforgeLegendaryUpgrade: // NYI
|
||||
break;
|
||||
case GossipOptionNpc.ProfessionsCraftingOrder: // NYI
|
||||
break;
|
||||
case GossipOptionNpc.ProfessionsCustomerOrder: // NYI
|
||||
break;
|
||||
case GossipOptionNpc.BarbersChoice: // NYI - unknown if needs sending
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
if (item.GossipNpcOptionID.HasValue)
|
||||
{
|
||||
GossipMenuAddon addon = Global.ObjectMgr.GetGossipMenuAddon(menuId);
|
||||
GossipMenuItemAddon itemAddon = Global.ObjectMgr.GetGossipMenuItemAddon(menuId, gossipListId);
|
||||
SendGarrisonOpenTalentNpc(guid, itemAddon != null ? itemAddon.GarrTalentTreeID.GetValueOrDefault(0) : 0, addon != null ? addon.FriendshipFactionID : 0);
|
||||
break;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
case GossipOptionNpc.Transmogrify:
|
||||
GetSession().SendOpenTransmogrifier(guid);
|
||||
break;
|
||||
case GossipOptionNpc.AzeriteRespec:
|
||||
PlayerTalkClass.SendCloseGossip();
|
||||
GetSession().SendAzeriteRespecNPC(guid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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); }
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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})");
|
||||
SendCharCreate(ResponseCodes.CharCreateExpansionClass);
|
||||
return;
|
||||
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,8 +500,17 @@ 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?
|
||||
if (!allowTwoSideAccounts)
|
||||
@@ -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));
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -444,7 +457,7 @@ namespace Game.Networking.Packets
|
||||
public int SlotInBag;
|
||||
public ItemInstance Item;
|
||||
public int QuestLogItemID;// Item ID used for updating quest progress
|
||||
// only set if different than real ID (similar to CreatureTemplate.KillCredit)
|
||||
// only set if different than real ID (similar to CreatureTemplate.KillCredit)
|
||||
public uint Quantity;
|
||||
public uint QuantityInInventory;
|
||||
public int DungeonEncounterID;
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
_worldPacket.WriteBit(TextID.HasValue);
|
||||
_worldPacket.WriteBit(TextID2.HasValue);
|
||||
_worldPacket.FlushBits();
|
||||
|
||||
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);
|
||||
options.Write(_worldPacket);
|
||||
|
||||
_worldPacket.WriteBits(options.Text.GetByteCount(), 12);
|
||||
_worldPacket.WriteBits(options.Confirm.GetByteCount(), 12);
|
||||
_worldPacket.WriteBits((byte)options.Status, 2);
|
||||
_worldPacket.WriteBit(options.SpellID.HasValue);
|
||||
_worldPacket.FlushBits();
|
||||
if (TextID.HasValue)
|
||||
_worldPacket.WriteInt32(TextID.Value);
|
||||
|
||||
options.Treasure.Write(_worldPacket);
|
||||
|
||||
_worldPacket.WriteString(options.Text);
|
||||
_worldPacket.WriteString(options.Confirm);
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user