Core: Update to 10.1.5
Port From (https://github.com/TrinityCore/TrinityCore/commit/0cea730fa23473a85c47451c3bd13df816f2b6e4)
This commit is contained in:
@@ -424,9 +424,29 @@ namespace Framework.Constants
|
||||
|
||||
PlayerHasPerksProgramPendingReward = 350,
|
||||
PlayerCanUseItem = 351, // Player can use item {#Item}
|
||||
PlayerSummonedBattlePetSpecies = 352,
|
||||
PlayerSummonedBattlePetIsMaxLevel = 353,
|
||||
|
||||
PlayerHasAtLeastProfPathRanks = 355, // Player has purchased or granted at least {#Count} ranks in {SkillLine} config
|
||||
PlayerHasAtLeastMissingProfPathRanks = 356, /*NYI*/ // Player is missing least {#Count} ranks in {SkillLine} config
|
||||
|
||||
PlayerHasItemTransmogrifiedToItemModifiedAppearance = 358, // Player has item with {ItemModifiedAppearance} transmog
|
||||
ItemHasBonusList = 359, /*NYI*/ // Item has {ItemBonusList} (used by ItemCondition)
|
||||
ItemHasBonusListFromGroup = 360, /*NYI*/ // Item has a bonus list from {ItemBonusListGroup} (used by ItemCondition)
|
||||
ItemHasContext = 361, /*NYI*/ // Item has {ItemContext}
|
||||
ItemHasItemLevelBetween = 362, /*NYI*/ // Item has item level between {#Min} and {#Max}
|
||||
ItemHasContentTuningID = 363, /*NYI*/ // Item has {ContentTuning} (modifier 28)
|
||||
ItemHasInventoryType = 364, /*NYI*/ // Item has inventory type
|
||||
ItemWasCraftedWithReagentInSlot = 365, /*NYI*/ // Item was crafted with reagent item {Item} in slot {ModifiedCraftingReagentSlot}
|
||||
PlayerHasCompletedDungeonEncounterInDifficulty = 366, // Player has completed {DungeonEncounter} on {Difficulty}
|
||||
PlayerCurrencyIsRelOpFromMax = 367, /*NYI*/ // Player {CurrencyTypes} is {RelOp} {#Amount} from currency limit
|
||||
ItemHasModifiedCraftingReagentSlot = 368, /*NYI*/ // Item has {ModifiedCraftingReagentSlot}
|
||||
PlayerIsBetweenQuests = 369, // Player has previously completed quest or is on "{QuestV2}" but not "{QuestV2}" (SecondaryAsset)
|
||||
PlayerIsOnQuestWithLabel = 370, /*NYI*/ // Player is on quest with {QuestLabel}
|
||||
PlayerScenarioStepID = 371, // Player is on scenario step number {ScenarioStep}
|
||||
PlayerHasCompletedQuestWithLabel = 372, /*NYI*/ // Player has previously completed quest with {QuestLabel}
|
||||
LegacyLootIsEnabled = 373, /*NYI*/
|
||||
PlayerZPositionBelow = 374,
|
||||
}
|
||||
|
||||
public enum CriteriaFailEvent : byte
|
||||
@@ -723,6 +743,7 @@ namespace Framework.Constants
|
||||
FulfillCraftingOrderType = 246, /*NYI*/ // {CraftingOrderType}
|
||||
|
||||
PerksProgramMonthComplete = 249, /*NYI*/
|
||||
CompleteTrackingQuest = 250, /*NYI*/
|
||||
|
||||
Count
|
||||
}
|
||||
|
||||
@@ -456,4 +456,14 @@ namespace Framework.Constants
|
||||
HordeCaptured = 4,
|
||||
AllianceCaptured = 5
|
||||
}
|
||||
|
||||
public enum PVPMatchState : byte
|
||||
{
|
||||
Waiting = 0,
|
||||
StartUp = 1,
|
||||
Engaged = 2,
|
||||
PostRound = 3,
|
||||
Inactive = 4,
|
||||
Complete = 5
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,8 @@ namespace Framework.Constants
|
||||
public enum ChatWhisperTargetStatus
|
||||
{
|
||||
CanWhisper = 0,
|
||||
Offline = 1,
|
||||
WrongFaction = 2
|
||||
CanWhisperGuild = 1,
|
||||
Offline = 2,
|
||||
WrongFaction = 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1904,7 +1904,7 @@ namespace Framework.Constants
|
||||
MonoValue = 0x400 // Skill always has value 1
|
||||
}
|
||||
|
||||
public enum SpellCategoryFlags : sbyte
|
||||
public enum SpellCategoryFlags : int
|
||||
{
|
||||
CooldownScalesWithWeaponSpeed = 0x01, // unused
|
||||
CooldownStartsOnEvent = 0x04,
|
||||
|
||||
@@ -11,7 +11,9 @@ namespace Framework.Constants
|
||||
Gameobject = 4,
|
||||
Calendar = 5,
|
||||
Blackmarket = 6,
|
||||
CommerceAuction = 7
|
||||
CommerceAuction = 7,
|
||||
Auction2 = 8,
|
||||
ArtisansConsortium = 9
|
||||
}
|
||||
|
||||
public enum MailCheckMask
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -96,6 +96,8 @@ namespace Framework.Constants
|
||||
ToolsClient = 50,
|
||||
WorldLayer = 51,
|
||||
ArenaTeam = 52,
|
||||
LMMParty = 53,
|
||||
LMMLobby = 54,
|
||||
|
||||
Count
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Framework.Constants
|
||||
{
|
||||
public enum CharmType
|
||||
@@ -29,6 +31,13 @@ namespace Framework.Constants
|
||||
NotInSlot = -1, // for avoid conflict with stable size grow will use negative value
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum PetStableFlags
|
||||
{
|
||||
Active = 0x1,
|
||||
Inactive = 0x2
|
||||
}
|
||||
|
||||
public enum PetSpellState
|
||||
{
|
||||
Unchanged = 0,
|
||||
@@ -88,23 +97,6 @@ namespace Framework.Constants
|
||||
DeclensionDoesntMatchBaseName = 16
|
||||
}
|
||||
|
||||
public enum PetStableinfo : byte
|
||||
{
|
||||
Active = 1,
|
||||
Inactive = 2
|
||||
}
|
||||
|
||||
public enum StableResult
|
||||
{
|
||||
NotEnoughMoney = 1, // "you don't have enough money"
|
||||
InvalidSlot = 3, // "That slot is locked"
|
||||
StableSuccess = 8, // stable success
|
||||
UnstableSuccess = 9, // unstable/swap success
|
||||
BuySlotSuccess = 10, // buy slot success
|
||||
CantControlExotic = 11, // "you are unable to control exotic creatures"
|
||||
InternalError = 12, // "Internal pet error"
|
||||
}
|
||||
|
||||
public enum PetTameResult
|
||||
{
|
||||
Ok = 0,
|
||||
@@ -123,4 +115,15 @@ namespace Framework.Constants
|
||||
InvalidSlot = 13,
|
||||
EliteTooHighLevel = 14
|
||||
}
|
||||
|
||||
public enum StableResult
|
||||
{
|
||||
NotEnoughMoney = 1, // "you don't have enough money"
|
||||
InvalidSlot = 3, // "That slot is locked"
|
||||
StableSuccess = 8, // stable success
|
||||
UnstableSuccess = 9, // unstable/swap success
|
||||
BuySlotSuccess = 10, // buy slot success
|
||||
CantControlExotic = 11, // "you are unable to control exotic creatures"
|
||||
InternalError = 12, // "Internal pet error"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ namespace Framework.Constants
|
||||
|
||||
public enum QuestSlotStateMask
|
||||
{
|
||||
None = 0x0000,
|
||||
Complete = 0x0001,
|
||||
Fail = 0x0002
|
||||
None = 0x00,
|
||||
Complete = 0x1,
|
||||
Fail = 0x2
|
||||
}
|
||||
|
||||
public enum QuestType
|
||||
@@ -402,7 +402,7 @@ namespace Framework.Constants
|
||||
Max
|
||||
}
|
||||
|
||||
public enum QuestGiverStatus : uint
|
||||
public enum QuestGiverStatus : ulong
|
||||
{
|
||||
None = 0x00,
|
||||
Future = 0x02,
|
||||
@@ -426,6 +426,16 @@ namespace Framework.Constants
|
||||
CovenantCallingQuest = 0x80000,
|
||||
CovenantCallingRewardCompleteNoPOI = 0x100000,
|
||||
CovenantCallingRewardCompletePOI = 0x200000,
|
||||
TrivialLegendaryQuest = 0x400000,
|
||||
FutureLegendaryQuest = 0x800000,
|
||||
LegendaryReward = 0x1000000,
|
||||
ImportantQuest = 0x2000000,
|
||||
ImportantQuestReward = 0x4000000,
|
||||
TrivialImportantQuest = 0x8000000,
|
||||
ImportantQuestRewardCompleteNoPOI = 0x20000000,
|
||||
ImportantQuestRewardCompletePOI = 0x40000000,
|
||||
TrivialJourneyQuest = 0x80000000,
|
||||
TrivialCovenantCallingQuest = 0x100000000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@@ -533,10 +543,10 @@ namespace Framework.Constants
|
||||
{
|
||||
None = 0x00,
|
||||
// Flags For Set Specialflags In Db If Required But Used Only At Server
|
||||
Repeatable = 0x001, // Set by 1 in SpecialFlags from DB
|
||||
AutoPushToParty = 0x002, // Set by 2 in SpecialFlags from DB will make quest be pushed to entire party when one member accepts it
|
||||
AutoAccept = 0x004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
|
||||
DfQuest = 0x008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
|
||||
Repeatable = 0x01, // Set by 1 in SpecialFlags from DB
|
||||
AutoPushToParty = 0x02, // Set by 2 in SpecialFlags from DB will make quest be pushed to entire party when one member accepts it
|
||||
AutoAccept = 0x04, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
|
||||
DfQuest = 0x08, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
|
||||
Monthly = 0x010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month
|
||||
// Room For More Custom Flags
|
||||
|
||||
|
||||
@@ -294,18 +294,6 @@ namespace Framework.Constants
|
||||
29, 30, 31, -1, 11, 12, 13, 14
|
||||
};
|
||||
|
||||
public static ulong RaceMaskAllPlayable = (ulong)(GetMaskForRace(Race.Human) | GetMaskForRace(Race.Orc) | GetMaskForRace(Race.Dwarf) | GetMaskForRace(Race.NightElf) | GetMaskForRace(Race.Undead)
|
||||
| GetMaskForRace(Race.Tauren) | GetMaskForRace(Race.Gnome) | GetMaskForRace(Race.Troll) | GetMaskForRace(Race.BloodElf) | GetMaskForRace(Race.Draenei)
|
||||
| GetMaskForRace(Race.Goblin) | GetMaskForRace(Race.Worgen) | GetMaskForRace(Race.PandarenNeutral) | GetMaskForRace(Race.PandarenAlliance) | GetMaskForRace(Race.PandarenHorde)
|
||||
| GetMaskForRace(Race.Nightborne) | GetMaskForRace(Race.HighmountainTauren) | GetMaskForRace(Race.VoidElf) | GetMaskForRace(Race.LightforgedDraenei) | GetMaskForRace(Race.ZandalariTroll)
|
||||
| GetMaskForRace(Race.KulTiran) | GetMaskForRace(Race.DarkIronDwarf) | GetMaskForRace(Race.Vulpera) | GetMaskForRace(Race.MagharOrc) | GetMaskForRace(Race.MechaGnome) | GetMaskForRace(Race.DracthyrAlliance) | GetMaskForRace(Race.DracthyrHorde));
|
||||
|
||||
public static ulong RaceMaskAlliance = (ulong)(GetMaskForRace(Race.Human) | GetMaskForRace(Race.Dwarf) | GetMaskForRace(Race.NightElf) | GetMaskForRace(Race.Gnome)
|
||||
| GetMaskForRace(Race.Draenei) | GetMaskForRace(Race.Worgen) | GetMaskForRace(Race.PandarenAlliance) | GetMaskForRace(Race.VoidElf) | GetMaskForRace(Race.LightforgedDraenei)
|
||||
| GetMaskForRace(Race.KulTiran) | GetMaskForRace(Race.DarkIronDwarf) | GetMaskForRace(Race.MechaGnome) | GetMaskForRace(Race.DracthyrAlliance));
|
||||
|
||||
public static ulong RaceMaskHorde = RaceMaskAllPlayable & ~RaceMaskAlliance;
|
||||
|
||||
//Todo move these else where
|
||||
/// <summary>
|
||||
/// Method Const
|
||||
@@ -418,55 +406,6 @@ namespace Framework.Constants
|
||||
CascLocaleBit.itIT
|
||||
};
|
||||
|
||||
static int GetRaceBit(Race raceId)
|
||||
{
|
||||
switch (raceId)
|
||||
{
|
||||
case Race.Human:
|
||||
case Race.Orc:
|
||||
case Race.Dwarf:
|
||||
case Race.NightElf:
|
||||
case Race.Undead:
|
||||
case Race.Tauren:
|
||||
case Race.Gnome:
|
||||
case Race.Troll:
|
||||
case Race.Goblin:
|
||||
case Race.BloodElf:
|
||||
case Race.Draenei:
|
||||
case Race.Worgen:
|
||||
case Race.PandarenNeutral:
|
||||
case Race.PandarenAlliance:
|
||||
case Race.PandarenHorde:
|
||||
case Race.Nightborne:
|
||||
case Race.HighmountainTauren:
|
||||
case Race.VoidElf:
|
||||
case Race.LightforgedDraenei:
|
||||
case Race.ZandalariTroll:
|
||||
case Race.KulTiran:
|
||||
return (int)raceId - 1;
|
||||
case Race.DarkIronDwarf:
|
||||
return 11;
|
||||
case Race.Vulpera:
|
||||
return 12;
|
||||
case Race.MagharOrc:
|
||||
return 13;
|
||||
case Race.MechaGnome:
|
||||
return 14;
|
||||
case Race.DracthyrAlliance:
|
||||
return 16;
|
||||
case Race.DracthyrHorde:
|
||||
return 15;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static long GetMaskForRace(Race raceId)
|
||||
{
|
||||
int raceBit = GetRaceBit(raceId);
|
||||
return raceBit >= 0 && raceBit < sizeof(long) * 8 ? (1L << raceBit) : 0;
|
||||
}
|
||||
|
||||
public static bool IsActivePetSlot(PetSaveMode slot)
|
||||
{
|
||||
return slot >= PetSaveMode.FirstActiveSlot && slot < PetSaveMode.LastActiveSlot;
|
||||
@@ -3054,12 +2993,13 @@ namespace Framework.Constants
|
||||
CrossFactionGroupJoined = 1114,
|
||||
CantTargetUnfriendlyInOverworld = 1115,
|
||||
EquipablespellsSlotsFull = 1116,
|
||||
WowLabsPartyErrorTypePartyIsFull = 1117,
|
||||
WowLabsPartyErrorTypeMaxInviteSent = 1118,
|
||||
WowLabsPartyErrorTypePlayerAlreadyInvited = 1119,
|
||||
WowLabsPartyErrorTypePartyInviteInvalid = 1120,
|
||||
WowLabsLobbyMatchmakerErrorEnterQueueFailed = 1121,
|
||||
WowLabsLobbyMatchmakerErrorLeaveQueueFailed = 1122,
|
||||
ItemModAppearanceGroupAlreadyKnown = 1117,
|
||||
WowLabsPartyErrorTypePartyIsFull = 1118,
|
||||
WowLabsPartyErrorTypeMaxInviteSent = 1119,
|
||||
WowLabsPartyErrorTypePlayerAlreadyInvited = 1120,
|
||||
WowLabsPartyErrorTypePartyInviteInvalid = 1121,
|
||||
WowLabsLobbyMatchmakerErrorEnterQueueFailed = 1122,
|
||||
WowLabsLobbyMatchmakerErrorLeaveQueueFailed = 1123,
|
||||
}
|
||||
|
||||
public enum SceneFlags
|
||||
|
||||
@@ -545,6 +545,10 @@ namespace Framework.Constants
|
||||
Unk535 = 535,
|
||||
IgnoreSpellCreatureTypeRequirements = 536,
|
||||
Unk537 = 537,
|
||||
ModFakeInebriationMovementOnly = 538,
|
||||
AllowMountInCombat = 539,
|
||||
ModSupportStat = 540, // NYI
|
||||
ModRequiredMountCapabilityFlags = 541,
|
||||
Total
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Framework.Constants
|
||||
|
||||
public const float TrajectoryMissileSize = 3.0f;
|
||||
|
||||
public const int MaxPowersPerSpell = 4;
|
||||
public const int MaxPowersPerSpell = 5;
|
||||
|
||||
public const uint VisualKitFood = 406;
|
||||
public const uint VisualKitDrink = 438;
|
||||
@@ -763,7 +763,9 @@ namespace Framework.Constants
|
||||
CantBeRecrafted = 316,
|
||||
PassiveReplaced = 317,
|
||||
CantFlyHere = 318,
|
||||
Unknown = 319,
|
||||
DragonridingRidingRequirement = 319,
|
||||
ItemModAppearanceGroupAlreadyKnown = 320,
|
||||
Unknown = 321,
|
||||
|
||||
// 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
|
||||
@@ -1397,8 +1399,11 @@ namespace Framework.Constants
|
||||
RequiresADjaradinPillarShard = 831, // Requires A Djaradin Pillar Shard.
|
||||
RequiresAResilientStone = 832, // Requires A Resilient Stone.
|
||||
MyrritCannotCarryAnyMoreMaps = 835, // Myrrit Cannot Carry Any More Maps. Go On A Dig With Him!
|
||||
SomeGiftsAreBetterLeftUndelivered = 836, // Some gifts are better left undelivered.
|
||||
RequiresNiffenCaveDiveKeyandShieldDisabled = 850, // Requires Niffen Cave Dive Key And Shield Disabled.
|
||||
ElusiveCreatureBaitWasRecentlyUsed = 851, // You Cannot Lure Anything In This Area For A Few Minutes. Elusive Creature Bait Was Recently Used.
|
||||
MustBeInQuietPlaceWithinCaerDarrow = 852, // Must be in a suitably quiet place within Caer Darrow.
|
||||
YouDontHaveAnyGlimmerOfLightsActive = 856, // You don't have any Glimmer of Lights active.
|
||||
YouDontHaveTheSwirlingMojoStone = 999, // You Don'T Have The Swirling Mojo Stone Equipped.
|
||||
YouMustBeNearADragonflightOathstone = 1000, // You Must Be Near One Of The Five Dragonflight Oathstones In The Dragon Isles.
|
||||
CanOnlyUseThisItemWhileAirborne = 1001, // You Can Only Use This Item While Airborne.
|
||||
@@ -2500,7 +2505,7 @@ namespace Framework.Constants
|
||||
CreateTraitTreeConfig = 303, // Miscvalue[0] = Traittreeid
|
||||
ChangeActiveCombatTraitConfig = 304,
|
||||
Unk305 = 305,
|
||||
Unk306 = 306,
|
||||
UpdateInteractions = 306,
|
||||
Unk307 = 307,
|
||||
CancelPreloadWorld = 308,
|
||||
PreloadWorld = 309,
|
||||
@@ -2509,6 +2514,7 @@ namespace Framework.Constants
|
||||
Unk312 = 312,
|
||||
ChangeItemBonuses2 = 313, // MiscValue[0] = ItemBonusTreeID to preserve
|
||||
AddSocketBonus = 314, // MiscValue[0] = required ItemBonusTreeID
|
||||
LearnTransmogAppearanceFromItemModAppearanceGroup = 315, // MiscValue[0] = ItemModAppearanceGroupID (not in db2)
|
||||
|
||||
TotalSpellEffects
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace Framework.Database
|
||||
" WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
|
||||
|
||||
// ChrCustomizationReq.db2
|
||||
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ, "SELECT ID, ReqSource, Flags, ClassMask, AchievementID, QuestID, OverrideArchive, " +
|
||||
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ, "SELECT ID, RaceMask, ReqSource, Flags, ClassMask, AchievementID, QuestID, OverrideArchive, " +
|
||||
"ItemModifiedAppearanceID FROM chr_customization_req WHERE (`VerifiedBuild` > 0) = ?");
|
||||
PrepareStatement(HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ_LOCALE, "SELECT ID, ReqSource_lang FROM chr_customization_req_locale WHERE (`VerifiedBuild` > 0) = ?" +
|
||||
" AND locale = ?");
|
||||
@@ -331,6 +331,10 @@ namespace Framework.Database
|
||||
PrepareStatement(HotfixStatements.SEL_CINEMATIC_SEQUENCES, "SELECT ID, SoundID, Camera1, Camera2, Camera3, Camera4, Camera5, Camera6, Camera7, Camera8" +
|
||||
" FROM cinematic_sequences WHERE (`VerifiedBuild` > 0) = ?");
|
||||
|
||||
// ConditionalChrModel.db2
|
||||
PrepareStatement(HotfixStatements.SEL_CONDITIONAL_CHR_MODEL, "SELECT ID, ChrModelID, ChrCustomizationReqID, PlayerConditionID, Flags, " +
|
||||
"ChrCustomizationCategoryID FROM conditional_chr_model WHERE (`VerifiedBuild` > 0) = ?");
|
||||
|
||||
// ConditionalContentTuning.db2
|
||||
PrepareStatement(HotfixStatements.SEL_CONDITIONAL_CONTENT_TUNING, "SELECT ID, OrderIndex, RedirectContentTuningID, RedirectFlag, ParentContentTuningID" +
|
||||
" FROM conditional_content_tuning WHERE (`VerifiedBuild` > 0) = ?");
|
||||
@@ -496,7 +500,8 @@ namespace Framework.Database
|
||||
|
||||
// GameobjectDisplayInfo.db2
|
||||
PrepareStatement(HotfixStatements.SEL_GAMEOBJECT_DISPLAY_INFO, "SELECT ID, GeoBoxMinX, GeoBoxMinY, GeoBoxMinZ, GeoBoxMaxX, GeoBoxMaxY, GeoBoxMaxZ, " +
|
||||
"FileDataID, ObjectEffectPackageID, OverrideLootEffectScale, OverrideNameScale FROM gameobject_display_info WHERE (`VerifiedBuild` > 0) = ?");
|
||||
"FileDataID, ObjectEffectPackageID, OverrideLootEffectScale, OverrideNameScale, AlternateDisplayType, ClientCreatureDisplayInfoID, " +
|
||||
"ClientItemID FROM gameobject_display_info WHERE (`VerifiedBuild` > 0) = ?");
|
||||
|
||||
// Gameobjects.db2
|
||||
PrepareStatement(HotfixStatements.SEL_GAMEOBJECTS, "SELECT Name, PosX, PosY, PosZ, Rot1, Rot2, Rot3, Rot4, ID, OwnerID, DisplayID, Scale, TypeID, " +
|
||||
@@ -1496,7 +1501,8 @@ namespace Framework.Database
|
||||
|
||||
// UiMap.db2
|
||||
PrepareStatement(HotfixStatements.SEL_UI_MAP, "SELECT Name, ID, ParentUiMapID, Flags, `System`, Type, BountySetID, BountyDisplayLocation, " +
|
||||
"VisibilityPlayerConditionID, HelpTextPosition, BkgAtlasID, AlternateUiMapGroup, ContentTuningID FROM ui_map WHERE (`VerifiedBuild` > 0) = ?");
|
||||
"VisibilityPlayerConditionID2, VisibilityPlayerConditionID, HelpTextPosition, BkgAtlasID, AlternateUiMapGroup, ContentTuningID FROM ui_map" +
|
||||
" WHERE (`VerifiedBuild` > 0) = ?");
|
||||
PrepareStatement(HotfixStatements.SEL_UI_MAP_LOCALE, "SELECT ID, Name_lang FROM ui_map_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
|
||||
|
||||
// UiMapAssignment.db2
|
||||
@@ -1725,6 +1731,8 @@ namespace Framework.Database
|
||||
|
||||
SEL_CINEMATIC_SEQUENCES,
|
||||
|
||||
SEL_CONDITIONAL_CHR_MODEL,
|
||||
|
||||
SEL_CONDITIONAL_CONTENT_TUNING,
|
||||
|
||||
SEL_CONTENT_TUNING,
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace Game.AI
|
||||
|
||||
if (spellInfo.IsPositive())
|
||||
{
|
||||
if (spellInfo.CanBeUsedInCombat())
|
||||
if (spellInfo.CanBeUsedInCombat(me))
|
||||
{
|
||||
// Check if we're in combat or commanded to attack
|
||||
if (!me.IsInCombat() && !me.GetCharmInfo().IsCommandAttack())
|
||||
@@ -160,7 +160,7 @@ namespace Game.AI
|
||||
if (!spellUsed)
|
||||
spell.Dispose();
|
||||
}
|
||||
else if (me.GetVictim() && CanAttack(me.GetVictim()) && spellInfo.CanBeUsedInCombat())
|
||||
else if (me.GetVictim() && CanAttack(me.GetVictim()) && spellInfo.CanBeUsedInCombat(me))
|
||||
{
|
||||
Spell spell = new(me, spellInfo, TriggerCastFlags.None);
|
||||
if (spell.CanAutoCast(me.GetVictim()))
|
||||
|
||||
@@ -9,6 +9,7 @@ using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Garrisons;
|
||||
using Game.Maps;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Scenarios;
|
||||
@@ -3609,6 +3610,14 @@ namespace Game.Achievements
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType.PlayerSummonedBattlePetSpecies: // 352
|
||||
if (referencePlayer.m_playerData.CurrentBattlePetSpeciesID != reqValue)
|
||||
return false;
|
||||
break;
|
||||
case ModifierTreeType.PlayerSummonedBattlePetIsMaxLevel: // 353
|
||||
if (referencePlayer.m_unitData.WildBattlePetLevel != SharedConst.MaxBattlePetLevel)
|
||||
return false;
|
||||
break;
|
||||
case ModifierTreeType.PlayerHasAtLeastProfPathRanks: // 355
|
||||
{
|
||||
uint ranks = 0;
|
||||
@@ -3629,6 +3638,50 @@ namespace Game.Achievements
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType.PlayerHasItemTransmogrifiedToItemModifiedAppearance: // 358
|
||||
{
|
||||
var itemModifiedAppearance = CliDB.ItemModifiedAppearanceStorage.LookupByKey(reqValue);
|
||||
|
||||
bool bagScanReachedEnd = referencePlayer.ForEachItem(ItemSearchLocation.Inventory, item =>
|
||||
{
|
||||
if (item.GetVisibleAppearanceModId(referencePlayer) == itemModifiedAppearance.Id)
|
||||
return false;
|
||||
|
||||
if (item.GetEntry() == itemModifiedAppearance.ItemID)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
if (bagScanReachedEnd)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType.PlayerHasCompletedDungeonEncounterInDifficulty: // 366
|
||||
if (!referencePlayer.IsLockedToDungeonEncounter(reqValue, (Difficulty)secondaryAsset))
|
||||
return false;
|
||||
break;
|
||||
case ModifierTreeType.PlayerIsBetweenQuests: // 369
|
||||
{
|
||||
QuestStatus status = referencePlayer.GetQuestStatus(reqValue);
|
||||
if (status == QuestStatus.None || status == QuestStatus.Failed)
|
||||
return false;
|
||||
if (referencePlayer.IsQuestRewarded((uint)secondaryAsset))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType.PlayerScenarioStepID: // 371
|
||||
{
|
||||
Scenario scenario = referencePlayer.GetScenario();
|
||||
if (scenario == null)
|
||||
return false;
|
||||
if (scenario.GetStep().Id != reqValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ModifierTreeType.PlayerZPositionBelow: // 374
|
||||
if (referencePlayer.GetPositionZ() >= reqValue)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -4274,7 +4327,7 @@ namespace Game.Achievements
|
||||
criteria.Id, criteria.Entry.Type, DataType, ClassRace.ClassId);
|
||||
return false;
|
||||
}
|
||||
if (ClassRace.RaceId != 0 && (SharedConst.GetMaskForRace((Race)ClassRace.RaceId) & (long)SharedConst.RaceMaskAllPlayable) == 0)
|
||||
if (!RaceMask.AllPlayable.HasRace((Race)ClassRace.RaceId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.",
|
||||
criteria.Id, criteria.Entry.Type, DataType, ClassRace.RaceId);
|
||||
@@ -4419,7 +4472,7 @@ namespace Game.Achievements
|
||||
criteria.Id, criteria.Entry.Type, DataType, ClassRace.ClassId);
|
||||
return false;
|
||||
}
|
||||
if (ClassRace.RaceId != 0 && ((ulong)SharedConst.GetMaskForRace((Race)ClassRace.RaceId) & SharedConst.RaceMaskAllPlayable) == 0)
|
||||
if (ClassRace.RaceId != 0 && !RaceMask.AllPlayable.HasRace((Race)ClassRace.RaceId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.",
|
||||
criteria.Id, criteria.Entry.Type, DataType, ClassRace.RaceId);
|
||||
|
||||
@@ -351,6 +351,8 @@ namespace Game.BattleGrounds
|
||||
SetStatus(BattlegroundStatus.InProgress);
|
||||
SetStartDelayTime(StartDelayTimes[BattlegroundConst.EventIdFourth]);
|
||||
|
||||
SendPacketToAll(new PVPMatchSetState(PVPMatchState.Engaged));
|
||||
|
||||
foreach (var (guid, _) in GetPlayers())
|
||||
{
|
||||
Player player = Global.ObjAccessor.FindPlayer(guid);
|
||||
@@ -954,14 +956,16 @@ namespace Game.BattleGrounds
|
||||
{
|
||||
case BattlegroundStatus.None:
|
||||
case BattlegroundStatus.WaitQueue:
|
||||
pvpMatchInitialize.State = PVPMatchInitialize.MatchState.Inactive;
|
||||
pvpMatchInitialize.State = PVPMatchState.Inactive;
|
||||
break;
|
||||
case BattlegroundStatus.WaitJoin:
|
||||
pvpMatchInitialize.State = PVPMatchState.StartUp;
|
||||
break;
|
||||
case BattlegroundStatus.InProgress:
|
||||
pvpMatchInitialize.State = PVPMatchInitialize.MatchState.InProgress;
|
||||
pvpMatchInitialize.State = PVPMatchState.Engaged;
|
||||
break;
|
||||
case BattlegroundStatus.WaitLeave:
|
||||
pvpMatchInitialize.State = PVPMatchInitialize.MatchState.Complete;
|
||||
pvpMatchInitialize.State = PVPMatchState.Complete;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1226,7 +1230,7 @@ namespace Game.BattleGrounds
|
||||
{
|
||||
playerData.IsInWorld = true;
|
||||
playerData.PrimaryTalentTree = (int)player.GetPrimarySpecialization();
|
||||
playerData.Sex = (int)player.GetGender();
|
||||
playerData.Sex = (sbyte)player.GetGender();
|
||||
playerData.PlayerRace = player.GetRace();
|
||||
playerData.PlayerClass = (int)player.GetClass();
|
||||
playerData.HonorLevel = (int)player.GetHonorLevel();
|
||||
|
||||
@@ -580,7 +580,7 @@ namespace Game.Chat
|
||||
foreach (ChrCustomizationOptionRecord option in options)
|
||||
{
|
||||
ChrCustomizationReqRecord optionReq = CliDB.ChrCustomizationReqStorage.LookupByKey(option.ChrCustomizationReqID);
|
||||
if (optionReq != null && !worldSession.MeetsChrCustomizationReq(optionReq, target.GetClass(), false, customizations))
|
||||
if (optionReq != null && !worldSession.MeetsChrCustomizationReq(optionReq, target.GetRace(), target.GetClass(), false, customizations))
|
||||
continue;
|
||||
|
||||
// Loop over the options until the first one fits
|
||||
@@ -588,7 +588,7 @@ namespace Game.Chat
|
||||
foreach (ChrCustomizationChoiceRecord choiceForOption in choicesForOption)
|
||||
{
|
||||
var choiceReq = CliDB.ChrCustomizationReqStorage.LookupByKey(choiceForOption.ChrCustomizationReqID);
|
||||
if (choiceReq != null && !worldSession.MeetsChrCustomizationReq(choiceReq, target.GetClass(), false, customizations))
|
||||
if (choiceReq != null && !worldSession.MeetsChrCustomizationReq(choiceReq, target.GetRace(), target.GetClass(), false, customizations))
|
||||
continue;
|
||||
|
||||
ChrCustomizationChoiceRecord choiceEntry = choicesForOption[0];
|
||||
|
||||
@@ -5,6 +5,7 @@ using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Scenarios;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -159,7 +160,7 @@ namespace Game.Conditions
|
||||
break;
|
||||
case ConditionTypes.Race:
|
||||
if (unit != null)
|
||||
condMeets = Convert.ToBoolean(SharedConst.GetMaskForRace(unit.GetRace()) & ConditionValue1);
|
||||
condMeets = new RaceMask<uint>(ConditionValue1).HasRace(unit.GetRace());
|
||||
break;
|
||||
case ConditionTypes.Gender:
|
||||
if (player != null)
|
||||
|
||||
@@ -10,6 +10,7 @@ using Game.Entities;
|
||||
using Game.Groups;
|
||||
using Game.Loots;
|
||||
using Game.Maps;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -1445,9 +1446,10 @@ namespace Game
|
||||
}
|
||||
case ConditionTypes.Race:
|
||||
{
|
||||
if (Convert.ToBoolean(cond.ConditionValue1 & ~SharedConst.RaceMaskAllPlayable))
|
||||
RaceMask<ulong> invalidRaceMask = new RaceMask<ulong>(cond.ConditionValue1 & ~RaceMask.AllPlayable.RawValue);
|
||||
if (!invalidRaceMask.IsEmpty()) // uint32 works thanks to weird index remapping in racemask
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "{0} has non existing racemask ({1}), skipped.", cond.ToString(true), cond.ConditionValue1 & ~SharedConst.RaceMaskAllPlayable);
|
||||
Log.outError(LogFilter.Sql, "{0} has non existing racemask ({1}), skipped.", cond.ToString(true), cond.ConditionValue1 & ~RaceMask.AllPlayable.RawValue);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -2022,7 +2024,8 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
if (condition.RaceMask != 0 && !Convert.ToBoolean(SharedConst.GetMaskForRace(player.GetRace()) & condition.RaceMask))
|
||||
var raceMask = new RaceMask<long>(condition.RaceMask);
|
||||
if (!raceMask.IsEmpty() && raceMask.HasRace(player.GetRace()))
|
||||
return false;
|
||||
|
||||
if (condition.ClassMask != 0 && !Convert.ToBoolean(player.GetClassMask() & condition.ClassMask))
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace Game.DataStorage
|
||||
ChrSpecializationStorage = ReadDB2<ChrSpecializationRecord>("ChrSpecialization.db2", HotfixStatements.SEL_CHR_SPECIALIZATION, HotfixStatements.SEL_CHR_SPECIALIZATION_LOCALE);
|
||||
CinematicCameraStorage = ReadDB2<CinematicCameraRecord>("CinematicCamera.db2", HotfixStatements.SEL_CINEMATIC_CAMERA);
|
||||
CinematicSequencesStorage = ReadDB2<CinematicSequencesRecord>("CinematicSequences.db2", HotfixStatements.SEL_CINEMATIC_SEQUENCES);
|
||||
ConditionalChrModelStorage = ReadDB2<ConditionalChrModelRecord>("ConditionalChrModel.db2", HotfixStatements.SEL_CONDITIONAL_CHR_MODEL);
|
||||
ConditionalContentTuningStorage = ReadDB2<ConditionalContentTuningRecord>("ConditionalContentTuning.db2", HotfixStatements.SEL_CONDITIONAL_CONTENT_TUNING);
|
||||
ContentTuningStorage = ReadDB2<ContentTuningRecord>("ContentTuning.db2", HotfixStatements.SEL_CONTENT_TUNING);
|
||||
ContentTuningXExpectedStorage = ReadDB2<ContentTuningXExpectedRecord>("ContentTuningXExpected.db2", HotfixStatements.SEL_CONTENT_TUNING_X_EXPECTED);
|
||||
@@ -539,6 +540,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<ChrSpecializationRecord> ChrSpecializationStorage;
|
||||
public static DB6Storage<CinematicCameraRecord> CinematicCameraStorage;
|
||||
public static DB6Storage<CinematicSequencesRecord> CinematicSequencesStorage;
|
||||
public static DB6Storage<ConditionalChrModelRecord> ConditionalChrModelStorage;
|
||||
public static DB6Storage<ConditionalContentTuningRecord> ConditionalContentTuningStorage;
|
||||
public static DB6Storage<ContentTuningRecord> ContentTuningStorage;
|
||||
public static DB6Storage<ContentTuningXExpectedRecord> ContentTuningXExpectedStorage;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Networking;
|
||||
using System;
|
||||
using System.Collections;
|
||||
@@ -1830,7 +1831,8 @@ namespace Game.DataStorage
|
||||
var bounds = _skillRaceClassInfoBySkill.LookupByKey(skill);
|
||||
foreach (var skllRaceClassInfo in bounds)
|
||||
{
|
||||
if (skllRaceClassInfo.RaceMask != 0 && !Convert.ToBoolean(skllRaceClassInfo.RaceMask & SharedConst.GetMaskForRace(race)))
|
||||
var raceMask = new RaceMask<long>(skllRaceClassInfo.RaceMask);
|
||||
if (!raceMask.IsEmpty() && !raceMask.HasRace(race))
|
||||
continue;
|
||||
if (skllRaceClassInfo.ClassMask != 0 && !Convert.ToBoolean(skllRaceClassInfo.ClassMask & (1 << ((byte)class_ - 1))))
|
||||
continue;
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Game.DataStorage
|
||||
public uint UwIntroSound;
|
||||
public byte FactionGroupMask;
|
||||
public float AmbientMultiplier;
|
||||
public byte MountFlags;
|
||||
public int MountFlags;
|
||||
public short PvpCombatWorldStateID;
|
||||
public byte WildBattlePetLevelMin;
|
||||
public byte WildBattlePetLevelMax;
|
||||
|
||||
@@ -183,6 +183,7 @@ namespace Game.DataStorage
|
||||
public sealed class ChrCustomizationReqRecord
|
||||
{
|
||||
public uint Id;
|
||||
public long RaceMask;
|
||||
public string ReqSource;
|
||||
public int Flags;
|
||||
public int ClassMask;
|
||||
@@ -329,6 +330,16 @@ namespace Game.DataStorage
|
||||
public ushort[] Camera = new ushort[8];
|
||||
}
|
||||
|
||||
public sealed class ConditionalChrModelRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ChrModelID; // This is the PK
|
||||
public int ChrCustomizationReqID;
|
||||
public int PlayerConditionID;
|
||||
public int Flags;
|
||||
public int ChrCustomizationCategoryID;
|
||||
}
|
||||
|
||||
public sealed class ConditionalContentTuningRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -512,12 +523,12 @@ namespace Game.DataStorage
|
||||
public CriteriaType Type;
|
||||
public uint Asset;
|
||||
public uint ModifierTreeId;
|
||||
public byte StartEvent;
|
||||
public int StartEvent;
|
||||
public uint StartAsset;
|
||||
public ushort StartTimer;
|
||||
public byte FailEvent;
|
||||
public int FailEvent;
|
||||
public uint FailAsset;
|
||||
public byte Flags;
|
||||
public int Flags;
|
||||
public ushort EligibilityWorldStateID;
|
||||
public byte EligibilityWorldStateValue;
|
||||
|
||||
@@ -530,7 +541,7 @@ namespace Game.DataStorage
|
||||
public string Description;
|
||||
public uint Parent;
|
||||
public uint Amount;
|
||||
public sbyte Operator;
|
||||
public int Operator;
|
||||
public uint CriteriaID;
|
||||
public int OrderIndex;
|
||||
public CriteriaTreeFlags Flags;
|
||||
|
||||
@@ -21,6 +21,9 @@ namespace Game.DataStorage
|
||||
public short ObjectEffectPackageID;
|
||||
public float OverrideLootEffectScale;
|
||||
public float OverrideNameScale;
|
||||
public int AlternateDisplayType;
|
||||
public int ClientCreatureDisplayInfoID;
|
||||
public int ClientItemID;
|
||||
|
||||
public Vector3 GeoBoxMin
|
||||
{
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace Game.DataStorage
|
||||
public UiMapType Type;
|
||||
public int BountySetID;
|
||||
public uint BountyDisplayLocation;
|
||||
public int VisibilityPlayerConditionID;
|
||||
public int VisibilityPlayerConditionID2; // if not met then map is skipped when evaluating UiMapAssignment
|
||||
public int VisibilityPlayerConditionID; // if not met then client checks other maps with the same AlternateUiMapGroup, not re-evaluating UiMapAssignment for them
|
||||
public sbyte HelpTextPosition;
|
||||
public int BkgAtlasID;
|
||||
public int AlternateUiMapGroup;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.AI;
|
||||
using Game.Maps;
|
||||
using Game.Movement;
|
||||
@@ -11,6 +10,7 @@ using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Game.Entities
|
||||
@@ -537,6 +537,9 @@ namespace Game.Entities
|
||||
_ai.OnUnitExit(leavingUnit);
|
||||
}
|
||||
}
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.NumUnitsInside), _insideUnits.Count);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.NumPlayersInside), _insideUnits.Count(guid => guid.IsPlayer()));
|
||||
}
|
||||
|
||||
public AreaTriggerTemplate GetTemplate()
|
||||
@@ -815,6 +818,8 @@ namespace Game.Entities
|
||||
m_areaTriggerData.ClearChanged(m_areaTriggerData.TimeToTarget);
|
||||
});
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OrbitPathTarget), orbit.PathTarget.GetValueOrDefault(ObjectGuid.Empty));
|
||||
|
||||
_orbitInfo = orbit;
|
||||
|
||||
_orbitInfo.TimeToTarget = timeToTarget;
|
||||
|
||||
@@ -1044,6 +1044,7 @@ namespace Game.Entities
|
||||
public struct duelflag
|
||||
{
|
||||
public uint InteractRadiusOverride; // 0 Interact Radius Override (in hundredths), int, Min value: 0, Max value: 2147483647, Default value: 0
|
||||
public uint Willthisduelgountilaplayerdies; // 1 Will this duel go until a player dies?, enum { false, true, }; Default: false
|
||||
}
|
||||
|
||||
public struct fishingnode
|
||||
|
||||
@@ -2038,6 +2038,22 @@ namespace Game.Entities
|
||||
return (ushort)GetAppearanceModId();
|
||||
}
|
||||
|
||||
uint GetVisibleModifiedAppearanceId(Player owner)
|
||||
{
|
||||
uint itemModifiedAppearanceId = GetModifier(ItemConst.AppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()]);
|
||||
if (itemModifiedAppearanceId == 0)
|
||||
itemModifiedAppearanceId = GetModifier(ItemModifier.TransmogAppearanceAllSpecs);
|
||||
|
||||
if (itemModifiedAppearanceId == 0)
|
||||
{
|
||||
var itemModifiedAppearance = GetItemModifiedAppearance();
|
||||
if (itemModifiedAppearance != null)
|
||||
itemModifiedAppearanceId = itemModifiedAppearance.Id;
|
||||
}
|
||||
|
||||
return itemModifiedAppearanceId;
|
||||
}
|
||||
|
||||
public uint GetVisibleSecondaryModifiedAppearanceId(Player owner)
|
||||
{
|
||||
uint itemModifiedAppearanceId = GetModifier(ItemConst.SecondaryAppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()]);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Framework.Constants;
|
||||
using Game.DataStorage;
|
||||
using Game.Miscellaneous;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@@ -274,7 +275,7 @@ namespace Game.Entities
|
||||
public uint GetSellPrice() { return ExtendedData.SellPrice; }
|
||||
public InventoryType GetInventoryType() { return ExtendedData.inventoryType; }
|
||||
public int GetAllowableClass() { return ExtendedData.AllowableClass; }
|
||||
public long GetAllowableRace() { return ExtendedData.AllowableRace; }
|
||||
public RaceMask<long> GetAllowableRace() { return new RaceMask<long>(ExtendedData.AllowableRace); }
|
||||
public uint GetBaseItemLevel() { return ExtendedData.ItemLevel; }
|
||||
public int GetBaseRequiredLevel() { return ExtendedData.RequiredLevel; }
|
||||
public uint GetRequiredSkill() { return ExtendedData.RequiredSkill; }
|
||||
|
||||
@@ -113,6 +113,7 @@ namespace Game.Entities
|
||||
case HighGuid.UniqUserClient:
|
||||
case HighGuid.ClientSession:
|
||||
case HighGuid.ClientConnection:
|
||||
case HighGuid.LMMParty:
|
||||
return ObjectGuidFactory.CreateClient(type, 0, arg1, counter);
|
||||
default:
|
||||
return Empty;
|
||||
@@ -151,10 +152,13 @@ namespace Game.Entities
|
||||
case HighGuid.AILock:
|
||||
case HighGuid.AILockTicket:
|
||||
return ObjectGuidFactory.CreateWorldObject(type, 0, 0, (ushort)mapId, 0, entry, counter);
|
||||
case HighGuid.ToolsClient:
|
||||
return ObjectGuidFactory.CreateToolsClient(mapId, entry, counter);
|
||||
default:
|
||||
return Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjectGuid Create(HighGuid type, SpellCastSource subType, uint mapId, uint entry, ulong counter)
|
||||
{
|
||||
switch (type)
|
||||
@@ -166,6 +170,22 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjectGuid Create(HighGuid type, uint arg1, ushort arg2, byte arg3, uint arg4)
|
||||
{
|
||||
if (type != HighGuid.WorldLayer)
|
||||
return Empty;
|
||||
|
||||
return ObjectGuidFactory.CreateWorldLayer(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
public static ObjectGuid Create(HighGuid type, uint arg2, byte arg3, byte arg4, ulong counter)
|
||||
{
|
||||
if (type != HighGuid.LMMLobby)
|
||||
return Empty;
|
||||
|
||||
return ObjectGuidFactory.CreateLMMLobby(0, arg2, arg3, arg4, counter);
|
||||
}
|
||||
|
||||
public byte[] GetRawValue()
|
||||
{
|
||||
byte[] temp = new byte[16];
|
||||
@@ -541,6 +561,16 @@ namespace Game.Entities
|
||||
return new ObjectGuid((ulong)(((ulong)HighGuid.WorldLayer << 58) | ((ulong)(arg1 & 0xFFFFFFFF) << 10) | (ulong)(arg2 & 0x1FFu)), (ulong)(((ulong)(arg3 & 0xFF) << 24) | (ulong)(arg4 & 0x7FFFFF)));
|
||||
}
|
||||
|
||||
public static ObjectGuid CreateLMMLobby(uint realmId, uint arg2, byte arg3, byte arg4, ulong counter)
|
||||
{
|
||||
return new ObjectGuid((ulong)(((ulong)HighGuid.LMMLobby << 58)
|
||||
| ((ulong)GetRealmIdForObjectGuid(realmId) << 42)
|
||||
| ((ulong)(arg2 & 0xFFFFFFFF) << 26)
|
||||
| ((ulong)(arg3 & 0xFF) << 18)
|
||||
| ((ulong)(arg4 & 0xFF) << 10)),
|
||||
counter);
|
||||
}
|
||||
|
||||
static uint GetRealmIdForObjectGuid(uint realmId)
|
||||
{
|
||||
if (realmId != 0)
|
||||
@@ -608,6 +638,11 @@ namespace Game.Entities
|
||||
SET_GUID_INFO(HighGuid.Cast, FormatWorldObject, ParseWorldObject);
|
||||
SET_GUID_INFO(HighGuid.ClientConnection, FormatClient, ParseClient);
|
||||
SET_GUID_INFO(HighGuid.ClubFinder, FormatClubFinder, ParseClubFinder);
|
||||
SET_GUID_INFO(HighGuid.ToolsClient, FormatToolsClient, ParseToolsClient);
|
||||
SET_GUID_INFO(HighGuid.WorldLayer, FormatWorldLayer, ParseWorldLayer);
|
||||
SET_GUID_INFO(HighGuid.ArenaTeam, FormatGuild, ParseGuild);
|
||||
SET_GUID_INFO(HighGuid.LMMParty, FormatClient, ParseClient);
|
||||
SET_GUID_INFO(HighGuid.LMMLobby, FormatLMMLobby, ParseLMMLobby);
|
||||
}
|
||||
|
||||
static void SET_GUID_INFO(HighGuid type, Func<HighGuid, ObjectGuid, string> format, Func<HighGuid, string, ObjectGuid> parse)
|
||||
@@ -993,12 +1028,12 @@ namespace Game.Entities
|
||||
return ObjectGuidFactory.CreateClubFinder(realmId, typeNum, clubFinderId, dbId);
|
||||
}
|
||||
|
||||
string FormatToolsClient(HighGuid typeName, ObjectGuid guid)
|
||||
static string FormatToolsClient(HighGuid typeName, ObjectGuid guid)
|
||||
{
|
||||
return $"{typeName}-{guid.GetMapId()}-{(uint)(guid.GetLowValue() >> 40) & 0xFFFFFF}-{guid.GetCounter():X10}";
|
||||
}
|
||||
|
||||
ObjectGuid ParseToolsClient(HighGuid type, string guidString)
|
||||
static ObjectGuid ParseToolsClient(HighGuid type, string guidString)
|
||||
{
|
||||
string[] split = guidString.Split('-');
|
||||
if (split.Length != 3)
|
||||
@@ -1010,12 +1045,12 @@ namespace Game.Entities
|
||||
return ObjectGuidFactory.CreateToolsClient(mapId, serverId, counter);
|
||||
}
|
||||
|
||||
string FormatWorldLayer(HighGuid typeName, ObjectGuid guid)
|
||||
static string FormatWorldLayer(HighGuid typeName, ObjectGuid guid)
|
||||
{
|
||||
return $"{typeName}-{(uint)((guid.GetHighValue() >> 10) & 0xFFFFFFFF)}-{(uint)(guid.GetHighValue() & 0x1FF)}-{(uint)((guid.GetLowValue() >> 24) & 0xFF)}-{(uint)(guid.GetLowValue() & 0x7FFFFF)}";
|
||||
}
|
||||
|
||||
ObjectGuid ParseWorldLayer(HighGuid type, string guidString)
|
||||
static ObjectGuid ParseWorldLayer(HighGuid type, string guidString)
|
||||
{
|
||||
string[] split = guidString.Split('-');
|
||||
if (split.Length != 4)
|
||||
@@ -1026,6 +1061,23 @@ namespace Game.Entities
|
||||
|
||||
return ObjectGuidFactory.CreateWorldLayer(arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
||||
static string FormatLMMLobby(HighGuid typeName, ObjectGuid guid)
|
||||
{
|
||||
return $"{typeName}-{guid.GetRealmId()}-{(uint)(guid.GetHighValue() >> 26) & 0xFFFFFF}-{(uint)(guid.GetHighValue() >> 18) & 0xFF}-{(uint)(guid.GetHighValue() >> 10) & 0xFF}-{guid.GetLowValue():X}";
|
||||
}
|
||||
|
||||
static ObjectGuid ParseLMMLobby(HighGuid type, string guidString)
|
||||
{
|
||||
string[] split = guidString.Split('-');
|
||||
if (split.Length != 5)
|
||||
return ObjectGuid.FromStringFailed;
|
||||
|
||||
if (!uint.TryParse(split[0], out uint realmId) || !uint.TryParse(split[1], out uint arg2) || !byte.TryParse(split[2], out byte arg3) || !byte.TryParse(split[0], out byte arg4) || !ulong.TryParse(split[0], out ulong arg5))
|
||||
return ObjectGuid.FromStringFailed;
|
||||
|
||||
return ObjectGuidFactory.CreateLMMLobby(realmId, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
}
|
||||
|
||||
public class Legacy
|
||||
|
||||
@@ -423,6 +423,12 @@ namespace Game.Entities
|
||||
return updateField;
|
||||
}
|
||||
|
||||
public OptionalUpdateField<U> ModifyValue<U>(OptionalUpdateField<U> updateField) where U : new()
|
||||
{
|
||||
MarkChanged(updateField);
|
||||
return updateField;
|
||||
}
|
||||
|
||||
public UpdateFieldString ModifyValue(UpdateFieldString updateField)
|
||||
{
|
||||
MarkChanged(updateField);
|
||||
@@ -464,6 +470,12 @@ namespace Game.Entities
|
||||
_changesMask.Set(updateField.Bit);
|
||||
}
|
||||
|
||||
public void MarkChanged<U>(OptionalUpdateField<U> updateField) where U : new()
|
||||
{
|
||||
_changesMask.Set(updateField.BlockBit);
|
||||
_changesMask.Set(updateField.Bit);
|
||||
}
|
||||
|
||||
public void MarkChanged(UpdateFieldString updateField)
|
||||
{
|
||||
_changesMask.Set(updateField.BlockBit);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -756,7 +756,7 @@ namespace Game.Entities
|
||||
|
||||
SetQuestSlot(slot, questId);
|
||||
SetQuestSlotEndTime(slot, endTime);
|
||||
SetQuestSlotAcceptTime(slot, acceptTime);
|
||||
questStatusData.AcceptTime = acceptTime;
|
||||
|
||||
if (questStatusData.Status == QuestStatus.Complete)
|
||||
SetQuestSlotState(slot, QuestSlotStateMask.Complete);
|
||||
@@ -1624,42 +1624,49 @@ namespace Game.Entities
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
// SELECT id, entry, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType, specialization FROM character_pet WHERE owner = ?
|
||||
if (!result.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
PetStable.PetInfo petInfo = new();
|
||||
petInfo.PetNumber = result.Read<uint>(0);
|
||||
petInfo.CreatureId = result.Read<uint>(1);
|
||||
petInfo.DisplayId = result.Read<uint>(2);
|
||||
petInfo.Level = result.Read<byte>(3);
|
||||
petInfo.Experience = result.Read<uint>(4);
|
||||
petInfo.ReactState = (ReactStates)result.Read<byte>(5);
|
||||
PetSaveMode slot = (PetSaveMode)result.Read<short>(6);
|
||||
petInfo.Name = result.Read<string>(7);
|
||||
petInfo.WasRenamed = result.Read<bool>(8);
|
||||
petInfo.Health = result.Read<uint>(9);
|
||||
petInfo.Mana = result.Read<uint>(10);
|
||||
petInfo.ActionBar = result.Read<string>(11);
|
||||
petInfo.LastSaveTime = result.Read<uint>(12);
|
||||
petInfo.CreatedBySpellId = result.Read<uint>(13);
|
||||
petInfo.Type = (PetType)result.Read<byte>(14);
|
||||
petInfo.SpecializationId = result.Read<ushort>(15);
|
||||
if (slot >= PetSaveMode.FirstActiveSlot && slot < PetSaveMode.LastActiveSlot)
|
||||
m_petStable.ActivePets[(int)slot] = petInfo;
|
||||
else if (slot >= PetSaveMode.FirstStableSlot && slot < PetSaveMode.LastStableSlot)
|
||||
m_petStable.StabledPets[slot - PetSaveMode.FirstStableSlot] = petInfo;
|
||||
else if (slot == PetSaveMode.NotInSlot)
|
||||
m_petStable.UnslottedPets.Add(petInfo);
|
||||
|
||||
} while (result.NextRow());
|
||||
}
|
||||
do
|
||||
{
|
||||
PetStable.PetInfo petInfo = new();
|
||||
petInfo.PetNumber = result.Read<uint>(0);
|
||||
petInfo.CreatureId = result.Read<uint>(1);
|
||||
petInfo.DisplayId = result.Read<uint>(2);
|
||||
petInfo.Level = result.Read<byte>(3);
|
||||
petInfo.Experience = result.Read<uint>(4);
|
||||
petInfo.ReactState = (ReactStates)result.Read<byte>(5);
|
||||
PetSaveMode slot = (PetSaveMode)result.Read<short>(6);
|
||||
petInfo.Name = result.Read<string>(7);
|
||||
petInfo.WasRenamed = result.Read<bool>(8);
|
||||
petInfo.Health = result.Read<uint>(9);
|
||||
petInfo.Mana = result.Read<uint>(10);
|
||||
petInfo.ActionBar = result.Read<string>(11);
|
||||
petInfo.LastSaveTime = result.Read<uint>(12);
|
||||
petInfo.CreatedBySpellId = result.Read<uint>(13);
|
||||
petInfo.Type = (PetType)result.Read<byte>(14);
|
||||
petInfo.SpecializationId = result.Read<ushort>(15);
|
||||
if (slot >= PetSaveMode.FirstActiveSlot && slot < PetSaveMode.LastActiveSlot)
|
||||
{
|
||||
m_petStable.ActivePets[(int)slot] = petInfo;
|
||||
|
||||
if (m_petStable.ActivePets[(int)slot].Type == PetType.Hunter)
|
||||
AddPetToUpdateFields(m_petStable.ActivePets[(int)slot], slot, PetStableFlags.Active);
|
||||
}
|
||||
else if (slot >= PetSaveMode.FirstStableSlot && slot < PetSaveMode.LastStableSlot)
|
||||
{
|
||||
m_petStable.StabledPets[slot - PetSaveMode.FirstStableSlot] = petInfo;
|
||||
|
||||
if (m_petStable.StabledPets[slot - PetSaveMode.FirstStableSlot].Type == PetType.Hunter)
|
||||
AddPetToUpdateFields(m_petStable.StabledPets[slot - PetSaveMode.FirstStableSlot], slot, PetStableFlags.Inactive);
|
||||
}
|
||||
else if (slot == PetSaveMode.NotInSlot)
|
||||
m_petStable.UnslottedPets.Add(petInfo);
|
||||
|
||||
} while (result.NextRow());
|
||||
|
||||
if (Pet.GetLoadPetInfo(m_petStable, 0, summonedPetNumber, null).Item1 != null)
|
||||
m_temporaryUnsummonedPetNumber = summonedPetNumber;
|
||||
}
|
||||
|
||||
|
||||
void _SaveInventory(SQLTransaction trans)
|
||||
{
|
||||
PreparedStatement stmt;
|
||||
@@ -2121,8 +2128,8 @@ namespace Game.Entities
|
||||
stmt.AddValue(1, save.Key);
|
||||
stmt.AddValue(2, (byte)data.Status);
|
||||
stmt.AddValue(3, data.Explored);
|
||||
stmt.AddValue(4, (long)GetQuestSlotAcceptTime(data.Slot));
|
||||
stmt.AddValue(5, (long)GetQuestSlotEndTime(data.Slot));
|
||||
stmt.AddValue(4, data.AcceptTime);
|
||||
stmt.AddValue(5, GetQuestSlotEndTime(data.Slot));
|
||||
trans.Append(stmt);
|
||||
|
||||
// Save objectives
|
||||
|
||||
@@ -1447,7 +1447,7 @@ namespace Game.Entities
|
||||
if (proto.HasFlag(ItemFlags2.FactionAlliance) && GetTeam() != Team.Alliance)
|
||||
return InventoryResult.CantEquipEver;
|
||||
|
||||
if ((proto.GetAllowableClass() & GetClassMask()) == 0 || (proto.GetAllowableRace() & (long)SharedConst.GetMaskForRace(GetRace())) == 0)
|
||||
if ((proto.GetAllowableClass() & GetClassMask()) == 0 || !proto.GetAllowableRace().HasRace(GetRace()))
|
||||
return InventoryResult.CantEquipEver;
|
||||
|
||||
if (proto.GetRequiredSkill() != 0)
|
||||
@@ -2967,7 +2967,7 @@ namespace Game.Entities
|
||||
return InventoryResult.ItemNotFound;
|
||||
|
||||
// Used by group, function GroupLoot, to know if a prototype can be used by a player
|
||||
if ((proto.GetAllowableClass() & GetClassMask()) == 0 || (proto.GetAllowableRace() & (long)SharedConst.GetMaskForRace(GetRace())) == 0)
|
||||
if ((proto.GetAllowableClass() & GetClassMask()) == 0 || !proto.GetAllowableRace().HasRace(GetRace()))
|
||||
return InventoryResult.CantEquipEver;
|
||||
|
||||
if (proto.GetRequiredSpell() != 0 && !HasSpell(proto.GetRequiredSpell()))
|
||||
@@ -3002,7 +3002,7 @@ namespace Game.Entities
|
||||
// if current back slot non-empty search oldest or free
|
||||
if (m_items[slot] != null)
|
||||
{
|
||||
ulong oldest_time = m_activePlayerData.BuybackTimestamp[0];
|
||||
long oldest_time = m_activePlayerData.BuybackTimestamp[0];
|
||||
uint oldest_slot = InventorySlots.BuyBackStart;
|
||||
|
||||
for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i)
|
||||
@@ -3014,7 +3014,7 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
|
||||
ulong i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
|
||||
long i_time = m_activePlayerData.BuybackTimestamp[i - InventorySlots.BuyBackStart];
|
||||
if (oldest_time > i_time)
|
||||
{
|
||||
oldest_time = i_time;
|
||||
@@ -3466,7 +3466,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, ulong timestamp) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackTimestamp, (int)slot), timestamp); }
|
||||
public void SetBuybackTimestamp(uint slot, long timestamp) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BuybackTimestamp, (int)slot), timestamp); }
|
||||
|
||||
public Item GetItemFromBuyBackSlot(uint slot)
|
||||
{
|
||||
|
||||
@@ -561,6 +561,19 @@ namespace Game.Entities
|
||||
return (instanceLock.GetData().CompletedEncountersMask & (1u << dungeonEncounter.Bit)) != 0;
|
||||
}
|
||||
|
||||
public bool IsLockedToDungeonEncounter(uint dungeonEncounterId, Difficulty difficulty)
|
||||
{
|
||||
var dungeonEncounter = CliDB.DungeonEncounterStorage.LookupByKey(dungeonEncounterId);
|
||||
if (dungeonEncounter == null)
|
||||
return false;
|
||||
|
||||
InstanceLock instanceLock = Global.InstanceLockMgr.FindActiveInstanceLock(GetGUID(), new MapDb2Entries((uint)dungeonEncounter.MapID, difficulty));
|
||||
if (instanceLock == null)
|
||||
return false;
|
||||
|
||||
return (instanceLock.GetData().CompletedEncountersMask & (1u << dungeonEncounter.Bit)) != 0;
|
||||
}
|
||||
|
||||
public override void ProcessTerrainStatusUpdate(ZLiquidStatus oldLiquidStatus, LiquidData newLiquidData)
|
||||
{
|
||||
// process liquid auras using generic unit code
|
||||
|
||||
@@ -798,7 +798,7 @@ namespace Game.Entities
|
||||
AdjustQuestObjectiveProgress(quest);
|
||||
|
||||
long endTime = 0;
|
||||
uint limittime = quest.LimitTime;
|
||||
uint limittime = (uint)quest.LimitTime;
|
||||
if (limittime != 0)
|
||||
{
|
||||
// shared timed quest
|
||||
@@ -833,7 +833,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
SetQuestSlotEndTime(logSlot, endTime);
|
||||
SetQuestSlotAcceptTime(logSlot, GameTime.GetGameTime());
|
||||
questStatusData.AcceptTime = GameTime.GetGameTime();
|
||||
|
||||
m_QuestStatusSave[questId] = QuestSaveType.Default;
|
||||
|
||||
@@ -1591,17 +1591,12 @@ namespace Game.Entities
|
||||
|
||||
public bool SatisfyQuestRace(Quest qInfo, bool msg)
|
||||
{
|
||||
long reqraces = qInfo.AllowableRaces;
|
||||
if (reqraces == -1)
|
||||
return true;
|
||||
|
||||
if ((reqraces & (long)SharedConst.GetMaskForRace(GetRace())) == 0)
|
||||
if (!qInfo.AllowableRaces.HasRace(GetRace()))
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
SendCanTakeQuestResponse(QuestFailedReasons.FailedWrongRace);
|
||||
Log.outDebug(LogFilter.Server, "SatisfyQuestRace: Sent QuestFailedReasons.FailedWrongRace (questId: {0}) because player does not have required race.", qInfo.Id);
|
||||
|
||||
Log.outDebug(LogFilter.Server, $"SatisfyQuestRace: Sent QuestFailedReasons.FailedWrongRace (questId: {qInfo.Id}) because player '{GetName()}' ({GetGUID()}) does not have required race.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2068,7 +2063,9 @@ namespace Game.Entities
|
||||
switch (GetQuestStatus(questId))
|
||||
{
|
||||
case QuestStatus.Complete:
|
||||
if (quest.GetQuestTag() == QuestTagType.CovenantCalling)
|
||||
if (quest.IsImportant())
|
||||
result |= quest.HasFlag(QuestFlags.HideRewardPoi) ? QuestGiverStatus.ImportantQuestRewardCompleteNoPOI : QuestGiverStatus.ImportantQuestRewardCompletePOI;
|
||||
else if (quest.GetQuestTag() == QuestTagType.CovenantCalling)
|
||||
result |= quest.HasFlag(QuestFlags.HideRewardPoi) ? QuestGiverStatus.CovenantCallingRewardCompleteNoPOI : QuestGiverStatus.CovenantCallingRewardCompletePOI;
|
||||
else if (quest.HasFlagEx(QuestFlagsEx.Legendary))
|
||||
result |= quest.HasFlag(QuestFlags.HideRewardPoi) ? QuestGiverStatus.LegendaryRewardCompleteNoPOI : QuestGiverStatus.LegendaryRewardCompletePOI;
|
||||
@@ -2076,8 +2073,12 @@ namespace Game.Entities
|
||||
result |= quest.HasFlag(QuestFlags.HideRewardPoi) ? QuestGiverStatus.RewardCompleteNoPOI : QuestGiverStatus.RewardCompletePOI;
|
||||
break;
|
||||
case QuestStatus.Incomplete:
|
||||
if (quest.GetQuestTag() == QuestTagType.CovenantCalling)
|
||||
if (quest.IsImportant())
|
||||
result |= QuestGiverStatus.ImportantQuestReward;
|
||||
else if (quest.GetQuestTag() == QuestTagType.CovenantCalling)
|
||||
result |= QuestGiverStatus.CovenantCallingReward;
|
||||
else if (quest.HasFlagEx(QuestFlagsEx.Legendary))
|
||||
result |= QuestGiverStatus.LegendaryReward;
|
||||
else
|
||||
result |= QuestGiverStatus.Reward;
|
||||
break;
|
||||
@@ -2109,22 +2110,20 @@ namespace Game.Entities
|
||||
{
|
||||
if (SatisfyQuestLevel(quest, false))
|
||||
{
|
||||
if (GetLevel() <= (GetQuestLevel(quest) + WorldConfig.GetIntValue(WorldCfg.QuestLowLevelHideDiff)))
|
||||
{
|
||||
if (quest.GetQuestTag() == QuestTagType.CovenantCalling)
|
||||
result |= QuestGiverStatus.CovenantCallingQuest;
|
||||
else if (quest.HasFlagEx(QuestFlagsEx.Legendary))
|
||||
result |= QuestGiverStatus.LegendaryQuest;
|
||||
else if (quest.IsDaily())
|
||||
result |= QuestGiverStatus.DailyQuest;
|
||||
else
|
||||
result |= QuestGiverStatus.Quest;
|
||||
}
|
||||
bool isTrivial = GetLevel() <= (GetQuestLevel(quest) + WorldConfig.GetIntValue(WorldCfg.QuestLowLevelHideDiff));
|
||||
if (quest.IsImportant())
|
||||
result |= isTrivial ? QuestGiverStatus.TrivialImportantQuest : QuestGiverStatus.ImportantQuest;
|
||||
else if (quest.GetQuestTag() == QuestTagType.CovenantCalling)
|
||||
result |= isTrivial ? QuestGiverStatus.TrivialCovenantCallingQuest : QuestGiverStatus.CovenantCallingQuest;
|
||||
else if (quest.HasFlagEx(QuestFlagsEx.Legendary))
|
||||
result |= isTrivial ? QuestGiverStatus.TrivialLegendaryQuest : QuestGiverStatus.LegendaryQuest;
|
||||
else if (quest.IsDaily())
|
||||
result |= QuestGiverStatus.TrivialDailyQuest;
|
||||
result |= isTrivial ? QuestGiverStatus.TrivialDailyQuest : QuestGiverStatus.DailyQuest;
|
||||
else
|
||||
result |= QuestGiverStatus.Trivial;
|
||||
result |= isTrivial ? QuestGiverStatus.Trivial : QuestGiverStatus.Quest;
|
||||
}
|
||||
else if (quest.HasFlagEx(QuestFlagsEx.Legendary))
|
||||
result |= QuestGiverStatus.FutureLegendaryQuest;
|
||||
else
|
||||
result |= QuestGiverStatus.Future;
|
||||
}
|
||||
@@ -2201,16 +2200,11 @@ namespace Game.Entities
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint GetQuestSlotEndTime(ushort slot)
|
||||
public long GetQuestSlotEndTime(ushort slot)
|
||||
{
|
||||
return m_playerData.QuestLog[slot].EndTime;
|
||||
}
|
||||
|
||||
public uint GetQuestSlotAcceptTime(ushort slot)
|
||||
{
|
||||
return m_playerData.QuestLog[slot].AcceptTime;
|
||||
}
|
||||
|
||||
bool GetQuestSlotObjectiveFlag(ushort slot, sbyte objectiveIndex)
|
||||
{
|
||||
if (objectiveIndex < SharedConst.MaxQuestCounts)
|
||||
@@ -2244,7 +2238,6 @@ namespace Game.Entities
|
||||
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.QuestID), quest_id);
|
||||
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.StateFlags), 0u);
|
||||
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.EndTime), 0u);
|
||||
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.AcceptTime), 0u);
|
||||
SetUpdateFieldValue(questLogField.ModifyValue(questLogField.ObjectiveFlags), 0u);
|
||||
|
||||
for (int i = 0; i < SharedConst.MaxQuestCounts; ++i)
|
||||
@@ -2279,12 +2272,6 @@ namespace Game.Entities
|
||||
SetUpdateFieldValue(questLog.ModifyValue(questLog.EndTime), (uint)endTime);
|
||||
}
|
||||
|
||||
public void SetQuestSlotAcceptTime(ushort slot, long acceptTime)
|
||||
{
|
||||
QuestLog questLog = m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.QuestLog, slot);
|
||||
SetUpdateFieldValue(questLog.ModifyValue(questLog.AcceptTime), (uint)acceptTime);
|
||||
}
|
||||
|
||||
void SetQuestSlotObjectiveFlag(ushort slot, sbyte objectiveIndex)
|
||||
{
|
||||
QuestLog questLog = m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.QuestLog, slot);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.DataStorage;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
@@ -1627,7 +1628,6 @@ namespace Game.Entities
|
||||
|
||||
public void LearnSkillRewardedSpells(uint skillId, uint skillValue, Race race)
|
||||
{
|
||||
long raceMask = SharedConst.GetMaskForRace(race);
|
||||
uint classMask = GetClassMask();
|
||||
|
||||
List<SkillLineAbilityRecord> skillLineAbilities = Global.DB2Mgr.GetSkillLineAbilitiesBySkill(skillId);
|
||||
@@ -1659,7 +1659,8 @@ namespace Game.Entities
|
||||
continue;
|
||||
|
||||
// Check race if set
|
||||
if (ability.RaceMask != 0 && !Convert.ToBoolean(ability.RaceMask & raceMask))
|
||||
var raceMask = new RaceMask<long>(ability.RaceMask);
|
||||
if (!raceMask.IsEmpty() && !raceMask.HasRace(race))
|
||||
continue;
|
||||
|
||||
// Check class if set
|
||||
|
||||
@@ -19,6 +19,7 @@ using Game.Loots;
|
||||
using Game.Mails;
|
||||
using Game.Maps;
|
||||
using Game.Misc;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
@@ -859,6 +860,194 @@ namespace Game.Entities
|
||||
return m_petStable;
|
||||
}
|
||||
|
||||
public void AddPetToUpdateFields(PetStable.PetInfo pet, PetSaveMode slot, PetStableFlags flags)
|
||||
{
|
||||
StableInfo ufStable = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.PetStable);
|
||||
StablePetInfo ufPet = new();
|
||||
ufPet.ModifyValue(ufPet.PetSlot).SetValue((uint)slot);
|
||||
ufPet.ModifyValue(ufPet.PetNumber).SetValue(pet.PetNumber);
|
||||
ufPet.ModifyValue(ufPet.CreatureID).SetValue(pet.CreatureId);
|
||||
ufPet.ModifyValue(ufPet.DisplayID).SetValue(pet.DisplayId);
|
||||
ufPet.ModifyValue(ufPet.ExperienceLevel).SetValue(pet.Level);
|
||||
ufPet.ModifyValue(ufPet.PetFlags).SetValue((byte)flags);
|
||||
ufPet.ModifyValue(ufPet.Name).SetValue(pet.Name);
|
||||
AddDynamicUpdateFieldValue(ufStable.ModifyValue(ufStable.Pets), ufPet);
|
||||
}
|
||||
|
||||
public void SetPetSlot(uint petNumber, PetSaveMode dstPetSlot)
|
||||
{
|
||||
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Interacting);
|
||||
|
||||
WorldSession sess = GetSession();
|
||||
PetStable petStable = GetPetStable();
|
||||
if (petStable == null)
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
var (srcPet, srcPetSlot) = Pet.GetLoadPetInfo(petStable, 0, petNumber, null);
|
||||
PetStable.PetInfo dstPet = Pet.GetLoadPetInfo(petStable, 0, 0, dstPetSlot).Item1;
|
||||
|
||||
if (srcPet == null || srcPet.Type != PetType.Hunter)
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dstPet != null && dstPet.Type != PetType.Hunter)
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
PetStable.PetInfo src = null;
|
||||
PetStable.PetInfo dst = null;
|
||||
uint? newActivePetIndex = null;
|
||||
|
||||
if (SharedConst.IsActivePetSlot(srcPetSlot) && SharedConst.IsActivePetSlot(dstPetSlot))
|
||||
{
|
||||
// active<.active: only swap ActivePets and CurrentPetIndex (do not despawn pets)
|
||||
src = petStable.ActivePets[srcPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
dst = petStable.ActivePets[dstPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
|
||||
if (petStable.GetCurrentActivePetIndex() == (uint)srcPetSlot)
|
||||
newActivePetIndex = (uint)dstPetSlot;
|
||||
else if (petStable.GetCurrentActivePetIndex() == (uint)dstPetSlot)
|
||||
newActivePetIndex = (uint)srcPetSlot;
|
||||
}
|
||||
else if (SharedConst.IsStabledPetSlot(srcPetSlot) && SharedConst.IsStabledPetSlot(dstPetSlot))
|
||||
{
|
||||
// stabled<.stabled: only swap StabledPets
|
||||
src = petStable.StabledPets[srcPetSlot - PetSaveMode.FirstStableSlot];
|
||||
dst = petStable.StabledPets[dstPetSlot - PetSaveMode.FirstStableSlot];
|
||||
}
|
||||
else if (SharedConst.IsActivePetSlot(srcPetSlot) && SharedConst.IsStabledPetSlot(dstPetSlot))
|
||||
{
|
||||
// active<.stabled: swap petStable contents and despawn active pet if it is involved in swap
|
||||
if (petStable.CurrentPetIndex == (uint)srcPetSlot)
|
||||
{
|
||||
Pet oldPet = GetPet();
|
||||
if (oldPet && !oldPet.IsAlive())
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
RemovePet(oldPet, PetSaveMode.NotInSlot);
|
||||
}
|
||||
|
||||
if (dstPet != null)
|
||||
{
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(dstPet.CreatureId);
|
||||
if (creatureInfo == null || !creatureInfo.IsTameable(CanTameExoticPets(), creatureInfo.GetDifficulty(Difficulty.None)))
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.CantControlExotic);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
src = petStable.ActivePets[srcPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
dst = petStable.StabledPets[dstPetSlot - PetSaveMode.FirstStableSlot];
|
||||
}
|
||||
else if (SharedConst.IsStabledPetSlot(srcPetSlot) && SharedConst.IsActivePetSlot(dstPetSlot))
|
||||
{
|
||||
// stabled<.active: swap petStable contents and despawn active pet if it is involved in swap
|
||||
if (petStable.CurrentPetIndex == (uint)dstPetSlot)
|
||||
{
|
||||
Pet oldPet = GetPet();
|
||||
if (oldPet != null && !oldPet.IsAlive())
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
RemovePet(oldPet, PetSaveMode.NotInSlot);
|
||||
}
|
||||
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(srcPet.CreatureId);
|
||||
if (creatureInfo == null || !creatureInfo.IsTameable(CanTameExoticPets(), creatureInfo.GetDifficulty(Difficulty.None)))
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.CantControlExotic);
|
||||
return;
|
||||
}
|
||||
|
||||
src = petStable.StabledPets[srcPetSlot - PetSaveMode.FirstStableSlot];
|
||||
dst = petStable.ActivePets[dstPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
}
|
||||
|
||||
SQLTransaction trans = new SQLTransaction();
|
||||
|
||||
PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt.AddValue(0, (short)dstPetSlot);
|
||||
stmt.AddValue(1, GetGUID().GetCounter());
|
||||
stmt.AddValue(2, srcPet.PetNumber);
|
||||
trans.Append(stmt);
|
||||
|
||||
if (dstPet != null)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt.AddValue(0, (short)srcPetSlot);
|
||||
stmt.AddValue(1, GetGUID().GetCounter());
|
||||
stmt.AddValue(2, dstPet.PetNumber);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
|
||||
GetSession().AddTransactionCallback(DB.Characters.AsyncCommitTransaction(trans)).AfterComplete(success =>
|
||||
{
|
||||
if (sess.GetPlayer() == this)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
Extensions.Swap(ref src, ref dst);
|
||||
if (newActivePetIndex.HasValue)
|
||||
sess.GetPlayer().GetPetStable().SetCurrentActivePetIndex(newActivePetIndex.Value);
|
||||
|
||||
int srcPetIndex = m_activePlayerData.PetStable.GetValue().Pets.FindIndexIf(p => p.PetSlot == (uint)srcPetSlot);
|
||||
int dstPetIndex = m_activePlayerData.PetStable.GetValue().Pets.FindIndexIf(p => p.PetSlot == (uint)dstPetSlot);
|
||||
|
||||
if (srcPetIndex >= 0)
|
||||
{
|
||||
StableInfo stableInfo = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.PetStable);
|
||||
StablePetInfo stablePetInfo = stableInfo.ModifyValue(stableInfo.Pets, srcPetIndex);
|
||||
SetUpdateFieldValue(stablePetInfo.ModifyValue(stablePetInfo.PetSlot), (uint)dstPetSlot);
|
||||
}
|
||||
|
||||
if (dstPetIndex >= 0)
|
||||
{
|
||||
StableInfo stableInfo = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.PetStable);
|
||||
StablePetInfo stablePetInfo = stableInfo.ModifyValue(stableInfo.Pets, dstPetIndex);
|
||||
SetUpdateFieldValue(stablePetInfo.ModifyValue(stablePetInfo.PetSlot), (uint)srcPetSlot);
|
||||
}
|
||||
|
||||
sess.SendPetStableResult(StableResult.StableSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
sess.SendPetStableResult(StableResult.InternalError);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ObjectGuid GetStableMaster()
|
||||
{
|
||||
if (!m_activePlayerData.PetStable.HasValue())
|
||||
return ObjectGuid.Empty;
|
||||
|
||||
return m_activePlayerData.PetStable.GetValue().StableMaster;
|
||||
}
|
||||
|
||||
public void SetStableMaster(ObjectGuid stableMaster)
|
||||
{
|
||||
if (!m_activePlayerData.PetStable.HasValue())
|
||||
return;
|
||||
|
||||
StableInfo stableInfo = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.PetStable);
|
||||
SetUpdateFieldValue(stableInfo.ModifyValue(stableInfo.StableMaster), stableMaster);
|
||||
}
|
||||
|
||||
// last used pet number (for BG's)
|
||||
public uint GetLastPetNumber() { return m_lastpetnumber; }
|
||||
public void SetLastPetNumber(uint petnumber) { m_lastpetnumber = petnumber; }
|
||||
@@ -2568,7 +2757,8 @@ namespace Game.Entities
|
||||
SendRespecWipeConfirm(guid, WorldConfig.GetBoolValue(WorldCfg.NoResetTalentCost) ? 0 : GetNextResetTalentsCost(), SpecResetType.Talents);
|
||||
break;
|
||||
case GossipOptionNpc.Stablemaster:
|
||||
GetSession().SendStablePet(guid);
|
||||
SetStableMaster(guid);
|
||||
handled = false;
|
||||
break;
|
||||
case GossipOptionNpc.PetSpecializationMaster:
|
||||
PlayerTalkClass.SendCloseGossip();
|
||||
@@ -3578,7 +3768,7 @@ namespace Game.Entities
|
||||
|
||||
public static bool IsValidGender(Gender _gender) { return _gender <= Gender.Female; }
|
||||
public static bool IsValidClass(Class _class) { return Convert.ToBoolean((1 << ((int)_class - 1)) & (int)Class.ClassMaskAllPlayable); }
|
||||
public static bool IsValidRace(Race _race) { return Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(_race) & SharedConst.RaceMaskAllPlayable); }
|
||||
public static bool IsValidRace(Race _race) { return RaceMask.AllPlayable.HasRace(_race); }
|
||||
|
||||
void LeaveLFGChannel()
|
||||
{
|
||||
@@ -4506,8 +4696,26 @@ namespace Game.Entities
|
||||
|
||||
PetStable.PetInfo currentPet = m_petStable.GetCurrentPet();
|
||||
Cypher.Assert(currentPet != null && currentPet.PetNumber == pet.GetCharmInfo().GetPetNumber());
|
||||
if (mode == PetSaveMode.NotInSlot || mode == PetSaveMode.AsDeleted)
|
||||
if (mode == PetSaveMode.NotInSlot)
|
||||
m_petStable.CurrentPetIndex = null;
|
||||
else if (mode == PetSaveMode.AsDeleted)
|
||||
{
|
||||
if (m_activePlayerData.PetStable.HasValue())
|
||||
{
|
||||
int ufIndex = m_activePlayerData.PetStable.GetValue().Pets.FindIndexIf(p => p.PetNumber == currentPet.PetNumber);
|
||||
if (ufIndex >= 0)
|
||||
{
|
||||
StableInfo stableInfo = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.PetStable);
|
||||
RemoveDynamicUpdateFieldValue(stableInfo.ModifyValue(stableInfo.Pets), ufIndex);
|
||||
}
|
||||
}
|
||||
|
||||
var petIndex = m_petStable.GetCurrentActivePetIndex();
|
||||
if (petIndex.HasValue)
|
||||
m_petStable.ActivePets[petIndex.Value] = null;
|
||||
|
||||
m_petStable.CurrentPetIndex = null;
|
||||
}
|
||||
// else if (stable slots) handled in opcode handlers due to required swaps
|
||||
// else (current pet) doesnt need to do anything
|
||||
|
||||
@@ -5083,7 +5291,7 @@ namespace Game.Entities
|
||||
if (pet)
|
||||
pet.SynchronizeLevelWithOwner();
|
||||
|
||||
MailLevelReward mailReward = ObjectMgr.GetMailLevelReward(level, (uint)SharedConst.GetMaskForRace(GetRace()));
|
||||
MailLevelReward mailReward = ObjectMgr.GetMailLevelReward(level, GetRace());
|
||||
if (mailReward != null)
|
||||
{
|
||||
//- TODO: Poor design of mail system
|
||||
@@ -7014,7 +7222,6 @@ namespace Game.Entities
|
||||
}
|
||||
public bool IsSpellFitByClassAndRace(uint spell_id)
|
||||
{
|
||||
long racemask = SharedConst.GetMaskForRace(GetRace());
|
||||
uint classmask = GetClassMask();
|
||||
|
||||
var bounds = SpellMgr.GetSkillLineAbilityMapBounds(spell_id);
|
||||
@@ -7025,7 +7232,8 @@ namespace Game.Entities
|
||||
foreach (var _spell_idx in bounds)
|
||||
{
|
||||
// skip wrong race skills
|
||||
if (_spell_idx.RaceMask != 0 && (_spell_idx.RaceMask & racemask) == 0)
|
||||
var raceMask = new RaceMask<long>(_spell_idx.RaceMask);
|
||||
if (!raceMask.IsEmpty() && !raceMask.HasRace(GetRace()))
|
||||
continue;
|
||||
|
||||
// skip wrong class skills
|
||||
@@ -7410,6 +7618,9 @@ namespace Game.Entities
|
||||
|
||||
public void SetTransportServerTime(int transportServerTime) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TransportServerTime), transportServerTime); }
|
||||
|
||||
public void SetRequiredMountCapabilityFlag(byte flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.RequiredMountCapabilityFlags), flag); }
|
||||
public void ReplaceAllRequiredMountCapabilityFlags(byte flags) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.RequiredMountCapabilityFlags), flags); }
|
||||
|
||||
public bool CanTameExoticPets() { return IsGameMaster() || HasAuraType(AuraType.AllowTamePetType); }
|
||||
|
||||
void SendAttackSwingCantAttack() { SendPacket(new AttackSwingError(AttackSwingErr.CantAttack)); }
|
||||
|
||||
@@ -769,9 +769,7 @@ namespace Game.Entities
|
||||
pet.SetCreatorGUID(GetGUID());
|
||||
pet.SetFaction(GetFaction());
|
||||
pet.SetCreatedBySpell(spell_id);
|
||||
|
||||
if (IsTypeId(TypeId.Player))
|
||||
pet.SetUnitFlag(UnitFlags.PlayerControlled);
|
||||
pet.SetUnitFlag(UnitFlags.PlayerControlled);
|
||||
|
||||
if (!pet.InitStatsForLevel(level))
|
||||
{
|
||||
@@ -790,6 +788,7 @@ namespace Game.Entities
|
||||
|
||||
PetStable.PetInfo petInfo = new();
|
||||
pet.FillPetInfo(petInfo);
|
||||
player.AddPetToUpdateFields(petInfo, (PetSaveMode)petStable.GetCurrentActivePetIndex(), PetStableFlags.Active);
|
||||
petStable.ActivePets[freeActiveSlot] = petInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1431,7 +1431,7 @@ namespace Game.Entities
|
||||
if (displayInfo != null)
|
||||
{
|
||||
ChrCustomizationReqRecord choiceReq = CliDB.ChrCustomizationReqStorage.LookupByKey(formModelData.Choices[i].ChrCustomizationReqID);
|
||||
if (choiceReq == null || thisPlayer.GetSession().MeetsChrCustomizationReq(choiceReq, GetClass(), false, thisPlayer.m_playerData.Customizations))
|
||||
if (choiceReq == null || thisPlayer.GetSession().MeetsChrCustomizationReq(choiceReq, GetRace(), GetClass(), false, thisPlayer.m_playerData.Customizations))
|
||||
displayIds.Add(displayInfo.DisplayID);
|
||||
}
|
||||
}
|
||||
@@ -1877,6 +1877,7 @@ namespace Game.Entities
|
||||
|
||||
public Race GetRace() { return (Race)(byte)m_unitData.Race; }
|
||||
public void SetRace(Race race) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Race), (byte)race); }
|
||||
public ulong GetRaceMask() { return 1UL << ((int)GetRace() - 1); }
|
||||
public Class GetClass() { return (Class)(byte)m_unitData.ClassId; }
|
||||
public void SetClass(Class classId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ClassId), (byte)classId); }
|
||||
public uint GetClassMask() { return (uint)(1 << ((int)GetClass() - 1)); }
|
||||
|
||||
@@ -12,6 +12,7 @@ using Game.Loots;
|
||||
using Game.Mails;
|
||||
using Game.Maps;
|
||||
using Game.Misc;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Movement;
|
||||
using Game.Scripting;
|
||||
using Game.Spells;
|
||||
@@ -6048,9 +6049,12 @@ namespace Game
|
||||
if (items.Empty())
|
||||
continue;
|
||||
|
||||
var raceMask = new RaceMask<long>(characterLoadout.RaceMask);
|
||||
|
||||
for (var raceIndex = Race.Human; raceIndex < Race.Max; ++raceIndex)
|
||||
{
|
||||
if (!characterLoadout.RaceMask.HasAnyFlag(SharedConst.GetMaskForRace(raceIndex)))
|
||||
|
||||
if (!raceMask.HasRace(raceIndex))
|
||||
continue;
|
||||
|
||||
var playerInfo = _playerInfo.LookupByKey(Tuple.Create((Race)raceIndex, (Class)characterLoadout.ChrClassID));
|
||||
@@ -6159,9 +6163,10 @@ namespace Game
|
||||
{
|
||||
if (rcInfo.Availability == 1)
|
||||
{
|
||||
var raceMask = new RaceMask<long>(rcInfo.RaceMask);
|
||||
for (Race raceIndex = Race.Human; raceIndex < Race.Max; ++raceIndex)
|
||||
{
|
||||
if (rcInfo.RaceMask == -1 || Convert.ToBoolean(SharedConst.GetMaskForRace(raceIndex) & rcInfo.RaceMask))
|
||||
if (raceMask.HasRace(raceIndex))
|
||||
{
|
||||
for (Class classIndex = Class.Warrior; classIndex < Class.Max; ++classIndex)
|
||||
{
|
||||
@@ -6194,11 +6199,11 @@ namespace Game
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
ulong raceMask = result.Read<ulong>(0);
|
||||
RaceMask<ulong> raceMask = new(result.Read<ulong>(0));
|
||||
uint classMask = result.Read<uint>(1);
|
||||
uint spellId = result.Read<uint>(2);
|
||||
|
||||
if (raceMask != 0 && !Convert.ToBoolean(raceMask & SharedConst.RaceMaskAllPlayable))
|
||||
if (!raceMask.IsEmpty() && (raceMask & RaceMask.AllPlayable).IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Wrong race mask {0} in `playercreateinfo_spell_custom` table, ignoring.", raceMask);
|
||||
continue;
|
||||
@@ -6212,7 +6217,7 @@ namespace Game
|
||||
|
||||
for (Race raceIndex = Race.Human; raceIndex < Race.Max; ++raceIndex)
|
||||
{
|
||||
if (raceMask == 0 || Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(raceIndex) & raceMask))
|
||||
if (raceMask.IsEmpty() || raceMask.HasRace(raceIndex))
|
||||
{
|
||||
for (Class classIndex = Class.Warrior; classIndex < Class.Max; ++classIndex)
|
||||
{
|
||||
@@ -6252,12 +6257,12 @@ namespace Game
|
||||
|
||||
do
|
||||
{
|
||||
ulong raceMask = result.Read<ulong>(0);
|
||||
RaceMask<ulong> raceMask = new(result.Read<ulong>(0));
|
||||
uint classMask = result.Read<uint>(1);
|
||||
uint spellId = result.Read<uint>(2);
|
||||
sbyte playerCreateMode = result.Read<sbyte>(3);
|
||||
|
||||
if (raceMask != 0 && (raceMask & SharedConst.RaceMaskAllPlayable) == 0)
|
||||
if (!raceMask.IsEmpty() && (raceMask & RaceMask.AllPlayable).IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Wrong race mask {raceMask} in `playercreateinfo_cast_spell` table, ignoring.");
|
||||
continue;
|
||||
@@ -6277,7 +6282,7 @@ namespace Game
|
||||
|
||||
for (Race raceIndex = Race.Human; raceIndex < Race.Max; ++raceIndex)
|
||||
{
|
||||
if (raceMask == 0 || Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(raceIndex) & raceMask))
|
||||
if (raceMask.IsEmpty() || raceMask.HasRace(raceIndex))
|
||||
{
|
||||
for (Class classIndex = Class.Warrior; classIndex < Class.Max; ++classIndex)
|
||||
{
|
||||
@@ -7387,12 +7392,12 @@ namespace Game
|
||||
}
|
||||
}
|
||||
// AllowableRaces, can be -1/RACEMASK_ALL_PLAYABLE to allow any race
|
||||
if (qinfo.AllowableRaces != -1)
|
||||
if (qinfo.AllowableRaces.RawValue != 0xFFFFFFFFFFFFFFFF)
|
||||
{
|
||||
if (qinfo.AllowableRaces > 0 && !Convert.ToBoolean(qinfo.AllowableRaces & (long)SharedConst.RaceMaskAllPlayable))
|
||||
if (!qinfo.AllowableRaces.IsEmpty() && (qinfo.AllowableRaces & RaceMask.AllPlayable).IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Quest {0} does not contain any playable races in `RequiredRaces` ({1}), value set to 0 (all races).", qinfo.Id, qinfo.AllowableRaces);
|
||||
qinfo.AllowableRaces = -1;
|
||||
qinfo.AllowableRaces = new(0xFFFFFFFFFFFFFFFF);
|
||||
}
|
||||
}
|
||||
// RequiredSkillId, can be 0
|
||||
@@ -9287,7 +9292,7 @@ namespace Game
|
||||
do
|
||||
{
|
||||
byte level = result.Read<byte>(0);
|
||||
ulong raceMask = result.Read<ulong>(1);
|
||||
RaceMask<ulong> raceMask = new(result.Read<ulong>(1));
|
||||
uint mailTemplateId = result.Read<uint>(2);
|
||||
uint senderEntry = result.Read<uint>(3);
|
||||
|
||||
@@ -9297,7 +9302,7 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Convert.ToBoolean(raceMask & SharedConst.RaceMaskAllPlayable))
|
||||
if ((raceMask & RaceMask.AllPlayable).IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `mail_level_reward` have raceMask ({0}) for level {1} that not include any player races, ignoring.", raceMask, level);
|
||||
continue;
|
||||
@@ -10221,14 +10226,14 @@ namespace Game
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} phase names in {Time.GetMSTimeDiffToNow(oldMSTime)} ms.");
|
||||
}
|
||||
|
||||
public MailLevelReward GetMailLevelReward(uint level, ulong raceMask)
|
||||
public MailLevelReward GetMailLevelReward(uint level, Race race)
|
||||
{
|
||||
var mailList = _mailLevelRewardStorage.LookupByKey((byte)level);
|
||||
if (mailList.Empty())
|
||||
return null;
|
||||
|
||||
foreach (var mailReward in mailList)
|
||||
if (Convert.ToBoolean(mailReward.raceMask & raceMask))
|
||||
if (mailReward.raceMask.HasRace(race))
|
||||
return mailReward;
|
||||
|
||||
return null;
|
||||
@@ -11531,14 +11536,14 @@ namespace Game
|
||||
|
||||
public class MailLevelReward
|
||||
{
|
||||
public MailLevelReward(ulong _raceMask = 0, uint _mailTemplateId = 0, uint _senderEntry = 0)
|
||||
public MailLevelReward(RaceMask<ulong> _raceMask, uint _mailTemplateId = 0, uint _senderEntry = 0)
|
||||
{
|
||||
raceMask = _raceMask;
|
||||
mailTemplateId = _mailTemplateId;
|
||||
senderEntry = _senderEntry;
|
||||
}
|
||||
|
||||
public ulong raceMask;
|
||||
public RaceMask<ulong> raceMask;
|
||||
public uint mailTemplateId;
|
||||
public uint senderEntry;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Framework.Database;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Guilds;
|
||||
using Game.Miscellaneous;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -436,7 +437,7 @@ namespace Game
|
||||
|
||||
reward.ItemID = result.Read<uint>(0);
|
||||
reward.MinGuildRep = result.Read<byte>(1);
|
||||
reward.RaceMask = result.Read<ulong>(2);
|
||||
reward.RaceMask = new RaceMask<ulong>(result.Read<ulong>(2));
|
||||
reward.Cost = result.Read<ulong>(3);
|
||||
|
||||
if (Global.ObjectMgr.GetItemTemplate(reward.ItemID) == null)
|
||||
@@ -497,7 +498,7 @@ namespace Game
|
||||
{
|
||||
public uint ItemID;
|
||||
public byte MinGuildRep;
|
||||
public ulong RaceMask;
|
||||
public RaceMask<ulong> RaceMask;
|
||||
public ulong Cost;
|
||||
public List<uint> AchievementsRequired = new();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Game.Entities;
|
||||
using Game.Groups;
|
||||
using Game.Guilds;
|
||||
using Game.Maps;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
@@ -85,7 +86,7 @@ namespace Game
|
||||
|
||||
charInfo.Customizations.Clear();
|
||||
|
||||
if (charInfo.Flags2 != CharacterCustomizeFlags.Customize)
|
||||
if (!charInfo.Flags2.HasAnyFlag(CharacterCustomizeFlags.Customize | CharacterCustomizeFlags.Faction | CharacterCustomizeFlags.Race))
|
||||
{
|
||||
PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.UPD_ADD_AT_LOGIN_FLAG);
|
||||
stmt.AddValue(0, (ushort)AtLoginFlags.Customize);
|
||||
@@ -165,7 +166,7 @@ namespace Game
|
||||
SendPacket(charEnum);
|
||||
}
|
||||
|
||||
public bool MeetsChrCustomizationReq(ChrCustomizationReqRecord req, Class playerClass, bool checkRequiredDependentChoices, List<ChrCustomizationChoice> selectedChoices)
|
||||
public bool MeetsChrCustomizationReq(ChrCustomizationReqRecord req, Race race, Class playerClass, bool checkRequiredDependentChoices, List<ChrCustomizationChoice> selectedChoices)
|
||||
{
|
||||
if (!req.GetFlags().HasFlag(ChrCustomizationReqFlag.HasRequirements))
|
||||
return true;
|
||||
@@ -173,6 +174,10 @@ namespace Game
|
||||
if (req.ClassMask != 0 && (req.ClassMask & (1 << ((int)playerClass - 1))) == 0)
|
||||
return false;
|
||||
|
||||
var raceMask = new RaceMask<long>(req.RaceMask);
|
||||
if (race != Race.None && !raceMask.IsEmpty() && raceMask.RawValue != -1 && !raceMask.HasRace(race))
|
||||
return false;
|
||||
|
||||
if (req.AchievementID != 0 /*&& !HasAchieved(req->AchievementID)*/)
|
||||
return false;
|
||||
|
||||
@@ -240,7 +245,7 @@ namespace Game
|
||||
|
||||
ChrCustomizationReqRecord req = CliDB.ChrCustomizationReqStorage.LookupByKey(customizationOptionData.ChrCustomizationReqID);
|
||||
if (req != null)
|
||||
if (!MeetsChrCustomizationReq(req, playerClass, false, customizations))
|
||||
if (!MeetsChrCustomizationReq(req, race, playerClass, false, customizations))
|
||||
return false;
|
||||
|
||||
var choicesForOption = Global.DB2Mgr.GetCustomiztionChoices(playerChoice.ChrCustomizationOptionID);
|
||||
@@ -255,7 +260,7 @@ namespace Game
|
||||
|
||||
ChrCustomizationReqRecord reqEntry = CliDB.ChrCustomizationReqStorage.LookupByKey(customizationChoiceData.ChrCustomizationReqID);
|
||||
if (reqEntry != null)
|
||||
if (!MeetsChrCustomizationReq(reqEntry, playerClass, true, customizations))
|
||||
if (!MeetsChrCustomizationReq(reqEntry, race, playerClass, true, customizations))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -374,8 +379,8 @@ namespace Game
|
||||
return;
|
||||
}
|
||||
|
||||
ulong raceMaskDisabled = WorldConfig.GetUInt64Value(WorldCfg.CharacterCreatingDisabledRacemask);
|
||||
if (Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(charCreate.CreateInfo.RaceId) & raceMaskDisabled))
|
||||
RaceMask<ulong> raceMaskDisabled = new(WorldConfig.GetUInt64Value(WorldCfg.CharacterCreatingDisabledRacemask));
|
||||
if (raceMaskDisabled.HasRace(charCreate.CreateInfo.RaceId))
|
||||
{
|
||||
SendCharCreate(ResponseCodes.CharCreateDisabled);
|
||||
return;
|
||||
@@ -839,10 +844,6 @@ namespace Game
|
||||
pCurrChar.SetGuildLevel(0);
|
||||
}
|
||||
|
||||
// Send stable contents to display icons on Call Pet spells
|
||||
if (pCurrChar.HasSpell(SharedConst.CallPetSpellId))
|
||||
SendStablePet(ObjectGuid.Empty);
|
||||
|
||||
pCurrChar.GetSession().GetBattlePetMgr().SendJournalLockStatus();
|
||||
|
||||
pCurrChar.SendInitialPacketsBeforeAddToMap();
|
||||
@@ -1382,6 +1383,23 @@ namespace Game
|
||||
[WorldPacketHandler(ClientOpcodes.AlterAppearance)]
|
||||
void HandleAlterAppearance(AlterApperance packet)
|
||||
{
|
||||
if (packet.CustomizedChrModelID != 0)
|
||||
{
|
||||
var conditionalChrModel = CliDB.ConditionalChrModelStorage.LookupByKey(packet.CustomizedChrModelID);
|
||||
if (conditionalChrModel == null)
|
||||
return;
|
||||
|
||||
var req = CliDB.ChrCustomizationReqStorage.LookupByKey(conditionalChrModel.ChrCustomizationReqID);
|
||||
if (req != null)
|
||||
if (!MeetsChrCustomizationReq(req, (Race)packet.CustomizedRace, _player.GetClass(), false, packet.Customizations))
|
||||
return;
|
||||
|
||||
var condition = CliDB.PlayerConditionStorage.LookupByKey(conditionalChrModel.PlayerConditionID);
|
||||
if (condition != null)
|
||||
if (!ConditionManager.IsPlayerMeetingCondition(_player, condition))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ValidateAppearance(_player.GetRace(), _player.GetClass(), (Gender)packet.NewSex, packet.Customizations))
|
||||
return;
|
||||
|
||||
@@ -1766,8 +1784,8 @@ namespace Game
|
||||
|
||||
if (!HasPermission(RBACPermissions.SkipCheckCharacterCreationRacemask))
|
||||
{
|
||||
ulong raceMaskDisabled = WorldConfig.GetUInt64Value(WorldCfg.CharacterCreatingDisabledRacemask);
|
||||
if (Convert.ToBoolean((ulong)SharedConst.GetMaskForRace(factionChangeInfo.RaceID) & raceMaskDisabled))
|
||||
RaceMask<ulong> raceMaskDisabled = new(WorldConfig.GetUInt64Value(WorldCfg.CharacterCreatingDisabledRacemask));
|
||||
if (raceMaskDisabled.HasRace(factionChangeInfo.RaceID))
|
||||
{
|
||||
SendCharFactionChange(ResponseCodes.CharCreateError, factionChangeInfo);
|
||||
return;
|
||||
@@ -2078,8 +2096,8 @@ namespace Game
|
||||
var questTemplates = Global.ObjectMgr.GetQuestTemplates();
|
||||
foreach (Quest quest in questTemplates.Values)
|
||||
{
|
||||
long newRaceMask = (long)(newTeamId == TeamId.Alliance ? SharedConst.RaceMaskAlliance : SharedConst.RaceMaskHorde);
|
||||
if (quest.AllowableRaces != -1 && !Convert.ToBoolean(quest.AllowableRaces & newRaceMask))
|
||||
RaceMask<ulong> newRaceMask = newTeamId == TeamId.Alliance ? RaceMask.Alliance : RaceMask.Horde;
|
||||
if (quest.AllowableRaces.RawValue != unchecked((ulong)-1) && (quest.AllowableRaces & newRaceMask).IsEmpty())
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST);
|
||||
stmt.AddValue(0, lowGuid);
|
||||
|
||||
@@ -614,7 +614,7 @@ namespace Game
|
||||
{
|
||||
GuildRewardItem rewardItem = new();
|
||||
rewardItem.ItemID = rewards[i].ItemID;
|
||||
rewardItem.RaceMask = (uint)rewards[i].RaceMask;
|
||||
rewardItem.RaceMask = rewards[i].RaceMask;
|
||||
rewardItem.MinGuildLevel = 0;
|
||||
rewardItem.MinGuildRep = rewards[i].MinGuildRep;
|
||||
rewardItem.AchievementsRequired = rewards[i].AchievementsRequired;
|
||||
|
||||
@@ -465,6 +465,9 @@ namespace Game
|
||||
{
|
||||
if (_player.PlayerTalkClass.GetInteractionData().SourceGuid == closeInteraction.SourceGuid)
|
||||
_player.PlayerTalkClass.GetInteractionData().Reset();
|
||||
|
||||
if (_player.GetStableMaster() == closeInteraction.SourceGuid)
|
||||
_player.SetStableMaster(ObjectGuid.Empty);
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.ConversationLineStarted)]
|
||||
|
||||
@@ -324,61 +324,10 @@ namespace Game
|
||||
if (GetPlayer().IsMounted())
|
||||
GetPlayer().RemoveAurasByType(AuraType.Mounted);
|
||||
|
||||
SendStablePet(packet.StableMaster);
|
||||
_player.SetStableMaster(packet.StableMaster);
|
||||
}
|
||||
|
||||
public void SendStablePet(ObjectGuid guid)
|
||||
{
|
||||
PetStableList packet = new();
|
||||
packet.StableMaster = guid;
|
||||
|
||||
PetStable petStable = GetPlayer().GetPetStable();
|
||||
if (petStable == null)
|
||||
{
|
||||
SendPacket(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint petSlot = 0; petSlot < petStable.ActivePets.Length; ++petSlot)
|
||||
{
|
||||
if (petStable.ActivePets[petSlot] == null)
|
||||
continue;
|
||||
|
||||
PetStable.PetInfo pet = petStable.ActivePets[petSlot];
|
||||
PetStableInfo stableEntry;
|
||||
stableEntry.PetSlot = petSlot + (int)PetSaveMode.FirstActiveSlot;
|
||||
stableEntry.PetNumber = pet.PetNumber;
|
||||
stableEntry.CreatureID = pet.CreatureId;
|
||||
stableEntry.DisplayID = pet.DisplayId;
|
||||
stableEntry.ExperienceLevel = pet.Level;
|
||||
stableEntry.PetFlags = PetStableinfo.Active;
|
||||
stableEntry.PetName = pet.Name;
|
||||
|
||||
packet.Pets.Add(stableEntry);
|
||||
}
|
||||
|
||||
for (uint petSlot = 0; petSlot < petStable.StabledPets.Length; ++petSlot)
|
||||
{
|
||||
if (petStable.StabledPets[petSlot] == null)
|
||||
continue;
|
||||
|
||||
PetStable.PetInfo pet = petStable.StabledPets[petSlot];
|
||||
PetStableInfo stableEntry;
|
||||
stableEntry.PetSlot = petSlot + (int)PetSaveMode.FirstStableSlot;
|
||||
stableEntry.PetNumber = pet.PetNumber;
|
||||
stableEntry.CreatureID = pet.CreatureId;
|
||||
stableEntry.DisplayID = pet.DisplayId;
|
||||
stableEntry.ExperienceLevel = pet.Level;
|
||||
stableEntry.PetFlags = PetStableinfo.Inactive;
|
||||
stableEntry.PetName = pet.Name;
|
||||
|
||||
packet.Pets.Add(stableEntry);
|
||||
}
|
||||
|
||||
SendPacket(packet);
|
||||
}
|
||||
|
||||
void SendPetStableResult(StableResult result)
|
||||
public void SendPetStableResult(StableResult result)
|
||||
{
|
||||
PetStableResult petStableResult = new();
|
||||
petStableResult.Result = result;
|
||||
@@ -394,141 +343,7 @@ namespace Game
|
||||
return;
|
||||
}
|
||||
|
||||
GetPlayer().RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Interacting);
|
||||
|
||||
PetStable petStable = GetPlayer().GetPetStable();
|
||||
if (petStable == null)
|
||||
{
|
||||
SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
(PetStable.PetInfo srcPet, PetSaveMode srcPetSlot) = Pet.GetLoadPetInfo(petStable, 0, setPetSlot.PetNumber, null);
|
||||
PetSaveMode dstPetSlot = (PetSaveMode)setPetSlot.DestSlot;
|
||||
PetStable.PetInfo dstPet = Pet.GetLoadPetInfo(petStable, 0, 0, dstPetSlot).Item1;
|
||||
|
||||
if (srcPet == null || srcPet.Type != PetType.Hunter)
|
||||
{
|
||||
SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dstPet != null && dstPet.Type != PetType.Hunter)
|
||||
{
|
||||
SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
PetStable.PetInfo src = null;
|
||||
PetStable.PetInfo dst = null;
|
||||
PetSaveMode? newActivePetIndex = null;
|
||||
|
||||
if (SharedConst.IsActivePetSlot(srcPetSlot) && SharedConst.IsActivePetSlot(dstPetSlot))
|
||||
{
|
||||
// active<.active: only swap ActivePets and CurrentPetIndex (do not despawn pets)
|
||||
src = petStable.ActivePets[srcPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
dst = petStable.ActivePets[dstPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
|
||||
if (petStable.GetCurrentActivePetIndex().Value == (uint)srcPetSlot)
|
||||
newActivePetIndex = dstPetSlot;
|
||||
else if (petStable.GetCurrentActivePetIndex().Value == (uint)dstPetSlot)
|
||||
newActivePetIndex = srcPetSlot;
|
||||
}
|
||||
else if (SharedConst.IsStabledPetSlot(srcPetSlot) && SharedConst.IsStabledPetSlot(dstPetSlot))
|
||||
{
|
||||
// stabled<.stabled: only swap StabledPets
|
||||
src = petStable.StabledPets[srcPetSlot - PetSaveMode.FirstStableSlot];
|
||||
dst = petStable.StabledPets[dstPetSlot - PetSaveMode.FirstStableSlot];
|
||||
}
|
||||
else if (SharedConst.IsActivePetSlot(srcPetSlot) && SharedConst.IsStabledPetSlot(dstPetSlot))
|
||||
{
|
||||
// active<.stabled: swap petStable contents and despawn active pet if it is involved in swap
|
||||
if (petStable.CurrentPetIndex.Value == (uint)srcPetSlot)
|
||||
{
|
||||
Pet oldPet = _player.GetPet();
|
||||
if (oldPet != null && !oldPet.IsAlive())
|
||||
{
|
||||
SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
_player.RemovePet(oldPet, PetSaveMode.NotInSlot);
|
||||
}
|
||||
|
||||
if (dstPet != null)
|
||||
{
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(dstPet.CreatureId);
|
||||
if (creatureInfo == null || !creatureInfo.IsTameable(_player.CanTameExoticPets(), creatureInfo.GetDifficulty(Difficulty.None)))
|
||||
{
|
||||
SendPetStableResult(StableResult.CantControlExotic);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
src = petStable.ActivePets[srcPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
dst = petStable.StabledPets[dstPetSlot - PetSaveMode.FirstStableSlot];
|
||||
}
|
||||
else if (SharedConst.IsStabledPetSlot(srcPetSlot) && SharedConst.IsActivePetSlot(dstPetSlot))
|
||||
{
|
||||
// stabled<.active: swap petStable contents and despawn active pet if it is involved in swap
|
||||
if (petStable.CurrentPetIndex.Value == (uint)dstPetSlot)
|
||||
{
|
||||
Pet oldPet = _player.GetPet();
|
||||
if (oldPet != null && !oldPet.IsAlive())
|
||||
{
|
||||
SendPetStableResult(StableResult.InternalError);
|
||||
return;
|
||||
}
|
||||
|
||||
_player.RemovePet(oldPet, PetSaveMode.NotInSlot);
|
||||
}
|
||||
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(srcPet.CreatureId);
|
||||
if (creatureInfo == null || !creatureInfo.IsTameable(_player.CanTameExoticPets(), creatureInfo.GetDifficulty(Difficulty.None)))
|
||||
{
|
||||
SendPetStableResult(StableResult.CantControlExotic);
|
||||
return;
|
||||
}
|
||||
|
||||
src = petStable.StabledPets[srcPetSlot - PetSaveMode.FirstStableSlot];
|
||||
dst = petStable.ActivePets[dstPetSlot - PetSaveMode.FirstActiveSlot];
|
||||
}
|
||||
|
||||
SQLTransaction trans = new();
|
||||
|
||||
PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt.AddValue(0, (short)dstPetSlot);
|
||||
stmt.AddValue(1, _player.GetGUID().GetCounter());
|
||||
stmt.AddValue(2, srcPet.PetNumber);
|
||||
trans.Append(stmt);
|
||||
|
||||
if (dstPet != null)
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt.AddValue(0, (short)srcPetSlot);
|
||||
stmt.AddValue(1, _player.GetGUID().GetCounter());
|
||||
stmt.AddValue(2, dstPet.PetNumber);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
AddTransactionCallback(DB.Characters.AsyncCommitTransaction(trans)).AfterComplete(success =>
|
||||
{
|
||||
var currentPlayerGuid = _player.GetGUID();
|
||||
if (_player && _player.GetGUID() == currentPlayerGuid)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
Extensions.Swap(ref src, ref dst);
|
||||
if (newActivePetIndex.HasValue)
|
||||
GetPlayer().GetPetStable().SetCurrentActivePetIndex((uint)newActivePetIndex.Value);
|
||||
SendPetStableResult(StableResult.StableSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendPetStableResult(StableResult.InternalError);
|
||||
}
|
||||
}
|
||||
});
|
||||
_player.SetPetSlot(setPetSlot.PetNumber, (PetSaveMode)setPetSlot.DestSlot);
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.RepairItem, Processing = PacketProcessing.Inplace)]
|
||||
|
||||
@@ -582,9 +582,6 @@ namespace Game
|
||||
[WorldPacketHandler(ClientOpcodes.PetAbandon)]
|
||||
void HandlePetAbandon(PetAbandon packet)
|
||||
{
|
||||
if (!GetPlayer().IsInWorld)
|
||||
return;
|
||||
|
||||
// pet/charmed
|
||||
Creature pet = ObjectAccessor.GetCreatureOrPetOrVehicle(GetPlayer(), packet.Pet);
|
||||
if (pet && pet.ToPet() && pet.ToPet().GetPetType() == PetType.Hunter)
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Game
|
||||
continue;
|
||||
|
||||
// check if race matches racemask
|
||||
if (!Convert.ToBoolean(request.RaceFilter & (1 << target.Race)))
|
||||
if (!request.RaceFilter.HasRace((Race)target.Race))
|
||||
continue;
|
||||
|
||||
if (!whoRequest.Areas.Empty())
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Game
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo((uint)effect.SpellID, user.GetMap().GetDifficultyID());
|
||||
if (spellInfo != null)
|
||||
{
|
||||
if (!spellInfo.CanBeUsedInCombat())
|
||||
if (!spellInfo.CanBeUsedInCombat(user))
|
||||
{
|
||||
user.SendEquipError(InventoryResult.NotInCombat, item);
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
|
||||
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Framework.Constants;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Game.Miscellaneous
|
||||
{
|
||||
public struct RaceMask
|
||||
{
|
||||
public static RaceMask<ulong> AllPlayable = new RaceMask<ulong>(
|
||||
RaceMask<ulong>.GetMaskForRace(Race.Human) | RaceMask<ulong>.GetMaskForRace(Race.Orc) | RaceMask<ulong>.GetMaskForRace(Race.Dwarf) | RaceMask<ulong>.GetMaskForRace(Race.NightElf) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.Undead) | RaceMask<ulong>.GetMaskForRace(Race.Tauren) | RaceMask<ulong>.GetMaskForRace(Race.Gnome) | RaceMask<ulong>.GetMaskForRace(Race.Troll) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.BloodElf) | RaceMask<ulong>.GetMaskForRace(Race.Draenei) | RaceMask<ulong>.GetMaskForRace(Race.Goblin) | RaceMask<ulong>.GetMaskForRace(Race.Worgen) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.PandarenNeutral) | RaceMask<ulong>.GetMaskForRace(Race.PandarenAlliance) | RaceMask<ulong>.GetMaskForRace(Race.PandarenHorde) | RaceMask<ulong>.GetMaskForRace(Race.Nightborne) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.HighmountainTauren) | RaceMask<ulong>.GetMaskForRace(Race.VoidElf) | RaceMask<ulong>.GetMaskForRace(Race.LightforgedDraenei) | RaceMask<ulong>.GetMaskForRace(Race.ZandalariTroll) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.KulTiran) | RaceMask<ulong>.GetMaskForRace(Race.DarkIronDwarf) | RaceMask<ulong>.GetMaskForRace(Race.Vulpera) | RaceMask<ulong>.GetMaskForRace(Race.MagharOrc) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.MechaGnome) | RaceMask<ulong>.GetMaskForRace(Race.DracthyrAlliance) | RaceMask<ulong>.GetMaskForRace(Race.DracthyrHorde));
|
||||
|
||||
public static RaceMask<ulong> Neutral = new(RaceMask<ulong>.GetMaskForRace(Race.PandarenNeutral));
|
||||
|
||||
public static RaceMask<ulong> Alliance = new(
|
||||
RaceMask<ulong>.GetMaskForRace(Race.Human) | RaceMask<ulong>.GetMaskForRace(Race.Dwarf) | RaceMask<ulong>.GetMaskForRace(Race.NightElf) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.Gnome) | RaceMask<ulong>.GetMaskForRace(Race.Draenei) | RaceMask<ulong>.GetMaskForRace(Race.Worgen) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.PandarenAlliance) | RaceMask<ulong>.GetMaskForRace(Race.VoidElf) | RaceMask<ulong>.GetMaskForRace(Race.LightforgedDraenei) |
|
||||
RaceMask<ulong>.GetMaskForRace(Race.KulTiran) | RaceMask<ulong>.GetMaskForRace(Race.DarkIronDwarf) | RaceMask<ulong>.GetMaskForRace(Race.MechaGnome) | RaceMask<ulong>.GetMaskForRace(Race.DracthyrAlliance));
|
||||
|
||||
public static RaceMask<ulong> Horde = new(AllPlayable.RawValue & ~(Neutral | Alliance).RawValue);
|
||||
}
|
||||
|
||||
public struct RaceMask<T> where T : unmanaged
|
||||
{
|
||||
public T RawValue;
|
||||
|
||||
public RaceMask(T rawValue)
|
||||
{
|
||||
RawValue = rawValue;
|
||||
}
|
||||
|
||||
public bool HasRace(Race raceId)
|
||||
{
|
||||
return ((dynamic)RawValue & GetMaskForRace(raceId)) != 0;
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return RawValue == (dynamic)0;
|
||||
}
|
||||
|
||||
public static RaceMask<T> operator &(RaceMask<T> left, RaceMask<T> right) { return new RaceMask<T>((dynamic)left.RawValue & right.RawValue); }
|
||||
public static RaceMask<T> operator |(RaceMask<T> left, RaceMask<T> right) { return new RaceMask<T>((dynamic)left.RawValue | right.RawValue); }
|
||||
|
||||
public static explicit operator T(RaceMask<T> raceMask)
|
||||
{
|
||||
return raceMask.RawValue;
|
||||
}
|
||||
|
||||
public static dynamic GetMaskForRace(Race raceId)
|
||||
{
|
||||
int raceBit = GetRaceBit(raceId);
|
||||
return (raceBit >= 0 && (uint)raceBit < Marshal.SizeOf<T>() * 8 ? (1 << raceBit) : 0);
|
||||
}
|
||||
|
||||
static int GetRaceBit(Race raceId)
|
||||
{
|
||||
switch (raceId)
|
||||
{
|
||||
case Race.Human:
|
||||
case Race.Orc:
|
||||
case Race.Dwarf:
|
||||
case Race.NightElf:
|
||||
case Race.Undead:
|
||||
case Race.Tauren:
|
||||
case Race.Gnome:
|
||||
case Race.Troll:
|
||||
case Race.Goblin:
|
||||
case Race.BloodElf:
|
||||
case Race.Draenei:
|
||||
case Race.Worgen:
|
||||
case Race.PandarenNeutral:
|
||||
case Race.PandarenAlliance:
|
||||
case Race.PandarenHorde:
|
||||
case Race.Nightborne:
|
||||
case Race.HighmountainTauren:
|
||||
case Race.VoidElf:
|
||||
case Race.LightforgedDraenei:
|
||||
case Race.ZandalariTroll:
|
||||
case Race.KulTiran:
|
||||
return (int)raceId - 1;
|
||||
case Race.DarkIronDwarf:
|
||||
return 11;
|
||||
case Race.Vulpera:
|
||||
return 12;
|
||||
case Race.MagharOrc:
|
||||
return 13;
|
||||
case Race.MechaGnome:
|
||||
return 14;
|
||||
case Race.DracthyrAlliance:
|
||||
return 16;
|
||||
case Race.DracthyrHorde:
|
||||
return 15;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteUInt32(CriteriaID);
|
||||
_worldPacket.WriteUInt64(Quantity);
|
||||
_worldPacket.WritePackedGuid(PlayerGUID);
|
||||
_worldPacket.WriteUInt32(Unused_10_1_5);
|
||||
_worldPacket.WriteUInt32(Flags);
|
||||
_worldPacket.WritePackedTime(CurrentTime);
|
||||
_worldPacket.WriteInt64(ElapsedTime);
|
||||
@@ -72,6 +73,7 @@ namespace Game.Networking.Packets
|
||||
public uint CriteriaID;
|
||||
public ulong Quantity;
|
||||
public ObjectGuid PlayerGUID;
|
||||
public uint Unused_10_1_5;
|
||||
public uint Flags;
|
||||
public long CurrentTime;
|
||||
public long ElapsedTime;
|
||||
@@ -178,6 +180,7 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteUInt32(0); // this is a hack. this is a packed time written as int64 (progress.DateUpdated)
|
||||
_worldPacket.WriteUInt64(progress.Quantity);
|
||||
_worldPacket.WritePackedGuid(progress.PlayerGUID);
|
||||
_worldPacket.WriteInt32(progress.Unused_10_1_5);
|
||||
_worldPacket.WriteInt32(progress.Flags);
|
||||
}
|
||||
}
|
||||
@@ -318,10 +321,11 @@ namespace Game.Networking.Packets
|
||||
data.WriteUInt32(Id);
|
||||
data.WriteUInt64(Quantity);
|
||||
data.WritePackedGuid(Player);
|
||||
data.WriteUInt32(Unused_10_1_5);
|
||||
data.WriteUInt32(Flags);
|
||||
data.WritePackedTime(Date);
|
||||
data.WriteInt64(TimeFromStart);
|
||||
data.WriteInt64(TimeFromCreate);
|
||||
data.WriteBits(Flags, 4);
|
||||
data.WriteBit(RafAcceptanceID.HasValue);
|
||||
data.FlushBits();
|
||||
|
||||
@@ -332,6 +336,7 @@ namespace Game.Networking.Packets
|
||||
public uint Id;
|
||||
public ulong Quantity;
|
||||
public ObjectGuid Player;
|
||||
public uint Unused_10_1_5;
|
||||
public uint Flags;
|
||||
public long Date;
|
||||
public long TimeFromStart;
|
||||
@@ -347,6 +352,7 @@ namespace Game.Networking.Packets
|
||||
public long DateUpdated;
|
||||
public ulong Quantity;
|
||||
public ObjectGuid PlayerGUID;
|
||||
public int Unused_10_1_5;
|
||||
public int Flags;
|
||||
}
|
||||
|
||||
|
||||
@@ -517,7 +517,8 @@ namespace Game.Networking.Packets
|
||||
class AuctionHelloResponse : ServerPacket
|
||||
{
|
||||
public ObjectGuid Guid;
|
||||
public uint DeliveryDelay;
|
||||
public uint PurchasedItemDeliveryDelay;
|
||||
public uint CancelledItemDeliveryDelay;
|
||||
public bool OpenForBusiness = true;
|
||||
|
||||
public AuctionHelloResponse() : base(ServerOpcodes.AuctionHelloResponse) { }
|
||||
@@ -525,7 +526,8 @@ namespace Game.Networking.Packets
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WritePackedGuid(Guid);
|
||||
_worldPacket.WriteUInt32(DeliveryDelay);
|
||||
_worldPacket.WriteUInt32(PurchasedItemDeliveryDelay);
|
||||
_worldPacket.WriteUInt32(CancelledItemDeliveryDelay);
|
||||
_worldPacket.WriteBit(OpenForBusiness);
|
||||
_worldPacket.FlushBits();
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteBit(SuccessInfo.NumPlayersHorde.HasValue);
|
||||
_worldPacket.WriteBit(SuccessInfo.NumPlayersAlliance.HasValue);
|
||||
_worldPacket.WriteBit(SuccessInfo.ExpansionTrialExpiration.HasValue);
|
||||
_worldPacket.WriteBit(SuccessInfo.NewBuildKeys != null);
|
||||
_worldPacket.FlushBits();
|
||||
|
||||
{
|
||||
@@ -155,6 +156,15 @@ namespace Game.Networking.Packets
|
||||
if(SuccessInfo.ExpansionTrialExpiration.HasValue)
|
||||
_worldPacket.WriteInt64(SuccessInfo.ExpansionTrialExpiration.Value);
|
||||
|
||||
if (SuccessInfo.NewBuildKeys != null)
|
||||
{
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
_worldPacket.WriteUInt8(SuccessInfo.NewBuildKeys.NewBuildKey[i]);
|
||||
_worldPacket.WriteUInt8(SuccessInfo.NewBuildKeys.SomeKey[i]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (VirtualRealmInfo virtualRealm in SuccessInfo.VirtualRealms)
|
||||
virtualRealm.Write(_worldPacket);
|
||||
|
||||
@@ -208,6 +218,7 @@ namespace Game.Networking.Packets
|
||||
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 long? ExpansionTrialExpiration; // expansion trial expiration unix timestamp
|
||||
public NewBuild NewBuildKeys;
|
||||
|
||||
public struct GameTime
|
||||
{
|
||||
@@ -216,6 +227,12 @@ namespace Game.Networking.Packets
|
||||
public uint Unknown735;
|
||||
public bool InGameRoom;
|
||||
}
|
||||
|
||||
public class NewBuild
|
||||
{
|
||||
public Array<byte> NewBuildKey = new Array<byte>(16);
|
||||
public Array<byte> SomeKey = new Array<byte>(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -485,15 +485,8 @@ namespace Game.Networking.Packets
|
||||
DeserterPenalty.Write(_worldPacket);
|
||||
}
|
||||
|
||||
public enum MatchState
|
||||
{
|
||||
InProgress = 1,
|
||||
Complete = 3,
|
||||
Inactive = 4
|
||||
}
|
||||
|
||||
public uint MapID;
|
||||
public MatchState State = MatchState.Inactive;
|
||||
public PVPMatchState State = PVPMatchState.Inactive;
|
||||
public long StartTime;
|
||||
public int Duration;
|
||||
public RatedMatchDeserterPenalty DeserterPenalty;
|
||||
@@ -503,6 +496,21 @@ namespace Game.Networking.Packets
|
||||
public bool AffectsRating;
|
||||
}
|
||||
|
||||
class PVPMatchSetState : ServerPacket
|
||||
{
|
||||
public PVPMatchSetState(PVPMatchState state) : base(ServerOpcodes.PvpMatchSetState)
|
||||
{
|
||||
State = state;
|
||||
}
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WriteUInt8((byte)State);
|
||||
}
|
||||
|
||||
PVPMatchState State;
|
||||
}
|
||||
|
||||
class PVPMatchComplete : ServerPacket
|
||||
{
|
||||
public PVPMatchComplete() : base(ServerOpcodes.PvpMatchComplete, ConnectionType.Instance) { }
|
||||
@@ -685,7 +693,7 @@ namespace Game.Networking.Packets
|
||||
data.WriteUInt32(HealingDone);
|
||||
data.WriteInt32(Stats.Count);
|
||||
data.WriteInt32(PrimaryTalentTree);
|
||||
data.WriteInt32(Sex);
|
||||
data.WriteInt8(Sex);
|
||||
data.WriteUInt32((uint)PlayerRace);
|
||||
data.WriteInt32(PlayerClass);
|
||||
data.WriteInt32(CreatureID);
|
||||
@@ -738,7 +746,7 @@ namespace Game.Networking.Packets
|
||||
public uint? PostMatchMMR;
|
||||
public List<PVPMatchPlayerPVPStat> Stats = new();
|
||||
public int PrimaryTalentTree;
|
||||
public int Sex;
|
||||
public sbyte Sex;
|
||||
public Race PlayerRace;
|
||||
public int PlayerClass;
|
||||
public int CreatureID;
|
||||
|
||||
@@ -868,6 +868,7 @@ namespace Game.Networking.Packets
|
||||
var customizationCount = _worldPacket.ReadUInt32();
|
||||
NewSex = _worldPacket.ReadUInt8();
|
||||
CustomizedRace = _worldPacket.ReadInt32();
|
||||
CustomizedChrModelID = _worldPacket.ReadInt32();
|
||||
|
||||
for (var i = 0; i < customizationCount; ++i)
|
||||
{
|
||||
@@ -884,6 +885,7 @@ namespace Game.Networking.Packets
|
||||
public byte NewSex;
|
||||
public Array<ChrCustomizationChoice> Customizations = new(125);
|
||||
public int CustomizedRace;
|
||||
public int CustomizedChrModelID;
|
||||
}
|
||||
|
||||
public class BarberShopResult : ServerPacket
|
||||
|
||||
@@ -62,6 +62,11 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteInt32(Absorbed);
|
||||
_worldPacket.WriteInt32(Resisted);
|
||||
_worldPacket.WriteInt32(ShieldBlock);
|
||||
_worldPacket.WriteInt32(WorldTextViewers.Count);
|
||||
_worldPacket.WriteInt32(Supporters.Count);
|
||||
|
||||
foreach (SpellSupportInfo supportInfo in Supporters)
|
||||
supportInfo.Write(_worldPacket);
|
||||
|
||||
_worldPacket.WriteBit(Periodic);
|
||||
_worldPacket.WriteBits(Flags, 7);
|
||||
@@ -69,6 +74,10 @@ namespace Game.Networking.Packets
|
||||
WriteLogDataBit();
|
||||
_worldPacket.WriteBit(ContentTuning != null);
|
||||
FlushBits();
|
||||
|
||||
foreach (CombatWorldTextViewerInfo worldTextViewer in WorldTextViewers)
|
||||
worldTextViewer.Write(_worldPacket);
|
||||
|
||||
WriteLogData();
|
||||
if (ContentTuning != null)
|
||||
ContentTuning.Write(_worldPacket);
|
||||
@@ -90,6 +99,8 @@ namespace Game.Networking.Packets
|
||||
public int Flags;
|
||||
// Optional<SpellNonMeleeDamageLogDebugInfo> DebugInfo;
|
||||
public ContentTuningParams ContentTuning;
|
||||
public List<CombatWorldTextViewerInfo> WorldTextViewers = new();
|
||||
public List<SpellSupportInfo> Supporters = new();
|
||||
}
|
||||
|
||||
class EnvironmentalDamageLog : CombatLogServerPacket
|
||||
@@ -193,6 +204,10 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteInt32(OriginalHeal);
|
||||
_worldPacket.WriteUInt32(OverHeal);
|
||||
_worldPacket.WriteUInt32(Absorbed);
|
||||
_worldPacket.WriteInt32(Supporters.Count);
|
||||
|
||||
foreach (SpellSupportInfo supportInfo in Supporters)
|
||||
supportInfo.Write(_worldPacket);
|
||||
|
||||
_worldPacket.WriteBit(Crit);
|
||||
|
||||
@@ -225,6 +240,7 @@ namespace Game.Networking.Packets
|
||||
public float? CritRollMade;
|
||||
public float? CritRollNeeded;
|
||||
public ContentTuningParams ContentTuning;
|
||||
public List<SpellSupportInfo> Supporters = new();
|
||||
}
|
||||
|
||||
class SpellPeriodicAuraLog : CombatLogServerPacket
|
||||
@@ -267,6 +283,10 @@ namespace Game.Networking.Packets
|
||||
data.WriteUInt32(SchoolMaskOrPower);
|
||||
data.WriteUInt32(AbsorbedOrAmplitude);
|
||||
data.WriteUInt32(Resisted);
|
||||
data.WriteInt32(Supporters.Count);
|
||||
|
||||
foreach (SpellSupportInfo supportInfo in Supporters)
|
||||
supportInfo.Write(data);
|
||||
|
||||
data.WriteBit(Crit);
|
||||
data.WriteBit(DebugInfo.HasValue);
|
||||
@@ -293,6 +313,7 @@ namespace Game.Networking.Packets
|
||||
public bool Crit;
|
||||
public PeriodicalAuraLogEffectDebugInfo? DebugInfo;
|
||||
public ContentTuningParams ContentTuning;
|
||||
public List<SpellSupportInfo> Supporters = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,6 +615,10 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WritePackedGuid(Caster);
|
||||
_worldPacket.WriteInt32(Absorbed);
|
||||
_worldPacket.WriteUInt32(OriginalDamage);
|
||||
_worldPacket.WriteInt32(Supporters.Count);
|
||||
|
||||
foreach (SpellSupportInfo supportInfo in Supporters)
|
||||
supportInfo.Write(_worldPacket);
|
||||
|
||||
_worldPacket.WriteBit(Unk);
|
||||
WriteLogDataBit();
|
||||
@@ -610,6 +635,7 @@ namespace Game.Networking.Packets
|
||||
public int Absorbed;
|
||||
public uint OriginalDamage;
|
||||
public bool Unk;
|
||||
public List<SpellSupportInfo> Supporters = new();
|
||||
}
|
||||
|
||||
class SpellHealAbsorbLog : ServerPacket
|
||||
|
||||
@@ -14,9 +14,11 @@ namespace Game.Networking.Packets
|
||||
public override void Read()
|
||||
{
|
||||
TargetGUID = _worldPacket.ReadPackedGuid();
|
||||
ToTheDeath = _worldPacket.HasBit();
|
||||
}
|
||||
|
||||
public ObjectGuid TargetGUID;
|
||||
public bool ToTheDeath;
|
||||
}
|
||||
|
||||
public class CanDuelResult : ServerPacket
|
||||
@@ -85,11 +87,14 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WritePackedGuid(ArbiterGUID);
|
||||
_worldPacket.WritePackedGuid(RequestedByGUID);
|
||||
_worldPacket.WritePackedGuid(RequestedByWowAccount);
|
||||
_worldPacket.WriteBit(ToTheDeath);
|
||||
_worldPacket.FlushBits();
|
||||
}
|
||||
|
||||
public ObjectGuid ArbiterGUID;
|
||||
public ObjectGuid RequestedByGUID;
|
||||
public ObjectGuid RequestedByWowAccount;
|
||||
public bool ToTheDeath;
|
||||
}
|
||||
|
||||
public class DuelResponse : ClientPacket
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.Entities;
|
||||
using Game.Miscellaneous;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -1705,12 +1706,20 @@ namespace Game.Networking.Packets
|
||||
|
||||
public class GuildRewardItem
|
||||
{
|
||||
public uint ItemID;
|
||||
public uint Unk4;
|
||||
public List<uint> AchievementsRequired = new();
|
||||
public RaceMask<ulong> RaceMask;
|
||||
public int MinGuildLevel;
|
||||
public int MinGuildRep;
|
||||
public ulong Cost;
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt32(ItemID);
|
||||
data.WriteUInt32(Unk4);
|
||||
data.WriteInt32(AchievementsRequired.Count);
|
||||
data.WriteUInt64(RaceMask);
|
||||
data.WriteUInt64(RaceMask.RawValue);
|
||||
data.WriteInt32(MinGuildLevel);
|
||||
data.WriteInt32(MinGuildRep);
|
||||
data.WriteUInt64(Cost);
|
||||
@@ -1718,14 +1727,6 @@ namespace Game.Networking.Packets
|
||||
foreach (var achievementId in AchievementsRequired)
|
||||
data.WriteUInt32(achievementId);
|
||||
}
|
||||
|
||||
public uint ItemID;
|
||||
public uint Unk4;
|
||||
public List<uint> AchievementsRequired = new();
|
||||
public ulong RaceMask;
|
||||
public int MinGuildLevel;
|
||||
public int MinGuildRep;
|
||||
public ulong Cost;
|
||||
}
|
||||
|
||||
public class GuildBankItemInfo
|
||||
|
||||
@@ -38,8 +38,8 @@ namespace Game.Networking.Packets
|
||||
Quantity = _worldPacket.ReadInt32();
|
||||
Muid = _worldPacket.ReadUInt32();
|
||||
Slot = _worldPacket.ReadUInt32();
|
||||
ItemType = (ItemVendorType)_worldPacket.ReadInt32();
|
||||
Item.Read(_worldPacket);
|
||||
ItemType = (ItemVendorType)_worldPacket.ReadBits<int>(3);
|
||||
}
|
||||
|
||||
public ObjectGuid VendorGUID;
|
||||
|
||||
@@ -250,6 +250,10 @@ namespace Game.Networking.Packets
|
||||
case MailMessageType.Creature:
|
||||
case MailMessageType.Gameobject:
|
||||
case MailMessageType.Calendar:
|
||||
case MailMessageType.Blackmarket:
|
||||
case MailMessageType.CommerceAuction:
|
||||
case MailMessageType.Auction2:
|
||||
case MailMessageType.ArtisansConsortium:
|
||||
AltSenderID = (int)mail.sender;
|
||||
break;
|
||||
}
|
||||
@@ -353,7 +357,7 @@ namespace Game.Networking.Packets
|
||||
public MailListEntry(Mail mail, Player player)
|
||||
{
|
||||
MailID = mail.messageID;
|
||||
SenderType = (byte)mail.messageType;
|
||||
SenderType = mail.messageType;
|
||||
|
||||
switch (mail.messageType)
|
||||
{
|
||||
@@ -364,6 +368,10 @@ namespace Game.Networking.Packets
|
||||
case MailMessageType.Gameobject:
|
||||
case MailMessageType.Auction:
|
||||
case MailMessageType.Calendar:
|
||||
case MailMessageType.Blackmarket:
|
||||
case MailMessageType.CommerceAuction:
|
||||
case MailMessageType.Auction2:
|
||||
case MailMessageType.ArtisansConsortium:
|
||||
AltSenderID = (uint)mail.sender;
|
||||
break;
|
||||
}
|
||||
@@ -388,7 +396,7 @@ namespace Game.Networking.Packets
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt64(MailID);
|
||||
data.WriteUInt8(SenderType);
|
||||
data.WriteUInt32((uint)SenderType);
|
||||
data.WriteUInt64(Cod);
|
||||
data.WriteInt32(StationeryID);
|
||||
data.WriteUInt64(SentMoney);
|
||||
@@ -397,28 +405,39 @@ namespace Game.Networking.Packets
|
||||
data.WriteInt32(MailTemplateID);
|
||||
data.WriteInt32(Attachments.Count);
|
||||
|
||||
data.WriteBit(SenderCharacter.HasValue);
|
||||
data.WriteBit(AltSenderID.HasValue);
|
||||
switch (SenderType)
|
||||
{
|
||||
case MailMessageType.Normal:
|
||||
data.WritePackedGuid(SenderCharacter);
|
||||
break;
|
||||
case MailMessageType.Auction:
|
||||
case MailMessageType.Creature:
|
||||
case MailMessageType.Gameobject:
|
||||
case MailMessageType.Calendar:
|
||||
case MailMessageType.Blackmarket:
|
||||
case MailMessageType.CommerceAuction:
|
||||
case MailMessageType.Auction2:
|
||||
case MailMessageType.ArtisansConsortium:
|
||||
data.WriteUInt32(AltSenderID);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
data.WriteBits(Subject.GetByteCount(), 8);
|
||||
data.WriteBits(Body.GetByteCount(), 13);
|
||||
data.FlushBits();
|
||||
|
||||
Attachments.ForEach(p => p.Write(data));
|
||||
|
||||
if (SenderCharacter.HasValue)
|
||||
data.WritePackedGuid(SenderCharacter.Value);
|
||||
|
||||
if (AltSenderID.HasValue)
|
||||
data.WriteUInt32(AltSenderID.Value);
|
||||
|
||||
data.WriteString(Subject);
|
||||
data.WriteString(Body);
|
||||
}
|
||||
|
||||
public ulong MailID;
|
||||
public byte SenderType;
|
||||
public ObjectGuid? SenderCharacter;
|
||||
public uint? AltSenderID;
|
||||
public MailMessageType SenderType;
|
||||
public ObjectGuid SenderCharacter;
|
||||
public uint AltSenderID;
|
||||
public ulong Cod;
|
||||
public int StationeryID;
|
||||
public ulong SentMoney;
|
||||
|
||||
@@ -1338,7 +1338,7 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteBit(BonusRoll);
|
||||
Item.Write(_worldPacket);
|
||||
_worldPacket.WriteInt32(LootSpec);
|
||||
_worldPacket.WriteInt32((int)Gender);
|
||||
_worldPacket.WriteInt8((sbyte)Gender);
|
||||
break;
|
||||
case DisplayToastType.NewCurrency:
|
||||
_worldPacket.WriteUInt32(CurrencyID);
|
||||
|
||||
@@ -394,12 +394,12 @@ namespace Game.Networking.Packets
|
||||
{
|
||||
data.WriteUInt64(Price);
|
||||
data.WriteInt32(MuID);
|
||||
data.WriteInt32(Type);
|
||||
data.WriteInt32(Durability);
|
||||
data.WriteInt32(StackCount);
|
||||
data.WriteInt32(Quantity);
|
||||
data.WriteInt32(ExtendedCostID);
|
||||
data.WriteInt32(PlayerConditionFailed);
|
||||
data.WriteBits(Type, 3);
|
||||
data.WriteBit(Locked);
|
||||
data.WriteBit(DoNotFilterOnVendor);
|
||||
data.WriteBit(Refundable);
|
||||
|
||||
@@ -124,32 +124,6 @@ namespace Game.Networking.Packets
|
||||
public List<PetSpellHistory> SpellHistory = new();
|
||||
}
|
||||
|
||||
class PetStableList : ServerPacket
|
||||
{
|
||||
public PetStableList() : base(ServerOpcodes.PetStableList, ConnectionType.Instance) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WritePackedGuid(StableMaster);
|
||||
|
||||
_worldPacket.WriteInt32(Pets.Count);
|
||||
foreach (PetStableInfo pet in Pets)
|
||||
{
|
||||
_worldPacket.WriteUInt32(pet.PetSlot);
|
||||
_worldPacket.WriteUInt32(pet.PetNumber);
|
||||
_worldPacket.WriteUInt32(pet.CreatureID);
|
||||
_worldPacket.WriteUInt32(pet.DisplayID);
|
||||
_worldPacket.WriteUInt32(pet.ExperienceLevel);
|
||||
_worldPacket.WriteUInt8((byte)pet.PetFlags);
|
||||
_worldPacket.WriteBits(pet.PetName.GetByteCount(), 8);
|
||||
_worldPacket.WriteString(pet.PetName);
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectGuid StableMaster;
|
||||
public List<PetStableInfo> Pets = new();
|
||||
}
|
||||
|
||||
class PetStableResult : ServerPacket
|
||||
{
|
||||
public PetStableResult() : base(ServerOpcodes.PetStableResult, ConnectionType.Instance) { }
|
||||
@@ -382,17 +356,6 @@ namespace Game.Networking.Packets
|
||||
public sbyte ConsumedCharges;
|
||||
}
|
||||
|
||||
struct PetStableInfo
|
||||
{
|
||||
public uint PetSlot;
|
||||
public uint PetNumber;
|
||||
public uint CreatureID;
|
||||
public uint DisplayID;
|
||||
public uint ExperienceLevel;
|
||||
public PetStableinfo PetFlags;
|
||||
public string PetName;
|
||||
}
|
||||
|
||||
struct PetRenameData
|
||||
{
|
||||
public ObjectGuid PetGUID;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.Entities;
|
||||
using Game.Miscellaneous;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -53,7 +54,7 @@ namespace Game.Networking.Packets
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WritePackedGuid(QuestGiver.Guid);
|
||||
_worldPacket.WriteUInt32((uint)QuestGiver.Status);
|
||||
_worldPacket.WriteUInt64((ulong)QuestGiver.Status);
|
||||
}
|
||||
|
||||
public QuestGiverInfo QuestGiver;
|
||||
@@ -69,7 +70,7 @@ namespace Game.Networking.Packets
|
||||
foreach (QuestGiverInfo questGiver in QuestGiver)
|
||||
{
|
||||
_worldPacket.WritePackedGuid(questGiver.Guid);
|
||||
_worldPacket.WriteUInt32((uint)questGiver.Status);
|
||||
_worldPacket.WriteUInt64((ulong)questGiver.Status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,10 +191,10 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteUInt32(Info.CompleteSoundKitID);
|
||||
|
||||
_worldPacket.WriteUInt32(Info.AreaGroupID);
|
||||
_worldPacket.WriteUInt32(Info.TimeAllowed);
|
||||
_worldPacket.WriteInt64(Info.TimeAllowed);
|
||||
|
||||
_worldPacket.WriteInt32(Info.Objectives.Count);
|
||||
_worldPacket.WriteInt64(Info.AllowableRaces);
|
||||
_worldPacket.WriteUInt64(Info.AllowableRaces.RawValue);
|
||||
_worldPacket.WriteInt32(Info.TreasurePickerID);
|
||||
_worldPacket.WriteInt32(Info.Expansion);
|
||||
_worldPacket.WriteInt32(Info.ManagedWorldStateID);
|
||||
@@ -1037,7 +1038,7 @@ namespace Game.Networking.Packets
|
||||
public float POIx;
|
||||
public float POIy;
|
||||
public uint POIPriority;
|
||||
public long AllowableRaces = -1;
|
||||
public RaceMask<ulong> AllowableRaces = new (0xFFFFFFFFFFFFFFFF);
|
||||
public string LogTitle;
|
||||
public string LogDescription;
|
||||
public string QuestDescription;
|
||||
@@ -1059,7 +1060,7 @@ namespace Game.Networking.Packets
|
||||
public uint AcceptedSoundKitID;
|
||||
public uint CompleteSoundKitID;
|
||||
public uint AreaGroupID;
|
||||
public uint TimeAllowed;
|
||||
public long TimeAllowed;
|
||||
public int TreasurePickerID;
|
||||
public int Expansion;
|
||||
public int ManagedWorldStateID;
|
||||
|
||||
@@ -10,10 +10,25 @@ namespace Game.Networking.Packets
|
||||
{
|
||||
class ScenarioState : ServerPacket
|
||||
{
|
||||
public ObjectGuid ScenarioGUID;
|
||||
public int ScenarioID;
|
||||
public int CurrentStep = -1;
|
||||
public uint DifficultyID;
|
||||
public uint WaveCurrent;
|
||||
public uint WaveMax;
|
||||
public uint TimerDuration;
|
||||
public List<CriteriaProgressPkt> CriteriaProgress = new();
|
||||
public List<BonusObjectiveData> BonusObjectives = new();
|
||||
public List<uint> PickedSteps = new();
|
||||
public List<ScenarioSpellUpdate> Spells = new();
|
||||
public ObjectGuid PlayerGUID;
|
||||
public bool ScenarioComplete;
|
||||
|
||||
public ScenarioState() : base(ServerOpcodes.ScenarioState, ConnectionType.Instance) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WritePackedGuid(ScenarioGUID);
|
||||
_worldPacket.WriteInt32(ScenarioID);
|
||||
_worldPacket.WriteInt32(CurrentStep);
|
||||
_worldPacket.WriteUInt32(DifficultyID);
|
||||
@@ -41,35 +56,24 @@ namespace Game.Networking.Packets
|
||||
foreach (ScenarioSpellUpdate spell in Spells)
|
||||
spell.Write(_worldPacket);
|
||||
}
|
||||
|
||||
public int ScenarioID;
|
||||
public int CurrentStep = -1;
|
||||
public uint DifficultyID;
|
||||
public uint WaveCurrent;
|
||||
public uint WaveMax;
|
||||
public uint TimerDuration;
|
||||
public List<CriteriaProgressPkt> CriteriaProgress = new();
|
||||
public List<BonusObjectiveData> BonusObjectives = new();
|
||||
public List<uint> PickedSteps = new();
|
||||
public List<ScenarioSpellUpdate> Spells = new();
|
||||
public ObjectGuid PlayerGUID;
|
||||
public bool ScenarioComplete = false;
|
||||
}
|
||||
|
||||
class ScenarioProgressUpdate : ServerPacket
|
||||
{
|
||||
public CriteriaProgressPkt CriteriaProgress;
|
||||
|
||||
public ScenarioProgressUpdate() : base(ServerOpcodes.ScenarioProgressUpdate, ConnectionType.Instance) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
CriteriaProgress.Write(_worldPacket);
|
||||
}
|
||||
|
||||
public CriteriaProgressPkt CriteriaProgress;
|
||||
}
|
||||
|
||||
class ScenarioCompleted : ServerPacket
|
||||
{
|
||||
public uint ScenarioID;
|
||||
|
||||
public ScenarioCompleted(uint scenarioId) : base(ServerOpcodes.ScenarioCompleted, ConnectionType.Instance)
|
||||
{
|
||||
ScenarioID = scenarioId;
|
||||
@@ -79,29 +83,31 @@ namespace Game.Networking.Packets
|
||||
{
|
||||
_worldPacket.WriteUInt32(ScenarioID);
|
||||
}
|
||||
|
||||
public uint ScenarioID;
|
||||
}
|
||||
|
||||
class ScenarioVacate : ServerPacket
|
||||
{
|
||||
public ObjectGuid ScenarioGUID;
|
||||
public int ScenarioID;
|
||||
public int Unk1;
|
||||
public byte Unk2;
|
||||
|
||||
public ScenarioVacate() : base(ServerOpcodes.ScenarioVacate, ConnectionType.Instance) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WritePackedGuid(ScenarioGUID);
|
||||
_worldPacket.WriteInt32(ScenarioID);
|
||||
_worldPacket.WriteInt32(Unk1);
|
||||
_worldPacket.WriteBits(Unk2, 2);
|
||||
_worldPacket.FlushBits();
|
||||
}
|
||||
|
||||
public int ScenarioID;
|
||||
public int Unk1;
|
||||
public byte Unk2;
|
||||
}
|
||||
|
||||
class QueryScenarioPOI : ClientPacket
|
||||
{
|
||||
public Array<int> MissingScenarioPOIs = new(50);
|
||||
|
||||
public QueryScenarioPOI(WorldPacket packet) : base(packet) { }
|
||||
|
||||
public override void Read()
|
||||
@@ -110,12 +116,12 @@ namespace Game.Networking.Packets
|
||||
for (var i = 0; i < count; ++i)
|
||||
MissingScenarioPOIs[i] = _worldPacket.ReadInt32();
|
||||
}
|
||||
|
||||
public Array<int> MissingScenarioPOIs = new(50);
|
||||
}
|
||||
|
||||
class ScenarioPOIs : ServerPacket
|
||||
{
|
||||
public List<ScenarioPOIData> ScenarioPOIDataStats = new();
|
||||
|
||||
public ScenarioPOIs() : base(ServerOpcodes.ScenarioPois) { }
|
||||
|
||||
public override void Write()
|
||||
@@ -148,34 +154,32 @@ namespace Game.Networking.Packets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<ScenarioPOIData> ScenarioPOIDataStats = new();
|
||||
}
|
||||
|
||||
struct BonusObjectiveData
|
||||
{
|
||||
public int BonusObjectiveID;
|
||||
public bool ObjectiveComplete;
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteInt32(BonusObjectiveID);
|
||||
data.WriteBit(ObjectiveComplete);
|
||||
data.FlushBits();
|
||||
}
|
||||
|
||||
public int BonusObjectiveID;
|
||||
public bool ObjectiveComplete;
|
||||
}
|
||||
|
||||
class ScenarioSpellUpdate
|
||||
{
|
||||
public uint SpellID;
|
||||
public bool Usable = true;
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt32(SpellID);
|
||||
data.WriteBit(Usable);
|
||||
data.FlushBits();
|
||||
}
|
||||
|
||||
public uint SpellID;
|
||||
public bool Usable = true;
|
||||
}
|
||||
|
||||
struct ScenarioPOIData
|
||||
|
||||
@@ -1371,6 +1371,43 @@ namespace Game.Networking.Packets
|
||||
}
|
||||
}
|
||||
|
||||
struct CombatWorldTextViewerInfo
|
||||
{
|
||||
public ObjectGuid ViewerGUID;
|
||||
public byte? ColorType;
|
||||
public byte? ScaleType;
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WritePackedGuid(ViewerGUID);
|
||||
data.WriteBit(ColorType.HasValue);
|
||||
data.WriteBit(ScaleType.HasValue);
|
||||
data.FlushBits();
|
||||
|
||||
if (ColorType.HasValue)
|
||||
data.WriteUInt8(ColorType.Value);
|
||||
|
||||
if (ScaleType.HasValue)
|
||||
data.WriteUInt8(ScaleType.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public struct SpellSupportInfo
|
||||
{
|
||||
public ObjectGuid CasterGUID;
|
||||
public int SpellID;
|
||||
public int Amount;
|
||||
public float Percentage;
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WritePackedGuid(CasterGUID);
|
||||
data.WriteInt32(SpellID);
|
||||
data.WriteInt32(Amount);
|
||||
data.WriteFloat(Percentage);
|
||||
}
|
||||
}
|
||||
|
||||
public struct SpellCastVisual
|
||||
{
|
||||
public uint SpellXSpellVisualID;
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteBit(LFGListCustomRequiresAuthenticator);
|
||||
_worldPacket.WriteBit(AddonsDisabled);
|
||||
_worldPacket.WriteBit(Unused1000);
|
||||
_worldPacket.WriteBit(ContentTrackingEnabled);
|
||||
|
||||
_worldPacket.FlushBits();
|
||||
|
||||
@@ -176,6 +177,7 @@ namespace Game.Networking.Packets
|
||||
public bool LFGListCustomRequiresAuthenticator;
|
||||
public bool AddonsDisabled;
|
||||
public bool Unused1000;
|
||||
public bool ContentTrackingEnabled;
|
||||
|
||||
public SocialQueueConfig QuickJoinConfig;
|
||||
public SquelchInfo Squelch;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
using Game.Entities;
|
||||
using Game.Miscellaneous;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -91,7 +92,7 @@ namespace Game.Networking.Packets
|
||||
{
|
||||
MinLevel = data.ReadInt32();
|
||||
MaxLevel = data.ReadInt32();
|
||||
RaceFilter = data.ReadInt64();
|
||||
RaceFilter = new RaceMask<long>(data.ReadInt64());
|
||||
ClassFilter = data.ReadInt32();
|
||||
|
||||
uint nameLength = data.ReadBits<uint>(6);
|
||||
@@ -129,7 +130,7 @@ namespace Game.Networking.Packets
|
||||
public string VirtualRealmName;
|
||||
public string Guild;
|
||||
public string GuildVirtualRealmName;
|
||||
public long RaceFilter;
|
||||
public RaceMask<long> RaceFilter;
|
||||
public int ClassFilter = -1;
|
||||
public List<string> Words = new();
|
||||
public bool ShowEnemies;
|
||||
|
||||
@@ -6,6 +6,7 @@ using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
using System.Collections;
|
||||
@@ -101,7 +102,7 @@ namespace Game
|
||||
SoundTurnIn = fields.Read<uint>(99);
|
||||
AreaGroupID = fields.Read<uint>(100);
|
||||
LimitTime = fields.Read<uint>(101);
|
||||
AllowableRaces = (long)fields.Read<ulong>(102);
|
||||
AllowableRaces = new(fields.Read<ulong>(102));
|
||||
TreasurePickerID = fields.Read<int>(103);
|
||||
Expansion = fields.Read<int>(104);
|
||||
ManagedWorldStateID = fields.Read<int>(105);
|
||||
@@ -472,6 +473,15 @@ namespace Game
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsImportant()
|
||||
{
|
||||
var questInfo = CliDB.QuestInfoStorage.LookupByKey(QuestInfoID);
|
||||
if (questInfo != null)
|
||||
return (questInfo.Modifiers & 0x400) != 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void BuildQuestRewards(QuestRewards rewards, Player player)
|
||||
{
|
||||
rewards.ChoiceItemCount = GetRewChoiceItemsCount();
|
||||
@@ -864,8 +874,8 @@ namespace Game
|
||||
public uint SoundAccept { get; set; }
|
||||
public uint SoundTurnIn { get; set; }
|
||||
public uint AreaGroupID;
|
||||
public uint LimitTime;
|
||||
public long AllowableRaces { get; set; }
|
||||
public long LimitTime;
|
||||
public RaceMask<ulong> AllowableRaces { get; set; }
|
||||
public int TreasurePickerID;
|
||||
public int Expansion;
|
||||
public int ManagedWorldStateID;
|
||||
@@ -946,6 +956,7 @@ namespace Game
|
||||
{
|
||||
public ushort Slot = SharedConst.MaxQuestLogSize;
|
||||
public QuestStatus Status;
|
||||
public long AcceptTime;
|
||||
public uint Timer;
|
||||
public bool Explored;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Framework.Constants;
|
||||
using Framework.Database;
|
||||
using Game.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -593,7 +594,7 @@ namespace Game
|
||||
var factionEntry = CliDB.FactionStorage.LookupByKey(factionTemplateEntry.Faction);
|
||||
if (factionEntry.Id != 0)
|
||||
// Never show factions of the opposing team
|
||||
if (!Convert.ToBoolean(factionEntry.ReputationRaceMask[1] & SharedConst.GetMaskForRace(_player.GetRace())) && factionEntry.ReputationBase[1] == SharedConst.ReputationBottom)
|
||||
if (!(new RaceMask<long>(factionEntry.ReputationRaceMask[1]).HasRace(_player.GetRace()) && factionEntry.ReputationBase[1] == SharedConst.ReputationBottom))
|
||||
SetVisible(factionEntry);
|
||||
}
|
||||
|
||||
@@ -798,13 +799,12 @@ namespace Game
|
||||
if (factionEntry == null)
|
||||
return -1;
|
||||
|
||||
long raceMask = SharedConst.GetMaskForRace(_player.GetRace());
|
||||
short classMask = (short)_player.GetClassMask();
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ((factionEntry.ReputationRaceMask[i].HasAnyFlag(raceMask) || (factionEntry.ReputationRaceMask[i] == 0 && factionEntry.ReputationClassMask[i] != 0))
|
||||
&& (factionEntry.ReputationClassMask[i].HasAnyFlag(classMask) || factionEntry.ReputationClassMask[i] == 0))
|
||||
|
||||
var raceMask = new RaceMask<long>(factionEntry.ReputationRaceMask[i]);
|
||||
if ((raceMask.HasRace(_player.GetRace()) || (raceMask.IsEmpty() && factionEntry.ReputationClassMask[i] != 0)) && (factionEntry.ReputationClassMask[i].HasAnyFlag(classMask) || factionEntry.ReputationClassMask[i] == 0))
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -862,13 +862,12 @@ namespace Game
|
||||
if (factionEntry == null)
|
||||
return 0;
|
||||
|
||||
long raceMask = SharedConst.GetMaskForRace(race);
|
||||
uint classMask = (1u << ((int)playerClass - 1));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ((factionEntry.ReputationClassMask[i] == 0 || factionEntry.ReputationClassMask[i].HasAnyFlag((short)classMask))
|
||||
&& (factionEntry.ReputationRaceMask[i] == 0 || factionEntry.ReputationRaceMask[i].HasAnyFlag(raceMask)))
|
||||
var raceMask = new RaceMask<long>(factionEntry.ReputationRaceMask[i]);
|
||||
if ((factionEntry.ReputationClassMask[i] == 0 || factionEntry.ReputationClassMask[i].HasAnyFlag((short)classMask)) && (raceMask.IsEmpty() || raceMask.HasRace(race)))
|
||||
return factionEntry.ReputationBase[i];
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Game.Scenarios
|
||||
{
|
||||
_map = map;
|
||||
_data = scenarioData;
|
||||
_guid = ObjectGuid.Create(HighGuid.Scenario, map.GetId(), scenarioData.Entry.Id, map.GenerateLowGuid(HighGuid.Scenario));
|
||||
_currentstep = null;
|
||||
|
||||
//ASSERT(_data);
|
||||
@@ -229,6 +230,7 @@ namespace Game.Scenarios
|
||||
|
||||
void BuildScenarioState(ScenarioState scenarioState)
|
||||
{
|
||||
scenarioState.ScenarioGUID = _guid;
|
||||
scenarioState.ScenarioID = (int)_data.Entry.Id;
|
||||
ScenarioStepRecord step = GetStep();
|
||||
if (step != null)
|
||||
@@ -343,6 +345,7 @@ namespace Game.Scenarios
|
||||
void SendBootPlayer(Player player)
|
||||
{
|
||||
ScenarioVacate scenarioBoot = new();
|
||||
scenarioBoot.ScenarioGUID = _guid;
|
||||
scenarioBoot.ScenarioID = (int)_data.Entry.Id;
|
||||
player.SendPacket(scenarioBoot);
|
||||
}
|
||||
@@ -362,6 +365,7 @@ namespace Game.Scenarios
|
||||
protected Map _map;
|
||||
List<ObjectGuid> _players = new();
|
||||
protected ScenarioData _data;
|
||||
ObjectGuid _guid;
|
||||
ScenarioStepRecord _currentstep;
|
||||
Dictionary<ScenarioStepRecord, ScenarioStepState> _stepStates = new();
|
||||
}
|
||||
|
||||
@@ -702,7 +702,7 @@ namespace Game
|
||||
_queryHolderProcessor.ProcessReadyCallbacks();
|
||||
}
|
||||
|
||||
TransactionCallback AddTransactionCallback(TransactionCallback callback)
|
||||
public TransactionCallback AddTransactionCallback(TransactionCallback callback)
|
||||
{
|
||||
return _transactionCallbacks.AddCallback(callback);
|
||||
}
|
||||
|
||||
@@ -4841,7 +4841,7 @@ namespace Game.Spells
|
||||
return;
|
||||
|
||||
if (apply)
|
||||
target.ToPlayer().GetSession().SendStablePet(target.GetGUID());
|
||||
target.ToPlayer().SetStableMaster(target.GetGUID());
|
||||
|
||||
// client auto close stable dialog at !apply aura
|
||||
}
|
||||
@@ -5959,6 +5959,28 @@ namespace Game.Spells
|
||||
playerTarget.SendMovementSetCollisionHeight(playerTarget.GetCollisionHeight(), UpdateCollisionHeightReason.Force);
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.ModRequiredMountCapabilityFlags)]
|
||||
void HandleModRequiredMountCapabilityFlags(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
|
||||
{
|
||||
if (!mode.HasAnyFlag(AuraEffectHandleModes.Real))
|
||||
return;
|
||||
|
||||
Player playerTarget = aurApp.GetTarget().ToPlayer();
|
||||
if (playerTarget == null)
|
||||
return;
|
||||
|
||||
if (apply)
|
||||
playerTarget.SetRequiredMountCapabilityFlag((byte)GetMiscValue());
|
||||
else
|
||||
{
|
||||
int mountCapabilityFlags = 0;
|
||||
foreach (AuraEffect otherAura in playerTarget.GetAuraEffectsByType(GetAuraType()))
|
||||
mountCapabilityFlags |= otherAura.GetMiscValue();
|
||||
|
||||
playerTarget.ReplaceAllRequiredMountCapabilityFlags((byte)mountCapabilityFlags);
|
||||
}
|
||||
}
|
||||
|
||||
[AuraEffectHandler(AuraType.SuppressItemPassiveEffectBySpellLabel)]
|
||||
void HandleSuppressItemPassiveEffectBySpellLabel(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
|
||||
{
|
||||
|
||||
@@ -4829,7 +4829,7 @@ namespace Game.Spells
|
||||
if (m_spellInfo.ExcludeCasterAuraType != 0 && unitCaster.HasAuraType(m_spellInfo.ExcludeCasterAuraType))
|
||||
return SpellCastResult.CasterAurastate;
|
||||
|
||||
if (reqCombat && unitCaster.IsInCombat() && !m_spellInfo.CanBeUsedInCombat())
|
||||
if (reqCombat && unitCaster.IsInCombat() && !m_spellInfo.CanBeUsedInCombat(unitCaster))
|
||||
return SpellCastResult.AffectingCombat;
|
||||
}
|
||||
|
||||
|
||||
@@ -518,9 +518,10 @@ namespace Game.Spells
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanBeUsedInCombat()
|
||||
public bool CanBeUsedInCombat(Unit caster)
|
||||
{
|
||||
return !HasAttribute(SpellAttr0.NotInCombatOnlyPeaceful);
|
||||
return !HasAttribute(SpellAttr0.NotInCombatOnlyPeaceful)
|
||||
|| (caster.HasAuraType(AuraType.AllowMountInCombat) && HasAura(AuraType.Mounted));
|
||||
}
|
||||
|
||||
public bool IsPositive()
|
||||
@@ -3144,7 +3145,7 @@ namespace Game.Spells
|
||||
}
|
||||
case SpellProcsPerMinuteModType.Race:
|
||||
{
|
||||
if (SharedConst.GetMaskForRace(caster.GetRace()).HasAnyFlag((int)mod.Param))
|
||||
if ((caster.GetRaceMask() & mod.Param) != 0)
|
||||
ppm *= 1.0f + mod.Coeff;
|
||||
break;
|
||||
}
|
||||
@@ -4822,15 +4823,16 @@ namespace Game.Spells
|
||||
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 303 SPELL_EFFECT_CREATE_TRAIT_TREE_CONFIG
|
||||
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 304 SPELL_EFFECT_CHANGE_ACTIVE_COMBAT_TRAIT_CONFIG
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 305 SPELL_EFFECT_305
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 306 SPELL_EFFECT_306
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 306 SPELL_EFFECT_UPDATE_INTERACTIONS
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 307 SPELL_EFFECT_307
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 308 SPELL_EFFECT_308
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 309 SPELL_EFFECT_309
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 308 SPELL_EFFECT_CANCEL_PRELOAD_WORLD
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 309 SPELL_EFFECT_PRELOAD_WORLD
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 310 SPELL_EFFECT_310
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 311 SPELL_EFFECT_311
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 311 SPELL_EFFECT_ENSURE_WORLD_LOADED
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 312 SPELL_EFFECT_312
|
||||
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 313 SPELL_EFFECT_313
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 314 SPELL_EFFECT_314
|
||||
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 313 SPELL_EFFECT_CHANGE_ITEM_BONUSES_2
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 314 SPELL_EFFECT_ADD_SOCKET_BONUS
|
||||
new StaticData(SpellEffectImplicitTargetTypes.Caster, SpellTargetObjectTypes.Unit), // 315 SPELL_EFFECT_LEARN_TRANSMOG_APPEARANCE_FROM_ITEM_MOD_APPEARANCE_GROUP
|
||||
};
|
||||
|
||||
#region Fields
|
||||
|
||||
@@ -8,6 +8,7 @@ using Game.BattleFields;
|
||||
using Game.BattleGrounds;
|
||||
using Game.BattlePets;
|
||||
using Game.DataStorage;
|
||||
using Game.Miscellaneous;
|
||||
using Game.Movement;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
@@ -1987,7 +1988,7 @@ namespace Game.Entities
|
||||
spellArea.questEndStatus = result.Read<uint>(4);
|
||||
spellArea.questEnd = result.Read<uint>(5);
|
||||
spellArea.auraSpell = result.Read<int>(6);
|
||||
spellArea.raceMask = result.Read<ulong>(7);
|
||||
spellArea.raceMask = new RaceMask<ulong>(result.Read<ulong>(7));
|
||||
spellArea.gender = (Gender)result.Read<uint>(8);
|
||||
spellArea.flags = (SpellAreaFlag)result.Read<byte>(9);
|
||||
|
||||
@@ -2016,7 +2017,7 @@ namespace Game.Entities
|
||||
continue;
|
||||
if (spellArea.auraSpell != bound.auraSpell)
|
||||
continue;
|
||||
if ((spellArea.raceMask & bound.raceMask) == 0)
|
||||
if ((spellArea.raceMask & bound.raceMask).IsEmpty())
|
||||
continue;
|
||||
if (spellArea.gender != bound.gender)
|
||||
continue;
|
||||
@@ -2107,7 +2108,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
if (spellArea.raceMask != 0 && (spellArea.raceMask & SharedConst.RaceMaskAllPlayable) == 0)
|
||||
if (!spellArea.raceMask.IsEmpty() && (spellArea.raceMask & RaceMask.AllPlayable).IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Spell {0} listed in `spell_area` have wrong race mask ({1}) requirement", spell, spellArea.raceMask);
|
||||
continue;
|
||||
@@ -4913,7 +4914,7 @@ namespace Game.Entities
|
||||
public uint questStart; // quest start (quest must be active or rewarded for spell apply)
|
||||
public uint questEnd; // quest end (quest must not be rewarded for spell apply)
|
||||
public int auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case
|
||||
public ulong raceMask; // can be applied only to races
|
||||
public RaceMask<ulong> raceMask; // can be applied only to races
|
||||
public Gender gender; // can be applied only to gender
|
||||
public uint questStartStatus; // QuestStatus that quest_start must have in order to keep the spell
|
||||
public uint questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped)
|
||||
@@ -4926,8 +4927,8 @@ namespace Game.Entities
|
||||
if (player == null || gender != player.GetNativeGender())
|
||||
return false;
|
||||
|
||||
if (raceMask != 0) // not in expected race
|
||||
if (player == null || !Convert.ToBoolean(raceMask & (ulong)SharedConst.GetMaskForRace(player.GetRace())))
|
||||
if (!raceMask.IsEmpty()) // not in expected race
|
||||
if (player == null || !raceMask.HasRace(player.GetRace()))
|
||||
return false;
|
||||
|
||||
if (areaId != 0) // not in expected zone
|
||||
|
||||
Reference in New Issue
Block a user