Core: Updated to 11.2.0

Port From (https://github.com/TrinityCore/TrinityCore/commit/5cf0c6c8bb2c4e58a2d66ba5f304af34d18a4782)
This commit is contained in:
Hondacrx
2025-08-25 20:48:29 -04:00
parent d64045154a
commit aaa669210a
63 changed files with 5958 additions and 5434 deletions
@@ -774,10 +774,10 @@ namespace Framework.Constants
CompleteQuestsCountOnAccount = 257, /*NYI*/
WarbandBankTabPurchased = 260, /*NYI*/
BankTabPurchased = 260, // Bank Tab Purchased in {#BankType}
ReachRenownLevel = 261,
LearnTaxiNode = 262,
Count = 264
Count = 270
}
public enum CriteriaDataType
@@ -46,4 +46,28 @@ namespace Framework.Constants
HasCircularMovement = 0x400, // DEPRECATED
Unk5 = 0x800,
}
public enum AreaTriggerFieldFlags
{
None = 0x0000,
HeightIgnoresScale = 0x0001,
WowLabsCircle = 0x0002,
CanLoop = 0x0004,
AbsoluteOrientation = 0x0008,
DynamicShape = 0x0010,
Attached = 0x0020,
FaceMovementDir = 0x0040,
FollowsTerrain = 0x0080,
Unknown1025 = 0x0100,
AlwaysExterior = 0x0200,
HasPlayers = 0x0400,
}
public enum AreaTriggerPathType
{
Spline = 0,
Orbit = 1,
None = 2,
MovementScript = 3
}
}
@@ -68,6 +68,8 @@ namespace Framework.Constants
ClientModel = 60,
CraftingTable = 61,
PerksProgramChest = 62,
FuturePatch = 63,
AssistAction = 64,
Max
}
+28 -29
View File
@@ -144,20 +144,14 @@ namespace Framework.Constants
public const byte ItemStart = 35;
public const byte ItemEnd = 63;
public const byte BankItemStart = 63;
public const byte BankItemEnd = 91;
public const byte BankBagStart = 63;
public const byte BankBagEnd = 69;
public const byte BankBagStart = 91;
public const byte BankBagEnd = 98;
public const byte BuyBackStart = 69;
public const byte BuyBackEnd = 81;
public const byte BuyBackStart = 98;
public const byte BuyBackEnd = 110;
public const byte ReagentStart = 110;
public const byte ReagentEnd = 208;
public const byte ChildEquipmentStart = 208;
public const byte ChildEquipmentEnd = 211;
public const byte ChildEquipmentStart = 81;
public const byte ChildEquipmentEnd = 84;
public const byte Bag0 = 255;
public const byte DefaultSize = 16;
@@ -165,22 +159,22 @@ namespace Framework.Constants
enum EquipableSpellSlots
{
OffensiveSlot1 = 211,
OffensiveSlot2 = 212,
OffensiveSlot3 = 213,
OffensiveSlot4 = 214,
UtilitySlot1 = 215,
UtilitySlot2 = 216,
UtilitySlot3 = 217,
UtilitySlot4 = 218,
DefensiveSlot1 = 219,
DefensiveSlot2 = 220,
DefensiveSlot3 = 221,
DefensiveSlot4 = 222,
WeaponSlot1 = 223,
WeaponSlot2 = 224,
WeaponSlot3 = 225,
WeaponSlot4 = 226,
OffensiveSlot1 = 84,
OffensiveSlot2 = 85,
OffensiveSlot3 = 86,
OffensiveSlot4 = 87,
UtilitySlot1 = 88,
UtilitySlot2 = 89,
UtilitySlot3 = 90,
UtilitySlot4 = 91,
DefensiveSlot1 = 92,
DefensiveSlot2 = 93,
DefensiveSlot3 = 94,
DefensiveSlot4 = 95,
WeaponSlot1 = 96,
WeaponSlot2 = 97,
WeaponSlot3 = 98,
WeaponSlot4 = 99,
}
public struct EquipmentSlot
@@ -761,7 +755,7 @@ namespace Framework.Constants
BnetAccountUntilEquipped = 9,
}
public enum ItemClass : sbyte
public enum ItemClass : int
{
None = -1,
Consumable = 0,
@@ -1399,6 +1393,8 @@ namespace Framework.Constants
BankNotAccessible = 128,// This Character Does Not Have Access To This Bank.
CantTradeAccountItem = 129,// You Can't Trade An Item From The Warband Bank.
AccountMoneyLocked = 130,// You cannot withdraw or deposit gold from the warband bank currently; please try again later.
CharacterBankNotAccessible = 131,// This character does not have access to this bank.
CharacterBankNotConverted = 132,// Your character's bank has not been converted. Please try again later.
}
public enum BankType
@@ -1531,6 +1527,9 @@ namespace Framework.Constants
PriorityJunk = 0x10,
PriorityQuestItems = 0x20,
ExcludeJunkSell = 0x40,
PriorityReagents = 0x80,
ExpansionCurrent = 0x100,
ExpansionLegacy = 0x200,
}
public enum LootStoreItemType
File diff suppressed because it is too large Load Diff
+8 -5
View File
@@ -532,7 +532,10 @@ namespace Framework.Constants
AccountSecured = 0x1000, // Script_IsAccountSecured
OverrideTransportServerTime = 0x8000,
MentorRestricted = 0x20000,
WeeklyRewardAvailable = 0x40000
HasAccountBankLock = 0x40000,
CharacterBankDisabled = 0x80000,
CharacterBankConversionFailed = 0x100000,
AccountBankDisabled = 0x200000,
}
public enum PlayerFieldByte2Flags
@@ -592,14 +595,14 @@ namespace Framework.Constants
// first slot for item stored (in any way in player items data)
Start = 0,
// last+1 slot for item stored (in any way in player items data)
End = 232,
End = 105,
Count = (End - Start)
}
enum AccountBankBagSlots
public enum AccountBankBagSlots
{
Start = 227,
End = 232
Start = 100,
End = 105
}
public enum PlayerTitle : ulong
File diff suppressed because it is too large Load Diff
@@ -651,6 +651,9 @@ namespace Framework.Constants
Unk641 = 641,
Unk642 = 642,
ModRangedAttackSpeedFlat = 643,
Unk644 = 644,
Unk645 = 645,
Total
}
@@ -2671,6 +2671,10 @@ namespace Framework.Constants
UiAction = 339,
Unk340 = 340,
LearnWarbanScene = 341,
Unk342 = 342,
Unk343 = 343,
Unk344 = 344, // some kind of teleport
AssistAction = 345, // MiscValue[0] = AssistActionType, MiscValue[1] = ID, depends on type
TotalSpellEffects
}
+2 -2
View File
@@ -37,10 +37,10 @@ namespace Framework.Database
fileName = @"/sql/base/characters_database.sql";
break;
case "WorldDatabase":
fileName = @"/sql/TDB_full_world_1115.25051_2025_05_31.sql";
fileName = @"/sql/TDB_full_world_1117.25071_2025_07_21.sql";
break;
case "HotfixDatabase":
fileName = @"/sql/TDB_full_hotfixes_1115.25051_2025_05_31.sql";
fileName = @"/sql/TDB_full_hotfixes_1117.25071_2025_07_21.sql";
break;
}
@@ -73,7 +73,7 @@ namespace Framework.Database
PrepareStatement(CharStatements.INS_BATTLEGROUND_RANDOM, "INSERT INTO character_battleground_random (guid) VALUES (?)");
PrepareStatement(CharStatements.SEL_CHARACTER, "SELECT c.guid, account, name, race, class, gender, level, xp, money, inventorySlots, inventoryBagFlags, bagSlotFlags1, bagSlotFlags2, bagSlotFlags3, bagSlotFlags4, bagSlotFlags5, " +
"bankSlots, bankBagFlags, bankBagSlotFlags1, bankBagSlotFlags2, bankBagSlotFlags3, bankBagSlotFlags4, bankBagSlotFlags5, bankBagSlotFlags6, bankBagSlotFlags7, restState, playerFlags, playerFlagsEx, " +
"bankSlots, bankTabs, bankBagFlags, restState, playerFlags, playerFlagsEx, " +
"position_x, position_y, position_z, map, orientation, taximask, createTime, createMode, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, " +
"resettalents_time, primarySpecialization, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, summonedPetNumber, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, " +
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " +
@@ -451,14 +451,14 @@ namespace Framework.Database
// Player saving
PrepareStatement(CharStatements.INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, inventorySlots, inventoryBagFlags, bagSlotFlags1, bagSlotFlags2, bagSlotFlags3, bagSlotFlags4, bagSlotFlags5, " +
"bankSlots, bankBagFlags, bankBagSlotFlags1, bankBagSlotFlags2, bankBagSlotFlags3, bankBagSlotFlags4, bankBagSlotFlags5, bankBagSlotFlags6, bankBagSlotFlags7, restState, playerFlags, playerFlagsEx, " +
"bankSlots, bankTabs, bankBagFlags, restState, playerFlags, playerFlagsEx, " +
"map, instance_id, dungeonDifficulty, raidDifficulty, legacyRaidDifficulty, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, " +
"taximask, createTime, createMode, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, primarySpecialization, " +
"extra_flags, summonedPetNumber, at_login, death_expire_time, taxi_path, totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, " +
"power4, power5, power6, power7, power8, power9, power10, latency, activeTalentGroup, lootSpecId, exploredZones, equipmentCache, knownTitles, actionBars, lastLoginBuild) VALUES " +
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
PrepareStatement(CharStatements.UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,inventorySlots=?,inventoryBagFlags=?,bagSlotFlags1=?,bagSlotFlags2=?,bagSlotFlags3=?,bagSlotFlags4=?,bagSlotFlags5=?," +
"bankSlots=?,bankBagFlags=?,bankBagSlotFlags1=?,bankBagSlotFlags2=?,bankBagSlotFlags3=?,bankBagSlotFlags4=?,bankBagSlotFlags5=?,bankBagSlotFlags6=?,bankBagSlotFlags7=?,restState=?,playerFlags=?,playerFlagsEx=?," +
"bankSlots=?,bankTabs=?,bankBagFlags=?,restState=?,playerFlags=?,playerFlagsEx=?," +
"map=?,instance_id=?,dungeonDifficulty=?,raidDifficulty=?,legacyRaidDifficulty=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?," +
"logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,numRespecs=?,primarySpecialization=?,extra_flags=?,summonedPetNumber=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?," +
"totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?," +
@@ -654,12 +654,6 @@ namespace Framework.Database
PrepareStatement(CharStatements.DEL_CHAR_TRAIT_CONFIGS, "DELETE FROM character_trait_config WHERE guid = ? AND traitConfigId = ?");
PrepareStatement(CharStatements.DEL_CHAR_TRAIT_CONFIGS_BY_CHAR, "DELETE FROM character_trait_config WHERE guid = ?");
// Void Storage
PrepareStatement(CharStatements.SEL_CHAR_VOID_STORAGE, "SELECT itemId, itemEntry, slot, creatorGuid, randomBonusListId, fixedScalingLevel, artifactKnowledgeLevel, context, bonusListIDs FROM character_void_storage WHERE playerGuid = ?");
PrepareStatement(CharStatements.REP_CHAR_VOID_STORAGE_ITEM, "REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomBonusListId, fixedScalingLevel, artifactKnowledgeLevel, context, bonusListIDs) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
PrepareStatement(CharStatements.DEL_CHAR_VOID_STORAGE_ITEM_BY_CHAR_GUID, "DELETE FROM character_void_storage WHERE playerGuid = ?");
PrepareStatement(CharStatements.DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT, "DELETE FROM character_void_storage WHERE slot = ? AND playerGuid = ?");
// CompactUnitFrame profiles
PrepareStatement(CharStatements.SEL_CHAR_CUF_PROFILES, "SELECT id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, topPoint, bottomPoint, leftPoint, topOffset, bottomOffset, leftOffset FROM character_cuf_profiles WHERE guid = ?");
PrepareStatement(CharStatements.REP_CHAR_CUF_PROFILES, "REPLACE INTO character_cuf_profiles (guid, id, name, frameHeight, frameWidth, sortBy, healthText, boolOptions, topPoint, bottomPoint, leftPoint, topOffset, bottomOffset, leftOffset) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
@@ -769,11 +763,17 @@ namespace Framework.Database
PrepareStatement(CharStatements.INS_INSTANCE, "INSERT INTO instance (instanceId, data, completedEncountersMask, entranceWorldSafeLocId) VALUES (?, ?, ?, ?)");
PrepareStatement(CharStatements.SEL_PLAYER_DATA_ELEMENTS_CHARACTER, "SELECT playerDataElementCharacterId, floatValue, int64Value FROM character_player_data_element WHERE characterGuid = ?");
PrepareStatement(CharStatements.DEL_PLAYER_DATA_ELEMENTS_CHARACTER_BY_GUID, "DELETE FROM character_player_data_element WHERE characterGuid = ?");
PrepareStatement(CharStatements.DEL_PLAYER_DATA_ELEMENTS_CHARACTER, "DELETE FROM character_player_data_element WHERE characterGuid = ? AND playerDataElementCharacterId = ?");
PrepareStatement(CharStatements.INS_PLAYER_DATA_ELEMENTS_CHARACTER, "INSERT INTO character_player_data_element (characterGuid, playerDataElementCharacterId, floatValue, int64Value) VALUES (?, ?, ?, ?)");
PrepareStatement(CharStatements.SEL_PLAYER_DATA_FLAGS_CHARACTER, "SELECT storageIndex, mask FROM character_player_data_flag WHERE characterGuid = ?");
PrepareStatement(CharStatements.DEL_PLAYER_DATA_FLAGS_CHARACTER_BY_GUID, "DELETE FROM character_player_data_flag WHERE characterGuid = ?");
PrepareStatement(CharStatements.DEL_PLAYER_DATA_FLAGS_CHARACTER, "DELETE FROM character_player_data_flag WHERE characterGuid = ? AND storageIndex = ?");
PrepareStatement(CharStatements.INS_PLAYER_DATA_FLAGS_CHARACTER, "INSERT INTO character_player_data_flag (characterGuid, storageIndex, mask) VALUES (?, ?, ?)");
PrepareStatement(CharStatements.SEL_CHARACTER_BANK_TAB_SETTINGS, "SELECT tabId, name, icon, description, depositFlags FROM character_bank_tab_settings WHERE characterGuid = ?");
PrepareStatement(CharStatements.DEL_CHARACTER_BANK_TAB_SETTINGS, "DELETE FROM character_bank_tab_settings WHERE characterGuid = ?");
PrepareStatement(CharStatements.INS_CHARACTER_BANK_TAB_SETTINGS, "INSERT INTO character_bank_tab_settings (characterGuid, tabId, name, icon, description, depositFlags) VALUES (?, ?, ?, ?, ?, ?)");
}
}
@@ -1301,11 +1301,6 @@ namespace Framework.Database
DEL_CHAR_TRAIT_CONFIGS,
DEL_CHAR_TRAIT_CONFIGS_BY_CHAR,
SEL_CHAR_VOID_STORAGE,
REP_CHAR_VOID_STORAGE_ITEM,
DEL_CHAR_VOID_STORAGE_ITEM_BY_CHAR_GUID,
DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT,
SEL_CHAR_CUF_PROFILES,
REP_CHAR_CUF_PROFILES,
DEL_CHAR_CUF_PROFILES_BY_ID,
@@ -1403,12 +1398,18 @@ namespace Framework.Database
INS_INSTANCE,
SEL_PLAYER_DATA_ELEMENTS_CHARACTER,
DEL_PLAYER_DATA_ELEMENTS_CHARACTER_BY_GUID,
DEL_PLAYER_DATA_ELEMENTS_CHARACTER,
INS_PLAYER_DATA_ELEMENTS_CHARACTER,
SEL_PLAYER_DATA_FLAGS_CHARACTER,
DEL_PLAYER_DATA_FLAGS_CHARACTER_BY_GUID,
DEL_PLAYER_DATA_FLAGS_CHARACTER,
INS_PLAYER_DATA_FLAGS_CHARACTER,
SEL_CHARACTER_BANK_TAB_SETTINGS,
DEL_CHARACTER_BANK_TAB_SETTINGS,
INS_CHARACTER_BANK_TAB_SETTINGS,
MAX_CHARACTERDATABASE_STATEMENTS
}
}
@@ -164,8 +164,9 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_AZERITE_UNLOCK_MAPPING, "SELECT ID, ItemLevel, ItemBonusListHead, ItemBonusListShoulders, ItemBonusListChest, " +
"AzeriteUnlockMappingSetID FROM azerite_unlock_mapping WHERE (`VerifiedBuild` > 0) = ?");
// BankBagSlotPrices.db2
PrepareStatement(HotfixStatements.SEL_BANK_BAG_SLOT_PRICES, "SELECT ID, Cost FROM bank_bag_slot_prices WHERE (`VerifiedBuild` > 0) = ?");
// BankTab.db2
PrepareStatement(HotfixStatements.SEL_BANK_TAB, "SELECT ID, Cost, BankType, OrderIndex, PlayerConditionID, PurchasePromptTitle, PurchasePromptBody, " +
"PurchasePromptConfirmation, TabCleanupConfirmation, TabNameEditBoxHeader FROM bank_tab WHERE (`VerifiedBuild` > 0) = ?");
// BannedAddons.db2
PrepareStatement(HotfixStatements.SEL_BANNED_ADDONS, "SELECT ID, Name, Version, Flags FROM banned_addons WHERE (`VerifiedBuild` > 0) = ?");
@@ -222,8 +223,8 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_CFG_CATEGORIES_LOCALE, "SELECT ID, Name_lang FROM cfg_categories_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
// CfgRegions.db2
PrepareStatement(HotfixStatements.SEL_CFG_REGIONS, "SELECT ID, Tag, RegionID, Raidorigin, RegionGroupMask, ChallengeOrigin FROM cfg_regions" +
" WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_CFG_REGIONS, "SELECT ID, Tag, RegionID, Raidorigin, RegionGroupMask, ChallengeOrigin, TimeEventRegionGroupID" +
" FROM cfg_regions WHERE (`VerifiedBuild` > 0) = ?");
// ChallengeModeItemBonusOverride.db2
PrepareStatement(HotfixStatements.SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE, "SELECT ID, ItemBonusTreeGroupID, DstItemBonusTreeID, Value, " +
@@ -259,12 +260,12 @@ namespace Framework.Database
// ChrClasses.db2
PrepareStatement(HotfixStatements.SEL_CHR_CLASSES, "SELECT Name, Filename, NameMale, NameFemale, PetNameToken, Description, RoleInfoString, DisabledString, " +
"HyphenatedNameMale, HyphenatedNameFemale, CreateScreenFileDataID, SelectScreenFileDataID, IconFileDataID, LowResScreenFileDataID, Flags, " +
"SpellTextureBlobFileDataID, ArmorTypeMask, CharStartKitUnknown901, MaleCharacterCreationVisualFallback, " +
"StartingLevel, SpellTextureBlobFileDataID, ArmorTypeMask, CharStartKitUnknown901, MaleCharacterCreationVisualFallback, " +
"MaleCharacterCreationIdleVisualFallback, FemaleCharacterCreationVisualFallback, FemaleCharacterCreationIdleVisualFallback, " +
"CharacterCreationIdleGroundVisualFallback, CharacterCreationGroundVisualFallback, AlteredFormCharacterCreationIdleVisualFallback, " +
"CharacterCreationAnimLoopWaitTimeMsFallback, CinematicSequenceID, DefaultSpec, ID, PrimaryStatPriority, DisplayPower, " +
"RangedAttackPowerPerAgility, AttackPowerPerAgility, AttackPowerPerStrength, SpellClassSet, ClassColorR, ClassColorG, ClassColorB, RolesMask" +
" FROM chr_classes WHERE (`VerifiedBuild` > 0) = ?");
"CharacterCreationAnimLoopWaitTimeMsFallback, CinematicSequenceID, DefaultSpec, ID, HasStrengthBonus, PrimaryStatPriority, DisplayPower, " +
"RangedAttackPowerPerAgility, AttackPowerPerAgility, AttackPowerPerStrength, SpellClassSet, ClassColorR, ClassColorG, ClassColorB, RolesMask, " +
"DamageBonusStat, HasRelicSlot FROM chr_classes WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_CHR_CLASSES_LOCALE, "SELECT ID, Name_lang, NameMale_lang, NameFemale_lang, Description_lang, RoleInfoString_lang, " +
"DisabledString_lang, HyphenatedNameMale_lang, HyphenatedNameFemale_lang FROM chr_classes_locale WHERE (`VerifiedBuild` > 0) = ?" +
" AND locale = ?");
@@ -391,7 +392,7 @@ namespace Framework.Database
// CreatureFamily.db2
PrepareStatement(HotfixStatements.SEL_CREATURE_FAMILY, "SELECT ID, Name, MinScale, MinScaleLevel, MaxScale, MaxScaleLevel, PetFoodMask, PetTalentType, " +
"IconFileID, SkillLine1, SkillLine2 FROM creature_family WHERE (`VerifiedBuild` > 0) = ?");
"CategoryEnumID, IconFileID, SkillLine1, SkillLine2 FROM creature_family WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_CREATURE_FAMILY_LOCALE, "SELECT ID, Name_lang FROM creature_family_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
// CreatureLabel.db2
@@ -482,7 +483,7 @@ namespace Framework.Database
// ExpectedStat.db2
PrepareStatement(HotfixStatements.SEL_EXPECTED_STAT, "SELECT ID, ExpansionID, CreatureHealth, PlayerHealth, CreatureAutoAttackDps, CreatureArmor, " +
"PlayerMana, PlayerPrimaryStat, PlayerSecondaryStat, ArmorConstant, CreatureSpellDamage, Lvl FROM expected_stat" +
"PlayerMana, PlayerPrimaryStat, PlayerSecondaryStat, ArmorConstant, CreatureSpellDamage, ContentSetID, Lvl FROM expected_stat" +
" WHERE (`VerifiedBuild` > 0) = ?");
// ExpectedStatMod.db2
@@ -818,7 +819,7 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_ITEM_SET_LOCALE, "SELECT ID, Name_lang FROM item_set_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
// ItemSetSpell.db2
PrepareStatement(HotfixStatements.SEL_ITEM_SET_SPELL, "SELECT ID, ChrSpecID, SpellID, Threshold, ItemSetID FROM item_set_spell" +
PrepareStatement(HotfixStatements.SEL_ITEM_SET_SPELL, "SELECT ID, ChrSpecID, SpellID, TraitSubTreeID, Threshold, ItemSetID FROM item_set_spell" +
" WHERE (`VerifiedBuild` > 0) = ?");
// ItemSparse.db2
@@ -937,7 +938,9 @@ namespace Framework.Database
// MapChallengeMode.db2
PrepareStatement(HotfixStatements.SEL_MAP_CHALLENGE_MODE, "SELECT Name, ID, MapID, Flags, ExpansionLevel, RequiredWorldStateID, CriteriaCount1, " +
"CriteriaCount2, CriteriaCount3 FROM map_challenge_mode WHERE (`VerifiedBuild` > 0) = ?");
"CriteriaCount2, CriteriaCount3, FirstRewardQuestID1, FirstRewardQuestID2, FirstRewardQuestID3, FirstRewardQuestID4, FirstRewardQuestID5, " +
"FirstRewardQuestID6, RewardQuestID1, RewardQuestID2, RewardQuestID3, RewardQuestID4, RewardQuestID5, RewardQuestID6 FROM map_challenge_mode" +
" WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_MAP_CHALLENGE_MODE_LOCALE, "SELECT ID, Name_lang FROM map_challenge_mode_locale WHERE (`VerifiedBuild` > 0) = ?" +
" AND locale = ?");
@@ -1407,8 +1410,9 @@ namespace Framework.Database
" FROM spell_visual_effect_name WHERE (`VerifiedBuild` > 0) = ?");
// SpellVisualKit.db2
PrepareStatement(HotfixStatements.SEL_SPELL_VISUAL_KIT, "SELECT ID, ClutterLevel, FallbackSpellVisualKitId, DelayMin, DelayMax, Flags1, Flags2" +
" FROM spell_visual_kit WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_SPELL_VISUAL_KIT, "SELECT ID, ClutterLevel, FallbackSpellVisualKitId, DelayMin, DelayMax, " +
"MinimumSpellVisualDensityFilterType, MinimumSpellVisualDensityFilterParam, ReducedSpellVisualDensityFilterType, " +
"ReducedSpellVisualDensityFilterParam, Flags1, Flags2 FROM spell_visual_kit WHERE (`VerifiedBuild` > 0) = ?");
// SpellVisualMissile.db2
PrepareStatement(HotfixStatements.SEL_SPELL_VISUAL_MISSILE, "SELECT CastOffset1, CastOffset2, CastOffset3, ImpactOffset1, ImpactOffset2, ImpactOffset3, ID, " +
@@ -1648,11 +1652,10 @@ namespace Framework.Database
PrepareStatement(HotfixStatements.SEL_VIGNETTE_LOCALE, "SELECT ID, Name_lang FROM vignette_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
// WarbandScene.db2
PrepareStatement(HotfixStatements.SEL_WARBAND_SCENE, "SELECT Name, Description, Source, PositionX, PositionY, PositionZ, LookAtX, LookAtY, LookAtZ, ID, " +
"MapID, Fov, TimeOfDay, Flags, SoundAmbienceID, Quality, TextureKit, DefaultScenePriority, SourceType FROM warband_scene" +
" WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_WARBAND_SCENE_LOCALE, "SELECT ID, Name_lang, Description_lang, Source_lang FROM warband_scene_locale" +
" WHERE (`VerifiedBuild` > 0) = ? AND locale = ?");
PrepareStatement(HotfixStatements.SEL_WARBAND_SCENE, "SELECT Name, Description, PositionX, PositionY, PositionZ, LookAtX, LookAtY, LookAtZ, ID, MapID, Fov, " +
"TimeOfDay, Flags, SoundAmbienceID, Quality, TextureKit, DefaultScenePriority FROM warband_scene WHERE (`VerifiedBuild` > 0) = ?");
PrepareStatement(HotfixStatements.SEL_WARBAND_SCENE_LOCALE, "SELECT ID, Name_lang, Description_lang FROM warband_scene_locale WHERE (`VerifiedBuild` > 0) = ?" +
" AND locale = ?");
// WmoAreaTable.db2
PrepareStatement(HotfixStatements.SEL_WMO_AREA_TABLE, "SELECT AreaName, ID, WmoID, NameSetID, WmoGroupID, SoundProviderPref, SoundProviderPrefUnderwater, " +
@@ -1759,7 +1762,7 @@ namespace Framework.Database
SEL_AZERITE_UNLOCK_MAPPING,
SEL_BANK_BAG_SLOT_PRICES,
SEL_BANK_TAB,
SEL_BANNED_ADDONS,
+19 -1
View File
@@ -379,6 +379,19 @@ namespace Game.Achievements
case CriteriaType.GuildAttainedLevel:
SetCriteriaProgress(criteria, miscValue1, referencePlayer);
break;
case CriteriaType.BankTabPurchased:
switch ((BankType)criteria.Entry.Asset)
{
case BankType.Character:
SetCriteriaProgress(criteria, referencePlayer.GetCharacterBankTabCount(), referencePlayer);
break;
case BankType.Account:
SetCriteriaProgress(criteria, referencePlayer.GetAccountBankTabCount(), referencePlayer);
break;
default:
break;
}
break;
// FIXME: not triggered in code as result, need to implement
case CriteriaType.RunInstance:
case CriteriaType.EarnTeamArenaRating:
@@ -825,6 +838,7 @@ namespace Game.Achievements
case CriteriaType.SellItemsToVendors:
case CriteriaType.GainLevels:
case CriteriaType.ReachRenownLevel:
case CriteriaType.BankTabPurchased:
case CriteriaType.LearnTaxiNode:
return progress.Counter >= requiredAmount;
case CriteriaType.EarnAchievement:
@@ -1246,6 +1260,10 @@ namespace Game.Achievements
if (!referencePlayer.IsMaxLevel())
return false;
break;
case CriteriaType.BankTabPurchased:
if (miscValue1 != 0 /*allow any at login*/ && miscValue1 != criteria.Entry.Asset)
return false;
break;
case CriteriaType.LearnTaxiNode:
if (miscValue1 != criteria.Entry.Asset)
return false;
@@ -4180,7 +4198,7 @@ namespace Game.Achievements
//CriteriaType.MythicPlusRatingAttained, /*NYI*/
//CriteriaType.MythicPlusDisplaySeasonEnded, /*NYI*/
//CriteriaType.CompleteTrackingQuest, /*NYI*/
//CriteriaType.WarbandBankTabPurchased, /*NYI*/
CriteriaType.BankTabPurchased,
CriteriaType.LearnTaxiNode,
CriteriaType.EarnAchievementPoints,
CriteriaType.BattlePetAchievementPointsEarned,
@@ -126,8 +126,6 @@ namespace Game.Chat.Commands
itemPos = "[equipped]";
else if (Player.IsInventoryPos((byte)itemBag, itemSlot))
itemPos = "[in inventory]";
else if (Player.IsReagentBankPos((byte)itemBag, itemSlot))
itemPos = "[in reagent bank]";
else if (Player.IsBankPos((byte)itemBag, itemSlot))
itemPos = "[in bank]";
else
@@ -227,7 +227,7 @@ namespace Game.DataStorage
}
// 0 1 2 3 4 5 6 7 8
SQLResult circularMovementInfos = DB.World.Query("SELECT AreaTriggerCreatePropertiesId, IsCustom, StartDelay, CircleRadius, BlendFromRadius, InitialAngle, ZOffset, CounterClockwise, CanLoop FROM `areatrigger_create_properties_orbit`");
SQLResult circularMovementInfos = DB.World.Query("SELECT AreaTriggerCreatePropertiesId, IsCustom, ExtraTimeForBlending, CircleRadius, BlendFromRadius, InitialAngle, ZOffset, CounterClockwise, CanLoop FROM `areatrigger_create_properties_orbit`");
if (!circularMovementInfos.IsEmpty())
{
do
@@ -243,7 +243,7 @@ namespace Game.DataStorage
AreaTriggerOrbitInfo orbitInfo = new();
orbitInfo.StartDelay = circularMovementInfos.Read<uint>(2);
orbitInfo.ExtraTimeForBlending = circularMovementInfos.Read<int>(2);
float ValidateAndSetFloat(float value)
{
+11 -9
View File
@@ -83,7 +83,7 @@ namespace Game.DataStorage
AzeriteTierUnlockStorage = ReadDB2<AzeriteTierUnlockRecord>("AzeriteTierUnlock.db2", HotfixStatements.SEL_AZERITE_TIER_UNLOCK);
AzeriteTierUnlockSetStorage = ReadDB2<AzeriteTierUnlockSetRecord>("AzeriteTierUnlockSet.db2", HotfixStatements.SEL_AZERITE_TIER_UNLOCK_SET);
AzeriteUnlockMappingStorage = ReadDB2<AzeriteUnlockMappingRecord>("AzeriteUnlockMapping.db2", HotfixStatements.SEL_AZERITE_UNLOCK_MAPPING);
BankBagSlotPricesStorage = ReadDB2<BankBagSlotPricesRecord>("BankBagSlotPrices.db2", HotfixStatements.SEL_BANK_BAG_SLOT_PRICES);
BankTabStorage = ReadDB2<BankTabRecord>("BankTab.db2", HotfixStatements.SEL_BANK_TAB);
BannedAddOnsStorage = ReadDB2<BannedAddonsRecord>("BannedAddons.db2", HotfixStatements.SEL_BANNED_ADDONS);
BarberShopStyleStorage = ReadDB2<BarberShopStyleRecord>("BarberShopStyle.db2", HotfixStatements.SEL_BARBER_SHOP_STYLE, HotfixStatements.SEL_BARBER_SHOP_STYLE_LOCALE);
BattlePetBreedQualityStorage = ReadDB2<BattlePetBreedQualityRecord>("BattlePetBreedQuality.db2", HotfixStatements.SEL_BATTLE_PET_BREED_QUALITY);
@@ -403,14 +403,16 @@ namespace Game.DataStorage
WorldStateExpressionStorage = ReadDB2<WorldStateExpressionRecord>("WorldStateExpression.db2", HotfixStatements.SEL_WORLD_STATE_EXPRESSION);
// Check loaded DB2 files proper version
if (!AreaTableStorage.ContainsKey(16108) || // last area added in 11.0.7 (58162)
!CharTitlesStorage.ContainsKey(876) || // last char title added in 11.0.7 (58162)
if (!AreaTableStorage.ContainsKey(16579) || // last area added in 11.2.0 (62213)
!CharTitlesStorage.ContainsKey(937) || // last char title added in 11.2.0 (62213)
!FlightCapabilityStorage.ContainsKey(1) || // default flight capability (required)
!GemPropertiesStorage.ContainsKey(4266) || // last gem property added in 11.0.7 (58162)
!ItemStorage.ContainsKey(235551) || // last item added in 11.0.7 (58162)
!ItemExtendedCostStorage.ContainsKey(9918) || // last item extended cost added in 11.0.7 (58162)
!MapStorage.ContainsKey(2829) || // last map added in 11.0.7 (58162)
!SpellNameStorage.ContainsKey(1218101)) // last spell added in 11.0.7 (58162)
!GemPropertiesStorage.ContainsKey(4287) || // last gem property added in 11.2.0 (62213)
!ItemStorage.ContainsKey(252009) || // last item added in 11.2.0 (62213)
!ItemSparseStorage.ContainsKey(208392) ||
!ItemSparseStorage.ContainsKey(242709) ||
!ItemExtendedCostStorage.ContainsKey(10637) || // last item extended cost added in 11.2.0 (62213)
!MapStorage.ContainsKey(2951) || // last map added in 11.2.0 (62213)
!SpellNameStorage.ContainsKey(1254022)) // last spell added in 11.2.0 (62213)
{
Log.outFatal(LogFilter.ServerLoading, "You have _outdated_ DB2 files. Please extract correct versions from current using client.");
Environment.Exit(1);
@@ -487,7 +489,7 @@ namespace Game.DataStorage
public static DB6Storage<AzeriteTierUnlockRecord> AzeriteTierUnlockStorage;
public static DB6Storage<AzeriteTierUnlockSetRecord> AzeriteTierUnlockSetStorage;
public static DB6Storage<AzeriteUnlockMappingRecord> AzeriteUnlockMappingStorage;
public static DB6Storage<BankBagSlotPricesRecord> BankBagSlotPricesStorage;
public static DB6Storage<BankTabRecord> BankTabStorage;
public static DB6Storage<BannedAddonsRecord> BannedAddOnsStorage;
public static DB6Storage<BarberShopStyleRecord> BarberShopStyleStorage;
public static DB6Storage<BattlePetBreedQualityRecord> BattlePetBreedQualityStorage;
+1 -1
View File
@@ -84,7 +84,7 @@ namespace Game.DataStorage
{
public uint Id;
public ushort Fallback;
public byte BehaviorTier;
public sbyte BehaviorTier;
public short BehaviorID;
public int[] Flags = new int[2];
}
+12 -4
View File
@@ -5,10 +5,18 @@ using Framework.Constants;
namespace Game.DataStorage
{
public sealed class BankBagSlotPricesRecord
public sealed class BankTabRecord
{
public uint Id;
public uint Cost;
public ulong Cost;
public byte BankType;
public sbyte OrderIndex;
public int PlayerConditionID;
public int PurchasePromptTitle;
public int PurchasePromptBody;
public int PurchasePromptConfirmation;
public int TabCleanupConfirmation;
public int TabNameEditBoxHeader;
}
public sealed class BannedAddonsRecord
@@ -16,7 +24,7 @@ namespace Game.DataStorage
public uint Id;
public string Name;
public string Version;
public byte Flags;
public int Flags;
}
public sealed class BarberShopStyleRecord
@@ -63,7 +71,7 @@ namespace Game.DataStorage
public int CovenantID;
public bool HasFlag(BattlePetSpeciesFlags battlePetSpeciesFlags) { return (Flags & (int)battlePetSpeciesFlags) != 0; }
}
}
public sealed class BattlePetSpeciesStateRecord
{
+7 -1
View File
@@ -29,6 +29,7 @@ namespace Game.DataStorage
public uint Raidorigin; // Date of first raid reset, all other resets are calculated as this date plus interval
public byte RegionGroupMask;
public uint ChallengeOrigin;
public int TimeEventRegionGroupID;
}
public sealed class ChallengeModeItemBonusOverrideRecord
@@ -56,7 +57,7 @@ namespace Game.DataStorage
public LocalizedString Name;
public LocalizedString Name1;
public ushort MaskID;
public sbyte Flags;
public int Flags;
}
public sealed class CharacterLoadoutRecord
@@ -115,6 +116,7 @@ namespace Game.DataStorage
public uint IconFileDataID;
public uint LowResScreenFileDataID;
public int Flags;
public int StartingLevel;
public uint SpellTextureBlobFileDataID;
public uint ArmorTypeMask;
public int CharStartKitUnknown901;
@@ -129,6 +131,7 @@ namespace Game.DataStorage
public ushort CinematicSequenceID;
public ushort DefaultSpec;
public uint Id;
public byte HasStrengthBonus;
public sbyte PrimaryStatPriority;
public PowerType DisplayPower;
public byte RangedAttackPowerPerAgility;
@@ -139,6 +142,8 @@ namespace Game.DataStorage
public byte ClassColorG;
public byte ClassColorB;
public byte RolesMask;
public byte DamageBonusStat;
public byte HasRelicSlot;
}
public sealed class ChrClassesXPowerTypesRecord
@@ -506,6 +511,7 @@ namespace Game.DataStorage
public sbyte MaxScaleLevel;
public ushort PetFoodMask;
public sbyte PetTalentType;
public int CategoryEnumID;
public int IconFileID;
public short[] SkillLine = new short[2];
}
@@ -47,6 +47,7 @@ namespace Game.DataStorage
public float PlayerSecondaryStat;
public float ArmorConstant;
public float CreatureSpellDamage;
public int ContentSetID;
public uint Lvl;
}
@@ -349,6 +349,7 @@ namespace Game.DataStorage
public uint Id;
public ushort ChrSpecID;
public uint SpellID;
public ushort TraitSubTreeID;
public byte Threshold;
public uint ItemSetID;
}
+4 -1
View File
@@ -87,6 +87,7 @@ namespace Game.DataStorage
case 1643:
case 2222:
case 2444:
case 2601:
return true;
default:
return false;
@@ -114,10 +115,12 @@ namespace Game.DataStorage
public LocalizedString Name;
public uint Id;
public ushort MapID;
public byte Flags;
public int Flags;
public uint ExpansionLevel;
public int RequiredWorldStateID; // maybe?
public short[] CriteriaCount = new short[3];
public int[] FirstRewardQuestID = new int[6];
public int[] RewardQuestID = new int[6];
}
public sealed class MapDifficultyRecord
+7 -3
View File
@@ -258,8 +258,8 @@ namespace Game.DataStorage
public uint Id;
public string Name;
public int Flags;
public byte UsesPerWeek;
public byte MaxCharges;
public int UsesPerWeek;
public int MaxCharges;
public int ChargeRecoveryTime;
public int TypeMask;
@@ -346,7 +346,7 @@ namespace Game.DataStorage
{
public uint Id;
public uint SpellID;
public sbyte EquippedItemClass;
public int EquippedItemClass;
public int EquippedItemInvTypes;
public int EquippedItemSubclass;
}
@@ -658,6 +658,10 @@ namespace Game.DataStorage
public int FallbackSpellVisualKitId;
public ushort DelayMin;
public ushort DelayMax;
public int MinimumSpellVisualDensityFilterType;
public int MinimumSpellVisualDensityFilterParam;
public int ReducedSpellVisualDensityFilterType;
public int ReducedSpellVisualDensityFilterParam;
public int[] Flags = new int[2];
}
+1 -1
View File
@@ -109,7 +109,7 @@ namespace Game.DataStorage
public float RegenerationPeace;
public float RegenerationCombat;
public byte BarType;
public ushort Flags;
public int Flags;
public float StartInset;
public float EndInset;
public uint[] FileDataID = new uint[6];
@@ -10,7 +10,6 @@ namespace Game.DataStorage
{
public LocalizedString Name;
public LocalizedString Description;
public LocalizedString Source;
public Vector3 Position;
public Vector3 LookAt;
public uint Id;
@@ -22,7 +21,6 @@ namespace Game.DataStorage
public sbyte Quality;
public int TextureKit;
public int DefaultScenePriority;
public sbyte SourceType;
public WarbandSceneFlags GetFlags() { return (WarbandSceneFlags)Flags; }
}
+269 -190
View File
@@ -26,7 +26,6 @@ namespace Game.Entities
ObjectTypeId = TypeId.AreaTrigger;
m_updateFlag.Stationary = true;
m_updateFlag.AreaTrigger = true;
m_entityFragments.Add(EntityFragment.Tag_AreaTrigger, false);
@@ -119,7 +118,7 @@ namespace Game.Entities
SetObjectScale(1.0f);
SetDuration(duration);
_shape = GetCreateProperties().Shape;
SetShape(GetCreateProperties().Shape);
var areaTriggerData = m_values.ModifyValue(m_areaTriggerData);
if (caster != null)
@@ -176,6 +175,35 @@ namespace Game.Entities
if (GetCreateProperties() != null && GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.VisualAnimIsDecay))
SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.IsDecay), true);
AreaTriggerFieldFlags fieldFlags()
{
var flags = GetCreateProperties().Flags;
AreaTriggerFieldFlags fieldFlags = AreaTriggerFieldFlags.None;
if (flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAbsoluteOrientation))
fieldFlags |= AreaTriggerFieldFlags.AbsoluteOrientation;
if (flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasDynamicShape))
fieldFlags |= AreaTriggerFieldFlags.DynamicShape;
if (flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAttached))
fieldFlags |= AreaTriggerFieldFlags.Attached;
if (flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasFaceMovementDir))
fieldFlags |= AreaTriggerFieldFlags.FaceMovementDir;
if (flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasFollowsTerrain))
fieldFlags |= AreaTriggerFieldFlags.FollowsTerrain;
if (flags.HasFlag(AreaTriggerCreatePropertiesFlag.AlwaysExterior))
fieldFlags |= AreaTriggerFieldFlags.AlwaysExterior;
return fieldFlags;
}
;
ReplaceAllAreaTriggerFlags(fieldFlags());
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.MovementStartTime), GameTime.GetGameTimeMS());
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.CreationTime), GameTime.GetGameTimeMS());
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ScaleCurveId), GetCreateProperties().ScaleCurveId);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.FacingCurveId), GetCreateProperties().FacingCurveId);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.MorphCurveId), GetCreateProperties().MorphCurveId);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.MoveCurveId), GetCreateProperties().MoveCurveId);
if (caster != null)
PhasingHandler.InheritPhaseShift(this, caster);
else if (IsStaticSpawn() && spawnData != null)
@@ -184,7 +212,7 @@ namespace Game.Entities
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), spawnData.PhaseUseFlags, spawnData.PhaseId, spawnData.PhaseGroup);
}
if (target != null && GetCreateProperties() != null && GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAttached))
if (target != null && HasAreaTriggerFlag(AreaTriggerFieldFlags.Attached))
m_movementInfo.transport.guid = target.GetGUID();
if (!IsStaticSpawn())
@@ -195,7 +223,7 @@ namespace Game.Entities
if (GetCreateProperties().OrbitInfo != null)
{
AreaTriggerOrbitInfo orbit = GetCreateProperties().OrbitInfo;
if (target != null && GetCreateProperties() != null && GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAttached))
if (target != null && HasAreaTriggerFlag(AreaTriggerFieldFlags.Attached))
orbit.PathTarget = target.GetGUID();
else
orbit.Center = new(pos.posX, pos.posY, pos.posZ);
@@ -206,6 +234,10 @@ namespace Game.Entities
{
InitSplineOffsets(GetCreateProperties().SplinePoints);
}
else
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)AreaTriggerPathType.None);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.Facing), _stationaryPosition.GetOrientation());
// movement on transport of areatriggers on unit is handled by themself
ITransport transport = null;
@@ -280,7 +312,6 @@ namespace Game.Entities
public override void Update(uint diff)
{
base.Update(diff);
_timeSinceCreated += diff;
if (!IsStaticSpawn())
{
@@ -291,19 +322,18 @@ namespace Game.Entities
}
else if (HasOrbit())
{
UpdateOrbitPosition(diff);
UpdateOrbitPosition();
}
else if (GetCreateProperties() != null && GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAttached))
else if (HasAreaTriggerFlag(AreaTriggerFieldFlags.Attached))
{
Unit target = GetTarget();
if (target != null)
{
float orientation = 0.0f;
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.FacingCurveId != 0)
orientation = Global.DB2Mgr.GetCurveValueAt(createProperties.FacingCurveId, GetProgress());
if (m_areaTriggerData.FacingCurveId != 0)
orientation = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.FacingCurveId, GetProgress());
if (GetCreateProperties() == null || !GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAbsoluteOrientation))
if (!HasAreaTriggerFlag(AreaTriggerFieldFlags.AbsoluteOrientation))
orientation += target.GetOrientation();
GetMap().AreaTriggerRelocation(this, target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), orientation);
@@ -311,16 +341,15 @@ namespace Game.Entities
}
else if (HasSplines())
{
UpdateSplinePosition(diff);
UpdateSplinePosition(_spline);
}
else
{
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.FacingCurveId != 0)
if (m_areaTriggerData.FacingCurveId != 0)
{
float orientation = Global.DB2Mgr.GetCurveValueAt(createProperties.FacingCurveId, GetProgress());
if (GetCreateProperties() == null || !GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAbsoluteOrientation))
orientation += _stationaryPosition.GetOrientation();
float orientation = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.FacingCurveId, GetProgress());
if (!HasAreaTriggerFlag(AreaTriggerFieldFlags.AbsoluteOrientation))
orientation += m_areaTriggerData.Facing;
SetOrientation(orientation);
}
@@ -351,6 +380,14 @@ namespace Game.Entities
AddObjectToRemoveList();
}
uint GetTimeSinceCreated()
{
uint now = GameTime.GetGameTimeMS();
if (now >= m_areaTriggerData.CreationTime)
return now - m_areaTriggerData.CreationTime;
return 0;
}
void SetOverrideScaleCurve(float overrideScale)
{
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideScaleCurve), overrideScale);
@@ -435,12 +472,8 @@ namespace Game.Entities
float scale = 1.0f;
if (m_areaTriggerData.OverrideScaleCurve.GetValue().OverrideActive)
scale *= Math.Max(GetScaleCurveValue(m_areaTriggerData.OverrideScaleCurve, m_areaTriggerData.TimeToTargetScale), 0.000001f);
else
{
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.ScaleCurveId != 0)
scale *= Math.Max(Global.DB2Mgr.GetCurveValueAt(createProperties.ScaleCurveId, GetScaleCurveProgress(m_areaTriggerData.OverrideScaleCurve, m_areaTriggerData.TimeToTargetScale)), 0.000001f);
}
else if (m_areaTriggerData.ScaleCurveId != 0)
scale *= Math.Max(Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.ScaleCurveId, GetScaleCurveProgress(m_areaTriggerData.OverrideScaleCurve, m_areaTriggerData.TimeToTargetScale)), 0.000001f);
scale *= Math.Max(GetScaleCurveValue(m_areaTriggerData.ExtraScaleCurve, m_areaTriggerData.TimeToTargetExtraScale), 0.000001f);
@@ -583,29 +616,21 @@ namespace Game.Entities
{
List<Unit> targetList = new();
switch (_shape.TriggerType)
m_areaTriggerData.ShapeData.Visit(shape =>
{
case AreaTriggerShapeType.Sphere:
SearchUnitInSphere(targetList);
break;
case AreaTriggerShapeType.Box:
SearchUnitInBox(targetList);
break;
case AreaTriggerShapeType.Polygon:
SearchUnitInPolygon(targetList);
break;
case AreaTriggerShapeType.Cylinder:
SearchUnitInCylinder(targetList);
break;
case AreaTriggerShapeType.Disk:
SearchUnitInDisk(targetList);
break;
case AreaTriggerShapeType.BoundedPlane:
SearchUnitInBoundedPlane(targetList);
break;
default:
break;
}
if (shape is AreaTriggerSphere)
SearchUnitInSphere(shape, targetList);
else if (shape is AreaTriggerBox)
SearchUnitInBox(shape, targetList);
else if (shape is AreaTriggerPolygon)
SearchUnitInPolygon(shape, targetList);
else if (shape is AreaTriggerCylinder)
SearchUnitInCylinder(shape, targetList);
else if (shape is AreaTriggerDisk)
SearchUnitInDisk(shape, targetList);
else if (shape is AreaTriggerBoundedPlane)
SearchUnitInBoundedPlane(shape, targetList);
});
if (GetTemplate() != null)
{
@@ -681,32 +706,30 @@ namespace Game.Entities
}
}
void SearchUnitInSphere(List<Unit> targetList)
void SearchUnitInSphere(AreaTriggerSphere sphere, List<Unit> targetList)
{
float progress = GetProgress();
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MorphCurveId, progress);
if (m_areaTriggerData.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MorphCurveId, progress);
float scale = CalcCurrentScale();
float radius = MathFunctions.Lerp(_shape.SphereDatas.Radius, _shape.SphereDatas.RadiusTarget, progress) * scale;
float radius = MathFunctions.Lerp(sphere.Radius, sphere.RadiusTarget, progress) * scale;
SearchUnits(targetList, radius, true);
}
void SearchUnitInBox(List<Unit> targetList)
void SearchUnitInBox(AreaTriggerBox box, List<Unit> targetList)
{
float progress = GetProgress();
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MorphCurveId, progress);
if (m_areaTriggerData.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MorphCurveId, progress);
unsafe
{
float scale = CalcCurrentScale();
float extentsX = MathFunctions.Lerp(_shape.BoxDatas.Extents[0], _shape.BoxDatas.ExtentsTarget[0], progress) * scale;
float extentsY = MathFunctions.Lerp(_shape.BoxDatas.Extents[1], _shape.BoxDatas.ExtentsTarget[1], progress) * scale;
float extentsZ = MathFunctions.Lerp(_shape.BoxDatas.Extents[2], _shape.BoxDatas.ExtentsTarget[2], progress) * scale;
float extentsX = MathFunctions.Lerp(box.Extents.GetValue().X, box.ExtentsTarget.GetValue().X, progress) * scale;
float extentsY = MathFunctions.Lerp(box.Extents.GetValue().Y, box.ExtentsTarget.GetValue().Y, progress) * scale;
float extentsZ = MathFunctions.Lerp(box.Extents.GetValue().Z, box.ExtentsTarget.GetValue().Z, progress) * scale;
float radius = MathF.Sqrt(extentsX * extentsX + extentsY * extentsY);
SearchUnits(targetList, radius, false);
@@ -716,14 +739,13 @@ namespace Game.Entities
}
}
void SearchUnitInPolygon(List<Unit> targetList)
void SearchUnitInPolygon(AreaTriggerPolygon polygon, List<Unit> targetList)
{
float progress = GetProgress();
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MorphCurveId, progress);
if (m_areaTriggerData.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MorphCurveId, progress);
float height = MathFunctions.Lerp(_shape.PolygonDatas.Height, _shape.PolygonDatas.HeightTarget, progress);
float height = MathFunctions.Lerp(polygon.Height, polygon.HeightTarget, progress);
float minZ = GetPositionZ() - height;
float maxZ = GetPositionZ() + height;
@@ -732,17 +754,16 @@ namespace Game.Entities
targetList.RemoveAll(unit => unit.GetPositionZ() < minZ || unit.GetPositionZ() > maxZ || !unit.IsInPolygon2D(this, _polygonVertices));
}
void SearchUnitInCylinder(List<Unit> targetList)
void SearchUnitInCylinder(AreaTriggerCylinder cylinder, List<Unit> targetList)
{
float progress = GetProgress();
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MorphCurveId, progress);
if (m_areaTriggerData.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MorphCurveId, progress);
float scale = CalcCurrentScale();
float radius = MathFunctions.Lerp(_shape.CylinderDatas.Radius, _shape.CylinderDatas.RadiusTarget, progress) * scale;
float height = MathFunctions.Lerp(_shape.CylinderDatas.Height, _shape.CylinderDatas.HeightTarget, progress);
if (!m_areaTriggerData.HeightIgnoresScale)
float radius = MathFunctions.Lerp(cylinder.Radius, cylinder.RadiusTarget, progress) * scale;
float height = MathFunctions.Lerp(cylinder.Height, cylinder.HeightTarget, progress);
if (!HasAreaTriggerFlag(AreaTriggerFieldFlags.HeightIgnoresScale))
height *= scale;
float minZ = GetPositionZ() - height;
@@ -753,18 +774,17 @@ namespace Game.Entities
targetList.RemoveAll(unit => unit.GetPositionZ() < minZ || unit.GetPositionZ() > maxZ);
}
void SearchUnitInDisk(List<Unit> targetList)
void SearchUnitInDisk(AreaTriggerDisk disk, List<Unit> targetList)
{
float progress = GetProgress();
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MorphCurveId, progress);
if (m_areaTriggerData.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MorphCurveId, progress);
float scale = CalcCurrentScale();
float innerRadius = MathFunctions.Lerp(_shape.DiskDatas.InnerRadius, _shape.DiskDatas.InnerRadiusTarget, progress) * scale;
float outerRadius = MathFunctions.Lerp(_shape.DiskDatas.OuterRadius, _shape.DiskDatas.OuterRadiusTarget, progress) * scale;
float height = MathFunctions.Lerp(_shape.DiskDatas.Height, _shape.DiskDatas.HeightTarget, progress);
if (!m_areaTriggerData.HeightIgnoresScale)
float innerRadius = MathFunctions.Lerp(disk.InnerRadius, disk.InnerRadiusTarget, progress) * scale;
float outerRadius = MathFunctions.Lerp(disk.OuterRadius, disk.OuterRadiusTarget, progress) * scale;
float height = MathFunctions.Lerp(disk.Height, disk.HeightTarget, progress);
if (!HasAreaTriggerFlag(AreaTriggerFieldFlags.HeightIgnoresScale))
height *= scale;
float minZ = GetPositionZ() - height;
@@ -775,18 +795,17 @@ namespace Game.Entities
targetList.RemoveAll(unit => unit.IsInDist2d(this, innerRadius) || unit.GetPositionZ() < minZ || unit.GetPositionZ() > maxZ);
}
void SearchUnitInBoundedPlane(List<Unit> targetList)
void SearchUnitInBoundedPlane(AreaTriggerBoundedPlane boundedPlane, List<Unit> targetList)
{
float progress = GetProgress();
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MorphCurveId, progress);
if (m_areaTriggerData.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MorphCurveId, progress);
unsafe
{
float scale = CalcCurrentScale();
float extentsX = MathFunctions.Lerp(_shape.BoundedPlaneDatas.Extents[0], _shape.BoundedPlaneDatas.ExtentsTarget[0], progress) * scale;
float extentsY = MathFunctions.Lerp(_shape.BoundedPlaneDatas.Extents[1], _shape.BoundedPlaneDatas.ExtentsTarget[1], progress) * scale;
float extentsX = MathFunctions.Lerp(boundedPlane.Extents.GetValue().X, boundedPlane.ExtentsTarget.GetValue().X, progress) * scale;
float extentsY = MathFunctions.Lerp(boundedPlane.Extents.GetValue().Y, boundedPlane.ExtentsTarget.GetValue().Y, progress) * scale;
float radius = MathF.Sqrt(extentsX * extentsX + extentsY * extentsY);
SearchUnits(targetList, radius, false);
@@ -854,8 +873,10 @@ namespace Game.Entities
}
}
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()));
if (_insideUnits.Any(guid => guid.IsPlayer()))
SetAreaTriggerFlag(AreaTriggerFieldFlags.HasPlayers);
else
RemoveAreaTriggerFlag(AreaTriggerFieldFlags.HasPlayers);
if (IsStaticSpawn())
SetActive(!_insideUnits.Empty());
@@ -902,6 +923,83 @@ namespace Game.Entities
return 0;
}
unsafe void SetShape(AreaTriggerShapeInfo shape)
{
var areaTriggerData = m_values.ModifyValue(m_areaTriggerData);
switch (shape.TriggerType)
{
case AreaTriggerShapeType.Sphere:
{
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)0);
var sphere = areaTriggerData.ModifyValue<AreaTriggerSphere>(m_areaTriggerData.ShapeData);
SetUpdateFieldValue(sphere.ModifyValue(sphere.Radius), shape.SphereDatas.Radius);
SetUpdateFieldValue(sphere.ModifyValue(sphere.RadiusTarget), shape.SphereDatas.RadiusTarget);
break;
}
case AreaTriggerShapeType.Box:
{
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)1);
var box = areaTriggerData.ModifyValue<AreaTriggerBox>(m_areaTriggerData.ShapeData);
SetUpdateFieldValue(box.ModifyValue(box.Extents), new Vector3(shape.BoxDatas.Extents[0], shape.BoxDatas.Extents[1], shape.BoxDatas.Extents[2]));
SetUpdateFieldValue(box.ModifyValue(box.ExtentsTarget), new Vector3(shape.BoxDatas.ExtentsTarget[0], shape.BoxDatas.ExtentsTarget[1], shape.BoxDatas.ExtentsTarget[2]));
break;
}
case AreaTriggerShapeType.Polygon:
{
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)3);
var polygon = areaTriggerData.ModifyValue<AreaTriggerPolygon>(m_areaTriggerData.ShapeData);
var vertices = polygon.ModifyValue(polygon.Vertices);
ClearDynamicUpdateFieldValues(vertices);
foreach (Vector2 vertex in shape.PolygonVertices)
AddDynamicUpdateFieldValue(vertices, vertex);
var verticesTarget = polygon.ModifyValue(polygon.VerticesTarget);
ClearDynamicUpdateFieldValues(verticesTarget);
foreach (Vector2 vertex in shape.PolygonVerticesTarget)
AddDynamicUpdateFieldValue(verticesTarget, vertex);
SetUpdateFieldValue(polygon.ModifyValue(polygon.Height), shape.PolygonDatas.Height);
SetUpdateFieldValue(polygon.ModifyValue(polygon.HeightTarget), shape.PolygonDatas.HeightTarget);
break;
}
case AreaTriggerShapeType.Cylinder:
{
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)4);
var cylinder = areaTriggerData.ModifyValue<AreaTriggerCylinder>(m_areaTriggerData.ShapeData);
SetUpdateFieldValue(cylinder.ModifyValue(cylinder.Radius), shape.CylinderDatas.Radius);
SetUpdateFieldValue(cylinder.ModifyValue(cylinder.RadiusTarget), shape.CylinderDatas.RadiusTarget);
SetUpdateFieldValue(cylinder.ModifyValue(cylinder.Height), shape.CylinderDatas.Height);
SetUpdateFieldValue(cylinder.ModifyValue(cylinder.HeightTarget), shape.CylinderDatas.HeightTarget);
SetUpdateFieldValue(cylinder.ModifyValue(cylinder.LocationZOffset), shape.CylinderDatas.LocationZOffset);
SetUpdateFieldValue(cylinder.ModifyValue(cylinder.LocationZOffsetTarget), shape.CylinderDatas.LocationZOffsetTarget);
break;
}
case AreaTriggerShapeType.Disk:
{
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)7);
var disk = areaTriggerData.ModifyValue<AreaTriggerDisk>(m_areaTriggerData.ShapeData);
SetUpdateFieldValue(disk.ModifyValue(disk.InnerRadius), shape.DiskDatas.InnerRadius);
SetUpdateFieldValue(disk.ModifyValue(disk.InnerRadiusTarget), shape.DiskDatas.InnerRadiusTarget);
SetUpdateFieldValue(disk.ModifyValue(disk.OuterRadius), shape.DiskDatas.OuterRadius);
SetUpdateFieldValue(disk.ModifyValue(disk.OuterRadiusTarget), shape.DiskDatas.OuterRadiusTarget);
SetUpdateFieldValue(disk.ModifyValue(disk.Height), shape.DiskDatas.Height);
SetUpdateFieldValue(disk.ModifyValue(disk.HeightTarget), shape.DiskDatas.HeightTarget);
SetUpdateFieldValue(disk.ModifyValue(disk.LocationZOffset), shape.DiskDatas.LocationZOffset);
SetUpdateFieldValue(disk.ModifyValue(disk.LocationZOffsetTarget), shape.DiskDatas.LocationZOffsetTarget);
break;
}
case AreaTriggerShapeType.BoundedPlane:
{
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)8);
var boundedPlane = areaTriggerData.ModifyValue<AreaTriggerBoundedPlane>(m_areaTriggerData.ShapeData);
SetUpdateFieldValue(boundedPlane.ModifyValue(boundedPlane.Extents), new Vector2(shape.BoundedPlaneDatas.Extents[0], shape.BoundedPlaneDatas.Extents[1]));
SetUpdateFieldValue(boundedPlane.ModifyValue(boundedPlane.ExtentsTarget), new Vector2(shape.BoundedPlaneDatas.ExtentsTarget[0], shape.BoundedPlaneDatas.ExtentsTarget[1]));
break;
}
default:
break;
}
}
float GetMaxSearchRadius()
{
return m_areaTriggerData.BoundsRadius2D * CalcCurrentScale();
@@ -909,26 +1007,25 @@ namespace Game.Entities
void UpdatePolygonVertices()
{
AreaTriggerCreateProperties createProperties = GetCreateProperties();
AreaTriggerShapeInfo shape = GetShape();
AreaTriggerPolygon shape = m_areaTriggerData.ShapeData.Get<AreaTriggerPolygon>();
float newOrientation = GetOrientation();
// No need to recalculate, orientation didn't change
if (MathFunctions.fuzzyEq(_verticesUpdatePreviousOrientation, newOrientation) && shape.PolygonVerticesTarget.Empty())
if (MathFunctions.fuzzyEq(_verticesUpdatePreviousOrientation, newOrientation) && shape.VerticesTarget.Empty())
return;
_polygonVertices.AddRange(shape.PolygonVertices.Select(p => new Position(p.X, p.Y)));
_polygonVertices.AddRange(shape.Vertices._values.Select(p => new Position(p.X, p.Y)));
if (!shape.PolygonVerticesTarget.Empty())
if (!shape.Vertices.Empty())
{
float progress = GetProgress();
if (createProperties.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MorphCurveId, progress);
if (m_areaTriggerData.MorphCurveId != 0)
progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MorphCurveId, progress);
for (var i = 0; i < _polygonVertices.Count; ++i)
{
Vector2 vertex = _polygonVertices[i];
Vector2 vertexTarget = shape.PolygonVerticesTarget[i];
Vector2 vertexTarget = shape.VerticesTarget[i];
vertex.X = MathFunctions.Lerp(vertex.X, vertexTarget.X, progress);
vertex.Y = MathFunctions.Lerp(vertex.Y, vertexTarget.Y, progress);
@@ -959,7 +1056,7 @@ namespace Game.Entities
public void UpdateShape()
{
if (_shape.IsPolygon())
if (m_areaTriggerData.ShapeData.Is<AreaTriggerPolygon>())
UpdatePolygonVertices();
}
@@ -1090,8 +1187,6 @@ namespace Game.Entities
if (splinePoints.Length < 2)
return;
_movementTime = 0;
_spline = new Spline<float>();
_spline.InitSpline(splinePoints, splinePoints.Length, EvaluationMode.Linear, _stationaryPosition.GetOrientation());
_spline.InitLengths();
@@ -1101,29 +1196,30 @@ namespace Game.Entities
speed = 1.0f;
uint timeToTarget = _spline.Length() / speed * (float)Time.InMilliseconds;
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget);
if (IsInWorld)
{
if (_reachedDestination)
{
AreaTriggerRePath reshapeDest = new();
reshapeDest.TriggerGUID = GetGUID();
SendMessageToSet(reshapeDest, true);
}
var areaTriggerData = m_values.ModifyValue(m_areaTriggerData);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.MovementStartTime), GameTime.GetGameTimeMS());
AreaTriggerRePath reshape = new();
reshape.TriggerGUID = GetGUID();
reshape.AreaTriggerSpline = new();
reshape.AreaTriggerSpline.ElapsedTimeForMovement = GetElapsedTimeForMovement();
reshape.AreaTriggerSpline.TimeToTarget = timeToTarget;
reshape.AreaTriggerSpline.Points = _spline;
SendMessageToSet(reshape, true);
}
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.PathType), (int)AreaTriggerPathType.Spline);
var pathData = areaTriggerData.ModifyValue<AreaTriggerSplineCalculator>(m_areaTriggerData.PathData);
SetUpdateFieldValue(pathData.ModifyValue(pathData.Catmullrom), splinePoints.Length >= 4);
var points = pathData.ModifyValue(pathData.Points);
ClearDynamicUpdateFieldValues(points);
foreach (Vector3 point in splinePoints)
AddDynamicUpdateFieldValue(points, point);
_reachedDestination = false;
}
uint GetElapsedTimeForMovement()
{
uint now = GameTime.GetGameTimeMS();
if (now >= m_areaTriggerData.MovementStartTime)
return now - m_areaTriggerData.MovementStartTime;
return 0;
}
void InitOrbit(AreaTriggerOrbitInfo orbit, float? overrideSpeed = null)
{
// Circular movement requires either a center position or an attached unit
@@ -1135,45 +1231,40 @@ namespace Game.Entities
uint timeToTarget = (uint)(orbit.Radius * 2.0f * MathF.PI * (float)Time.InMilliseconds / speed);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget);
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OrbitPathTarget), orbit.PathTarget.GetValueOrDefault(ObjectGuid.Empty));
var areaTriggerData = m_values.ModifyValue(m_areaTriggerData);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget);
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.MovementStartTime), GameTime.GetGameTimeMS());
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.OrbitPathTarget), orbit.PathTarget.GetValueOrDefault(ObjectGuid.Empty));
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ZOffset), orbit.ZOffset);
if (orbit.CanLoop)
SetAreaTriggerFlag(AreaTriggerFieldFlags.CanLoop);
else
RemoveAreaTriggerFlag(AreaTriggerFieldFlags.CanLoop);
_orbitInfo = new AreaTriggerOrbitInfo();
_orbitInfo.TimeToTarget = timeToTarget;
_orbitInfo.ElapsedTimeForMovement = 0;
if (IsInWorld)
{
AreaTriggerRePath reshape = new();
reshape.TriggerGUID = GetGUID();
reshape.AreaTriggerOrbit = _orbitInfo;
SendMessageToSet(reshape, true);
}
}
public bool HasOrbit()
{
return _orbitInfo != null;
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.PathType), (int)AreaTriggerPathType.Orbit);
var pathData = areaTriggerData.ModifyValue<AreaTriggerOrbit>(m_areaTriggerData.PathData);
SetUpdateFieldValue(pathData.ModifyValue(pathData.CounterClockwise), orbit.CounterClockwise);
SetUpdateFieldValue(pathData.ModifyValue(pathData.Center), orbit.Center.GetValueOrDefault(new Position()));
SetUpdateFieldValue(pathData.ModifyValue(pathData.Radius), orbit.Radius);
SetUpdateFieldValue(pathData.ModifyValue(pathData.InitialAngle), orbit.InitialAngle);
SetUpdateFieldValue(pathData.ModifyValue(pathData.BlendFromRadius), orbit.BlendFromRadius);
SetUpdateFieldValue(pathData.ModifyValue(pathData.ExtraTimeForBlending), orbit.ExtraTimeForBlending);
}
Position GetOrbitCenterPosition()
{
if (!HasOrbit())
AreaTriggerOrbit orbit = m_areaTriggerData.PathData.Get<AreaTriggerOrbit>();
if (orbit == null)
return null;
if (_orbitInfo.PathTarget.HasValue)
if (!m_areaTriggerData.OrbitPathTarget.GetValue().IsEmpty())
{
WorldObject center = Global.ObjAccessor.GetWorldObject(this, _orbitInfo.PathTarget.Value);
WorldObject center = Global.ObjAccessor.GetWorldObject(this, m_areaTriggerData.OrbitPathTarget);
if (center != null)
return center;
}
if (_orbitInfo.Center.HasValue)
return new Position(_orbitInfo.Center.Value);
return null;
return new Position(orbit.Center);
}
Position CalculateOrbitPosition()
@@ -1182,26 +1273,24 @@ namespace Game.Entities
if (centerPos == null)
return GetPosition();
AreaTriggerCreateProperties createProperties = GetCreateProperties();
AreaTriggerOrbitInfo cmi = GetOrbit();
AreaTriggerOrbit cmi = m_areaTriggerData.PathData.Get<AreaTriggerOrbit>();
// AreaTrigger make exactly "Duration / TimeToTarget" loops during his life time
float pathProgress = (float)cmi.ElapsedTimeForMovement / cmi.TimeToTarget;
if (createProperties != null && createProperties.MoveCurveId != 0)
pathProgress = Global.DB2Mgr.GetCurveValueAt(createProperties.MoveCurveId, pathProgress);
float pathProgress = (float)(GetElapsedTimeForMovement() + cmi.ExtraTimeForBlending) / (float)GetTimeToTarget();
if (m_areaTriggerData.MoveCurveId != 0)
pathProgress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MoveCurveId, pathProgress);
// We already made one circle and can't loop
if (!cmi.CanLoop)
if (!HasAreaTriggerFlag(AreaTriggerFieldFlags.CanLoop))
pathProgress = Math.Min(1.0f, pathProgress);
float radius = cmi.Radius;
if (MathFunctions.fuzzyNe(cmi.BlendFromRadius, radius))
if (pathProgress <= 1.0f && MathFunctions.fuzzyNe(cmi.BlendFromRadius, radius))
{
float blendCurve = (cmi.BlendFromRadius - radius) / radius;
// 4.f Defines four quarters
blendCurve = MathFunctions.RoundToInterval(ref blendCurve, 1.0f, 4.0f) / 4.0f;
float blendProgress = Math.Min(1.0f, pathProgress / blendCurve);
radius = MathFunctions.Lerp(cmi.BlendFromRadius, cmi.Radius, blendProgress);
MathFunctions.RoundToInterval(ref blendCurve, 1.0f, 4.0f);
float blendProgress = Math.Min(1.0f, pathProgress / blendCurve * 0.63661975f);
radius = MathFunctions.Lerp(cmi.BlendFromRadius, radius, blendProgress);
}
// Adapt Path progress depending of circle direction
@@ -1211,13 +1300,13 @@ namespace Game.Entities
float angle = cmi.InitialAngle + 2.0f * (float)Math.PI * pathProgress;
float x = centerPos.GetPositionX() + (radius * (float)Math.Cos(angle));
float y = centerPos.GetPositionY() + (radius * (float)Math.Sin(angle));
float z = centerPos.GetPositionZ() + cmi.ZOffset;
float z = centerPos.GetPositionZ() + m_areaTriggerData.ZOffset;
float orientation = 0.0f;
if (createProperties != null && createProperties.FacingCurveId != 0)
orientation = Global.DB2Mgr.GetCurveValueAt(createProperties.FacingCurveId, GetProgress());
if (m_areaTriggerData.FacingCurveId != 0)
orientation = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.FacingCurveId, GetProgress());
if (GetCreateProperties() == null || !GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAbsoluteOrientation))
if (!HasAreaTriggerFlag(AreaTriggerFieldFlags.AbsoluteOrientation))
{
orientation += angle;
orientation += cmi.CounterClockwise ? MathFunctions.PiOver4 : -MathFunctions.PiOver4;
@@ -1226,13 +1315,8 @@ namespace Game.Entities
return new Position(x, y, z, orientation);
}
void UpdateOrbitPosition(uint diff)
void UpdateOrbitPosition()
{
if (_orbitInfo.StartDelay > GetElapsedTimeForMovement())
return;
_orbitInfo.ElapsedTimeForMovement = (int)(GetElapsedTimeForMovement() - _orbitInfo.StartDelay);
Position pos = CalculateOrbitPosition();
GetMap().AreaTriggerRelocation(this, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
@@ -1240,14 +1324,12 @@ namespace Game.Entities
DebugVisualizePosition();
}
void UpdateSplinePosition(uint diff)
void UpdateSplinePosition(Spline<float> spline)
{
if (_reachedDestination)
return;
_movementTime += diff;
if (_movementTime >= GetTimeToTarget())
if (GetElapsedTimeForMovement() >= GetTimeToTarget())
{
_reachedDestination = true;
_lastSplineIndex = _spline.Last();
@@ -1262,18 +1344,18 @@ namespace Game.Entities
return;
}
float currentTimePercent = (float)_movementTime / GetTimeToTarget();
float currentTimePercent = (float)GetElapsedTimeForMovement() / GetTimeToTarget();
if (currentTimePercent <= 0.0f)
return;
AreaTriggerCreateProperties createProperties = GetCreateProperties();
if (createProperties != null && createProperties.MoveCurveId != 0)
if (m_areaTriggerData.MoveCurveId != 0)
{
float progress = Global.DB2Mgr.GetCurveValueAt(createProperties.MoveCurveId, currentTimePercent);
float progress = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.MoveCurveId, currentTimePercent);
if (progress < 0.0f || progress > 1.0f)
{
Log.outError(LogFilter.AreaTrigger, $"AreaTrigger (Id: {GetEntry()}, AreaTriggerCreatePropertiesId: (Id: {createProperties.Id.Id}, IsCustom: {createProperties.Id.IsCustom})) has wrong progress ({progress}) caused by curve calculation (MoveCurveId: {createProperties.MoveCurveId})");
AreaTriggerCreateProperties createProperties = GetCreateProperties();
Log.outError(LogFilter.AreaTrigger, $"AreaTrigger (Id: {GetEntry()}, AreaTriggerCreatePropertiesId: (Id: {createProperties.Id.Id}, IsCustom: {createProperties.Id.IsCustom})) has wrong progress ({progress}) caused by curve calculation (MoveCurveId: {m_areaTriggerData.MoveCurveId})");
}
else
currentTimePercent = progress;
@@ -1287,10 +1369,10 @@ namespace Game.Entities
_spline.Evaluate_Percent(lastPositionIndex, percentFromLastPoint, out currentPosition);
float orientation = _stationaryPosition.GetOrientation();
if (createProperties != null && createProperties.FacingCurveId != 0)
orientation += Global.DB2Mgr.GetCurveValueAt(createProperties.FacingCurveId, GetProgress());
if (m_areaTriggerData.FacingCurveId != 0)
orientation += Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.FacingCurveId, GetProgress());
if (GetCreateProperties() != null && !GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAbsoluteOrientation) && GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasFaceMovementDir))
if (!HasAreaTriggerFlag(AreaTriggerFieldFlags.AbsoluteOrientation) && HasAreaTriggerFlag(AreaTriggerFieldFlags.FaceMovementDir))
{
_spline.Evaluate_Derivative(lastPositionIndex, percentFromLastPoint, out Vector3 derivative);
if (derivative.X != 0.0f || derivative.Y != 0.0f)
@@ -1317,11 +1399,11 @@ namespace Game.Entities
float z = GetScaleCurveValueAtProgress(m_areaTriggerData.OverrideMoveCurveZ, progress);
float orientation = GetOrientation();
if (GetCreateProperties().FacingCurveId != 0)
if (m_areaTriggerData.FacingCurveId != 0)
{
orientation = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().FacingCurveId, GetProgress());
if (GetCreateProperties() == null || !GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAbsoluteOrientation))
orientation += _stationaryPosition.GetOrientation();
orientation = Global.DB2Mgr.GetCurveValueAt(m_areaTriggerData.FacingCurveId, GetProgress());
if (HasAreaTriggerFlag(AreaTriggerFieldFlags.AbsoluteOrientation))
orientation += m_areaTriggerData.Facing;
}
GetMap().AreaTriggerRelocation(this, x, y, z, orientation);
@@ -1438,9 +1520,15 @@ namespace Game.Entities
public bool IsRemoved() { return _isRemoved; }
public uint GetSpellId() { return m_areaTriggerData.SpellID; }
public AuraEffect GetAuraEffect() { return _aurEff; }
public uint GetTimeSinceCreated() { return _timeSinceCreated; }
public void SetHeightIgnoresScale(bool heightIgnoresScale) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.HeightIgnoresScale), heightIgnoresScale); }
public AreaTriggerFieldFlags GetAreaTriggerFlags() { return (AreaTriggerFieldFlags)m_areaTriggerData.Flags.GetValue(); }
public bool HasAreaTriggerFlag(AreaTriggerFieldFlags flag)
{
return GetAreaTriggerFlags().HasFlag(flag);
}
public void SetAreaTriggerFlag(AreaTriggerFieldFlags flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.Flags), (uint)flag); }
public void RemoveAreaTriggerFlag(AreaTriggerFieldFlags flag) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.Flags), (uint)flag); }
public void ReplaceAllAreaTriggerFlags(AreaTriggerFieldFlags flag) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.Flags), (uint)flag); }
public uint GetTimeToTarget() { return m_areaTriggerData.TimeToTarget; }
public void SetTimeToTarget(uint timeToTarget) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget); }
@@ -1467,15 +1555,11 @@ namespace Game.Entities
public override ObjectGuid GetOwnerGUID() { return GetCasterGuid(); }
public ObjectGuid GetCasterGuid() { return m_areaTriggerData.Caster; }
public AreaTriggerShapeInfo GetShape() { return _shape; }
public Vector3 GetRollPitchYaw() { return _rollPitchYaw; }
public Vector3 GetTargetRollPitchYaw() { return _targetRollPitchYaw; }
public bool HasSplines() { return !_spline.Empty(); }
public Spline<float> GetSpline() { return _spline; }
public uint GetElapsedTimeForMovement() { return GetTimeSinceCreated(); } // @todo: research the right value, in sniffs both timers are nearly identical
public AreaTriggerOrbitInfo GetOrbit() { return _orbitInfo; }
bool HasOrbit() { return m_areaTriggerData.PathData.Is<AreaTriggerOrbit>(); }
public AreaTriggerOrbit GetOrbit() { return m_areaTriggerData.PathData.Get<AreaTriggerOrbit>(); }
public AreaTriggerFieldData m_areaTriggerData;
@@ -1486,21 +1570,16 @@ namespace Game.Entities
AuraEffect _aurEff;
Position _stationaryPosition;
AreaTriggerShapeInfo _shape;
int _duration;
int _totalDuration;
uint _timeSinceCreated;
float _verticesUpdatePreviousOrientation;
bool _isRemoved;
Position _rollPitchYaw;
Position _targetRollPitchYaw;
List<Position> _polygonVertices;
Spline<float> _spline;
bool _reachedDestination;
int _lastSplineIndex;
uint _movementTime;
AreaTriggerOrbitInfo _orbitInfo;
@@ -104,18 +104,6 @@ namespace Game.Entities
public AreaTriggerScaleCurvePointsTemplate CurveTemplate;
}
public struct AreaTriggerMovementScriptInfo
{
public uint SpellScriptID;
public Vector3 Center;
public void Write(WorldPacket data)
{
data.WriteUInt32(SpellScriptID);
data.WriteVector3(Center);
}
}
public struct AreaTriggerId
{
public uint Id;
@@ -204,35 +192,11 @@ namespace Game.Entities
public class AreaTriggerOrbitInfo
{
public void Write(WorldPacket data)
{
data.WriteBit(PathTarget.HasValue);
data.WriteBit(Center.HasValue);
data.WriteBit(CounterClockwise);
data.WriteBit(CanLoop);
data.WriteUInt32(TimeToTarget);
data.WriteInt32(ElapsedTimeForMovement);
data.WriteUInt32(StartDelay);
data.WriteFloat(Radius);
data.WriteFloat(BlendFromRadius);
data.WriteFloat(InitialAngle);
data.WriteFloat(ZOffset);
if (PathTarget.HasValue)
data.WritePackedGuid(PathTarget.Value);
if (Center.HasValue)
data.WriteVector3(Center.Value);
}
public ObjectGuid? PathTarget;
public Vector3? Center;
public bool CounterClockwise;
public bool CanLoop;
public uint TimeToTarget;
public int ElapsedTimeForMovement;
public uint StartDelay;
public int ExtraTimeForBlending;
public float Radius;
public float BlendFromRadius;
public float InitialAngle;
@@ -166,6 +166,7 @@ namespace Game.Entities
stats.Flags[0] = (uint)creatureDifficulty.TypeFlags;
stats.Flags[1] = creatureDifficulty.TypeFlags2;
stats.Flags[2] = creatureDifficulty.TypeFlags3;
stats.CreatureType = (sbyte)CreatureType;
stats.CreatureFamily = (int)Family;
@@ -436,6 +437,7 @@ namespace Game.Entities
public int CreatureDifficultyID;
public CreatureTypeFlags TypeFlags;
public uint TypeFlags2;
public uint TypeFlags3;
public uint LootID;
public uint PickPocketLootID;
public uint SkinLootID;
@@ -224,6 +224,12 @@ namespace Game.Entities
[FieldOffset(80)]
public craftingTable CraftingTable;
[FieldOffset(80)]
public futurePatchGameObject FuturePatchGameObject;
[FieldOffset(80)]
public assistAction AssistAction;
[FieldOffset(80)]
public raw Raw;
@@ -539,6 +545,10 @@ namespace Game.Entities
return QuestGiver.gossipID;
case GameObjectTypes.Goober:
return Goober.gossipID;
case GameObjectTypes.SpellFocus:
return SpellFocus.gossipID;
case GameObjectTypes.AssistAction:
return AssistAction.gossipID;
default:
return 0;
}
@@ -641,6 +651,8 @@ namespace Game.Entities
return Trap.cooldown;
case GameObjectTypes.Goober:
return Goober.cooldown;
case GameObjectTypes.AssistAction:
return AssistAction.cooldown;
default:
return 0;
}
@@ -1483,7 +1495,7 @@ namespace Game.Entities
public uint radius; // 4 radius, int, Min value: 0, Max value: 50, Default value: 10
public uint InteractRadiusOverride; // 5 Interact Radius Override (Yards * 100), int, Min value: 0, Max value: 2147483647, Default value: 0
public uint ItemInteractionID; // 6 Item Interaction ID, References: UiItemInteraction, NoValue = 0
public uint PlayerInteractionType; // 7 Player Interaction Type, enum { None, TradePartner, Item, Gossip, QuestGiver, Merchant, TaxiNode, Trainer, Banker, AlliedRaceDetailsGiver, GuildBanker, Registrar, Vendor, PetitionVendor, GuildTabardVendor, TalentMaster, SpecializationMaster, MailInfo, SpiritHealer, AreaSpiritHealer, Binder, Auctioneer, StableMaster, BattleMaster, Transmogrifier, LFGDungeon, VoidStorageBanker, BlackMarketAuctioneer, AdventureMap, WorldMap, GarrArchitect, GarrTradeskill, GarrMission, ShipmentCrafter, GarrRecruitment, GarrTalent, Trophy, PlayerChoice, ArtifactForge, ObliterumForge, ScrappingMachine, ContributionCollector, AzeriteRespec, IslandQueue, ItemInteraction, ChromieTime, CovenantPreview, AnimaDiversion, LegendaryCrafting, WeeklyRewards, Soulbind, CovenantSanctum, NewPlayerGuide, ItemUpgrade, AdventureJournal, Renown, AzeriteForge, PerksProgramVendor, ProfessionsCraftingOrder, Professions, ProfessionsCustomerOrder, TraitSystem, BarbersChoice, JailersTowerBuffs, MajorFactionRenown, PersonalTabardVendor, ForgeMaster, CharacterBanker, AccountBanker, ProfessionRespec, PlaceholderType71, PlaceholderType72, PlaceholderType73, PlaceholderType74, PlaceholderType75, PlaceholderType76, PlaceholderType77, }; Default: None
public uint PlayerInteractionType; // 7 Player Interaction Type, enum { None, TradePartner, Item, Gossip, QuestGiver, Merchant, TaxiNode, Trainer, Banker, AlliedRaceDetailsGiver, GuildBanker, Registrar, Vendor, PetitionVendor, GuildTabardVendor, TalentMaster, SpecializationMaster, MailInfo, SpiritHealer, AreaSpiritHealer, Binder, Auctioneer, StableMaster, BattleMaster, Transmogrifier, LFGDungeon, VoidStorageBanker, BlackMarketAuctioneer, AdventureMap, WorldMap, GarrArchitect, GarrTradeskill, GarrMission, ShipmentCrafter, GarrRecruitment, GarrTalent, Trophy, PlayerChoice, ArtifactForge, ObliterumForge, ScrappingMachine, ContributionCollector, AzeriteRespec, IslandQueue, ItemInteraction, ChromieTime, CovenantPreview, AnimaDiversion, LegendaryCrafting, WeeklyRewards, Soulbind, CovenantSanctum, NewPlayerGuide, ItemUpgrade, AdventureJournal, Renown, AzeriteForge, PerksProgramVendor, ProfessionsCraftingOrder, Professions, ProfessionsCustomerOrder, TraitSystem, BarbersChoice, JailersTowerBuffs, MajorFactionRenown, PersonalTabardVendor, ForgeMaster, CharacterBanker, AccountBanker, ProfessionRespec, PlaceholderType71, PlaceholderType72, PlaceholderType73, PlaceholderType74, PlaceholderType75, PlaceholderType76, GuildRename, PlaceholderType76, }; Default: None
}
public struct keystonereceptacle
@@ -1614,6 +1626,19 @@ namespace Game.Entities
public uint Script; // 0 Script, References: SpellScript, NoValue = 0
public uint autoClose; // 1 autoClose (ms), int, Min value: 0, Max value: 2147483647, Default value: 3000
}
public struct futurePatchGameObject
{
}
public struct assistAction
{
public uint AssistActionType; // 0 Assist Action Type, enum { None, Lounging Player, Grave Marker, Placed VO, Player Guardian, Player Slayer, Captured Buff, }; Default: None
public uint cooldown; // 1 cooldown, int, Min value: 0, Max value: 2147483647, Default value: 3000
public uint gossipID; // 2 gossipID, References: Gossip, NoValue = 0
public uint spell; // 3 spell, References: Spell, NoValue = 0
public uint playerCast; // 4 playerCast, enum { false, true, }; Default: false
}
#endregion
}
+10 -4
View File
@@ -2551,8 +2551,14 @@ namespace Game.Entities
}
eff.SetBonuses.Add(itemSetSpell);
// spell cast only if fit form requirement, in other case will cast at form change
if (itemSetSpell.ChrSpecID == 0 || (ChrSpecialization)itemSetSpell.ChrSpecID == player.GetPrimarySpecialization())
if (itemSetSpell.ChrSpecID != 0 && (ChrSpecialization)itemSetSpell.ChrSpecID != player.GetPrimarySpecialization())
continue;
if (itemSetSpell.TraitSubTreeID != 0 && itemSetSpell.TraitSubTreeID != player.m_playerData.CurrentCombatTraitConfigSubTreeID)
continue;
player.ApplyEquipSpell(spellInfo, null, true);
}
}
@@ -2592,11 +2598,10 @@ namespace Game.Entities
if (itemSetSpell.Threshold <= eff.EquippedItems.Count)
continue;
if (!eff.SetBonuses.Contains(itemSetSpell))
if (!eff.SetBonuses.Remove(itemSetSpell))
continue;
player.ApplyEquipSpell(Global.SpellMgr.GetSpellInfo(itemSetSpell.SpellID, Difficulty.None), null, false);
eff.SetBonuses.Remove(itemSetSpell);
}
if (eff.EquippedItems.Empty()) //all items of a set were removed
@@ -2618,7 +2623,8 @@ namespace Game.Entities
{
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(itemSetSpell.SpellID, Difficulty.None);
if (itemSetSpell.ChrSpecID != 0 && (ChrSpecialization)itemSetSpell.ChrSpecID != player.GetPrimarySpecialization())
if ((itemSetSpell.ChrSpecID != 0 && itemSetSpell.ChrSpecID != (ushort)player.GetPrimarySpecialization())
|| (itemSetSpell.TraitSubTreeID != 0 && itemSetSpell.TraitSubTreeID != player.m_playerData.CurrentCombatTraitConfigSubTreeID))
player.ApplyEquipSpell(spellInfo, null, false, false); // item set aura is not for current spec
else
{
@@ -15,6 +15,12 @@ namespace Game.Entities
T GetValue();
}
public interface IHasChangesMask
{
void ClearChangesMask();
UpdateMask GetUpdateMask();
}
public class UpdateFieldString : IUpdateField<string>
{
public string _value;
@@ -347,15 +353,39 @@ namespace Game.Entities
}
}
public interface IHasChangesMask
public class VariantUpdateField(int blockBit, int bit, params Type[] types)
{
void ClearChangesMask();
UpdateMask GetUpdateMask();
public object _value;
Type[] _types = types;
public int BlockBit = blockBit;
public int Bit = bit;
public bool Is<T>() { return _types.Contains(typeof(T)); }
public T Get<T>() where T : class, new()
{
if (Is<T>())
return _value as T;
return null;
}
public void Visit(Action<dynamic> visitor)
{
visitor(_value);
}
public void ConstructValue<T>() where T : class, new()
{
_value = new T();
}
}
public abstract class HasChangesMask : IHasChangesMask
{
public int _changeMask;
public static int ChangeMaskLength;
public UpdateMask _changesMask;
public int _blockBit;
public int Bit;
@@ -364,12 +394,13 @@ namespace Game.Entities
{
_blockBit = blockBit;
Bit = (int)bit;
ChangeMaskLength = changeMask;
_changesMask = new UpdateMask(changeMask);
_changeMask = changeMask;
}
public HasChangesMask(int changeMask)
{
ChangeMaskLength = changeMask;
_changesMask = new UpdateMask(changeMask);
}
@@ -433,6 +464,19 @@ namespace Game.Entities
}
}
public void ClearChangesMask(VariantUpdateField field)
{
if (typeof(IHasChangesMask).IsAssignableFrom(field._value.GetType()))
((IHasChangesMask)field._value).ClearChangesMask();
}
public dynamic ModifyValueOld(dynamic value, int bit, int blockBit)
{
_changesMask.Set(blockBit);
_changesMask.Set(bit);
return value;
}
public UpdateField<U> ModifyValue<U>(UpdateField<U> updateField) where U : new()
{
MarkChanged(updateField);
@@ -504,6 +548,18 @@ namespace Game.Entities
return new DynamicUpdateFieldSetter<U>(updateField[index], dynamicIndex);
}
public V ModifyValue<V>(VariantUpdateField field) where V : class, new()
{
if (!field.Is<V>())
field.ConstructValue<V>();
if (field.BlockBit >= 0)
_changesMask.Set(field.BlockBit);
_changesMask.Set(Bit);
return field.Get<V>();
}
public void MarkChanged<U>(UpdateField<U> updateField) where U : new()
{
_changesMask.Set(updateField.BlockBit);
@@ -560,7 +616,7 @@ namespace Game.Entities
public UpdateMask GetStaticUpdateMask()
{
return new UpdateMask(_changeMask);
return new UpdateMask(ChangeMaskLength);
}
}
File diff suppressed because it is too large Load Diff
+12 -141
View File
@@ -299,6 +299,7 @@ namespace Game.Entities
data.WriteBit(flags.NoBirthAnim);
data.WriteBit(flags.EnablePortals);
data.WriteBit(flags.PlayHoverAnim);
data.WriteBit(flags.ThisIsYou);
data.WriteBit(flags.MovementUpdate);
data.WriteBit(flags.MovementTransport);
data.WriteBit(flags.Stationary);
@@ -307,10 +308,8 @@ namespace Game.Entities
data.WriteBit(flags.Vehicle);
data.WriteBit(flags.AnimKit);
data.WriteBit(flags.Rotation);
data.WriteBit(flags.AreaTrigger);
data.WriteBit(flags.GameObject);
data.WriteBit(flags.SmoothPhasing);
data.WriteBit(flags.ThisIsYou);
data.WriteBit(flags.SceneObject);
data.WriteBit(flags.ActivePlayer);
data.WriteBit(flags.Conversation);
@@ -461,7 +460,10 @@ namespace Game.Entities
}
if (flags.CombatVictim)
data.WritePackedGuid(ToUnit().GetVictim().GetGUID()); // CombatVictim
{
Unit unit = ToUnit();
data.WritePackedGuid(unit.GetVictim().GetGUID()); // CombatVictim
}
if (flags.ServerTime)
data.WriteUInt32(GameTime.GetGameTimeMS());
@@ -481,7 +483,10 @@ namespace Game.Entities
}
if (flags.Rotation)
data.WriteInt64(ToGameObject().GetPackedLocalRotation()); // Rotation
{
GameObject gameObject = ToGameObject();
data.WriteInt64(gameObject.GetPackedLocalRotation()); // Rotation
}
if (PauseTimes != null && !PauseTimes.Empty())
foreach (var stopFrame in PauseTimes)
@@ -493,138 +498,6 @@ namespace Game.Entities
MovementExtensions.WriteTransportInfo(data, self.m_movementInfo.transport);
}
if (flags.AreaTrigger)
{
AreaTrigger areaTrigger = ToAreaTrigger();
AreaTriggerCreateProperties createProperties = areaTrigger.GetCreateProperties();
AreaTriggerShapeInfo shape = areaTrigger.GetShape();
data.WriteUInt32(areaTrigger.GetTimeSinceCreated());
data.WriteVector3(areaTrigger.GetRollPitchYaw());
switch (shape.TriggerType)
{
case AreaTriggerShapeType.Sphere:
data.WriteInt8(0);
data.WriteFloat(shape.SphereDatas.Radius);
data.WriteFloat(shape.SphereDatas.RadiusTarget);
break;
case AreaTriggerShapeType.Box:
data.WriteInt8(1);
data.WriteFloat(shape.BoxDatas.Extents[0]);
data.WriteFloat(shape.BoxDatas.Extents[1]);
data.WriteFloat(shape.BoxDatas.Extents[2]);
data.WriteFloat(shape.BoxDatas.ExtentsTarget[0]);
data.WriteFloat(shape.BoxDatas.ExtentsTarget[1]);
data.WriteFloat(shape.BoxDatas.ExtentsTarget[2]);
break;
case AreaTriggerShapeType.Polygon:
data.WriteInt8(3);
data.WriteInt32(shape.PolygonVertices.Count);
data.WriteInt32(shape.PolygonVerticesTarget.Count);
data.WriteFloat(shape.PolygonDatas.Height);
data.WriteFloat(shape.PolygonDatas.HeightTarget);
foreach (var vertice in shape.PolygonVertices)
data.WriteVector2(vertice);
foreach (var vertice in shape.PolygonVerticesTarget)
data.WriteVector2(vertice);
break;
case AreaTriggerShapeType.Cylinder:
data.WriteInt8(4);
data.WriteFloat(shape.CylinderDatas.Radius);
data.WriteFloat(shape.CylinderDatas.RadiusTarget);
data.WriteFloat(shape.CylinderDatas.Height);
data.WriteFloat(shape.CylinderDatas.HeightTarget);
data.WriteFloat(shape.CylinderDatas.LocationZOffset);
data.WriteFloat(shape.CylinderDatas.LocationZOffsetTarget);
break;
case AreaTriggerShapeType.Disk:
data.WriteInt8(7);
data.WriteFloat(shape.DiskDatas.InnerRadius);
data.WriteFloat(shape.DiskDatas.InnerRadiusTarget);
data.WriteFloat(shape.DiskDatas.OuterRadius);
data.WriteFloat(shape.DiskDatas.OuterRadiusTarget);
data.WriteFloat(shape.DiskDatas.Height);
data.WriteFloat(shape.DiskDatas.HeightTarget);
data.WriteFloat(shape.DiskDatas.LocationZOffset);
data.WriteFloat(shape.DiskDatas.LocationZOffsetTarget);
break;
case AreaTriggerShapeType.BoundedPlane:
data.WriteInt8(8);
data.WriteFloat(shape.BoundedPlaneDatas.Extents[0]);
data.WriteFloat(shape.BoundedPlaneDatas.Extents[1]);
data.WriteFloat(shape.BoundedPlaneDatas.ExtentsTarget[0]);
data.WriteFloat(shape.BoundedPlaneDatas.ExtentsTarget[1]);
break;
default:
break;
}
bool hasAbsoluteOrientation = createProperties != null && createProperties.Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAbsoluteOrientation);
bool hasDynamicShape = createProperties != null && createProperties.Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasDynamicShape);
bool hasAttached = createProperties != null && createProperties.Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasAttached);
bool hasFaceMovementDir = createProperties != null && createProperties.Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasFaceMovementDir);
bool hasFollowsTerrain = createProperties != null && createProperties.Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasFollowsTerrain);
bool hasAlwaysExterior = createProperties != null && createProperties.Flags.HasFlag(AreaTriggerCreatePropertiesFlag.AlwaysExterior);
bool hasUnknown1025 = false;
bool hasTargetRollPitchYaw = createProperties != null && createProperties.Flags.HasFlag(AreaTriggerCreatePropertiesFlag.HasTargetRollPitchYaw);
bool hasScaleCurveID = createProperties != null && createProperties.ScaleCurveId != 0;
bool hasMorphCurveID = createProperties != null && createProperties.MorphCurveId != 0;
bool hasFacingCurveID = createProperties != null && createProperties.FacingCurveId != 0;
bool hasMoveCurveID = createProperties != null && createProperties.MoveCurveId != 0;
bool hasMovementScript = false;
bool hasPositionalSoundKitID = false;
data.WriteBit(hasAbsoluteOrientation);
data.WriteBit(hasDynamicShape);
data.WriteBit(hasAttached);
data.WriteBit(hasFaceMovementDir);
data.WriteBit(hasFollowsTerrain);
data.WriteBit(hasAlwaysExterior);
data.WriteBit(hasUnknown1025);
data.WriteBit(hasTargetRollPitchYaw);
data.WriteBit(hasScaleCurveID);
data.WriteBit(hasMorphCurveID);
data.WriteBit(hasFacingCurveID);
data.WriteBit(hasMoveCurveID);
data.WriteBit(hasPositionalSoundKitID);
data.WriteBit(areaTrigger.HasSplines());
data.WriteBit(areaTrigger.HasOrbit());
data.WriteBit(hasMovementScript);
data.FlushBits();
if (areaTrigger.HasSplines())
AreaTriggerSplineInfo.WriteAreaTriggerSpline(data, areaTrigger.GetTimeToTarget(), areaTrigger.GetElapsedTimeForMovement(), areaTrigger.GetSpline());
if (hasTargetRollPitchYaw)
data.WriteVector3(areaTrigger.GetTargetRollPitchYaw());
if (hasScaleCurveID)
data.WriteUInt32(createProperties.ScaleCurveId);
if (hasMorphCurveID)
data.WriteUInt32(createProperties.MorphCurveId);
if (hasFacingCurveID)
data.WriteUInt32(createProperties.FacingCurveId);
if (hasMoveCurveID)
data.WriteUInt32(createProperties.MoveCurveId);
if (hasPositionalSoundKitID)
data.WriteUInt32(0);
//if (hasMovementScript)
// *data << *areaTrigger.GetMovementScript(); // AreaTriggerMovementScriptInfo
if (areaTrigger.HasOrbit())
areaTrigger.GetOrbit().Write(data);
}
if (flags.GameObject)
{
GameObject gameObject = ToGameObject();
@@ -785,7 +658,7 @@ namespace Game.Entities
Player player = ToPlayer();
bool HasSceneInstanceIDs = !player.GetSceneMgr().GetSceneTemplateByInstanceMap().Empty();
bool HasRuneState = ToUnit().GetPowerIndex(PowerType.Runes) != (int)PowerType.Max;
bool HasRuneState = player.GetPowerIndex(PowerType.Runes) != (int)PowerType.Max;
data.WriteBit(HasSceneInstanceIDs);
data.WriteBit(HasRuneState);
@@ -794,8 +667,8 @@ namespace Game.Entities
if (HasSceneInstanceIDs)
{
data.WriteInt32(player.GetSceneMgr().GetSceneTemplateByInstanceMap().Count);
foreach (var pair in player.GetSceneMgr().GetSceneTemplateByInstanceMap())
data.WriteUInt32(pair.Key);
foreach (var (sceneInstanceId, _) in player.GetSceneMgr().GetSceneTemplateByInstanceMap())
data.WriteUInt32(sceneInstanceId);
}
if (HasRuneState)
@@ -4157,7 +4030,6 @@ namespace Game.Entities
public bool Vehicle;
public bool AnimKit;
public bool Rotation;
public bool AreaTrigger;
public bool GameObject;
public bool SmoothPhasing;
public bool ThisIsYou;
@@ -4178,7 +4050,6 @@ namespace Game.Entities
Vehicle = false;
AnimKit = false;
Rotation = false;
AreaTrigger = false;
GameObject = false;
SmoothPhasing = false;
ThisIsYou = false;
+65 -102
View File
@@ -725,6 +725,25 @@ namespace Game.Entities
}
}
void _LoadCharacterBankTabSettings(SQLResult result)
{
if (!result.IsEmpty())
{
do
{
if (result.Read<byte>(0) >= (InventorySlots.BankBagEnd - InventorySlots.BankBagStart))
continue;
SetCharacterBankTabSettings(result.Read<byte>(0), result.Read<string>(1), result.Read<string>(2),
result.Read<string>(3), (BagSlotFlags)result.Read<uint>(4));
} while (result.NextRow());
}
while (m_activePlayerData.CharacterBankTabSettings.Size() < m_activePlayerData.NumCharacterBankTabs)
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CharacterBankTabSettings), new BankTabSettings());
}
void _LoadCurrency(SQLResult result)
{
if (result.IsEmpty())
@@ -1272,7 +1291,13 @@ namespace Game.Entities
});
if (activeConfig >= 0)
SetActiveCombatTraitConfigID(m_activePlayerData.TraitConfigs[activeConfig].ID);
{
TraitConfig activeTraitConfig = m_activePlayerData.TraitConfigs[activeConfig];
SetActiveCombatTraitConfigID(activeTraitConfig.ID);
int activeSubTree = activeTraitConfig.SubTrees.FindIndexIf(subTree => subTree.Active != 0);
if (activeSubTree >= 0)
SetCurrentCombatTraitConfigSubTreeID(activeTraitConfig.SubTrees[activeSubTree].TraitSubTreeID);
}
foreach (TraitConfig traitConfig in m_activePlayerData.TraitConfigs)
{
@@ -1340,55 +1365,6 @@ namespace Game.Entities
RemoveAtLoginFlag(AtLoginFlags.Resurrect);
}
void _LoadVoidStorage(SQLResult result)
{
if (result.IsEmpty())
return;
do
{
// SELECT itemId, itemEntry, slot, creatorGuid, randomBonusListId, fixedScalingLevel, artifactKnowledgeLevel, context, bonusListIDs FROM character_void_storage WHERE playerGuid = ?
ulong itemId = result.Read<ulong>(0);
uint itemEntry = result.Read<uint>(1);
byte slot = result.Read<byte>(2);
ObjectGuid creatorGuid = result.Read<ulong>(3) != 0 ? ObjectGuid.Create(HighGuid.Player, result.Read<ulong>(3)) : ObjectGuid.Empty;
uint randomBonusListId = result.Read<uint>(4);
uint fixedScalingLevel = result.Read<uint>(5);
uint artifactKnowledgeLevel = result.Read<uint>(6);
ItemContext context = (ItemContext)result.Read<byte>(7);
List<uint> bonusListIDs = new();
var bonusListIdTokens = new StringArray(result.Read<string>(8), ' ');
for (var i = 0; i < bonusListIdTokens.Length; ++i)
{
if (uint.TryParse(bonusListIdTokens[i], out uint id))
bonusListIDs.Add(id);
}
if (itemId == 0)
{
Log.outError(LogFilter.Player, "Player:_LoadVoidStorage - Player (GUID: {0}, name: {1}) has an item with an invalid id (item id: item id: {2}, entry: {3}).", GetGUID().ToString(), GetName(), itemId, itemEntry);
continue;
}
if (Global.ObjectMgr.GetItemTemplate(itemEntry) == null)
{
Log.outError(LogFilter.Player, "Player:_LoadVoidStorage - Player (GUID: {0}, name: {1}) has an item with an invalid entry (item id: item id: {2}, entry: {3}).", GetGUID().ToString(), GetName(), itemId, itemEntry);
continue;
}
if (slot >= SharedConst.VoidStorageMaxSlot)
{
Log.outError(LogFilter.Player, "Player:_LoadVoidStorage - Player (GUID: {0}, name: {1}) has an item with an invalid slot (item id: item id: {2}, entry: {3}, slot: {4}).", GetGUID().ToString(), GetName(), itemId, itemEntry, slot);
continue;
}
_voidStorageItems[slot] = new VoidStorageItem(itemId, itemEntry, creatorGuid, randomBonusListId, fixedScalingLevel, artifactKnowledgeLevel, context, bonusListIDs);
BonusData bonus = new(new ItemInstance(_voidStorageItems[slot]));
GetSession().GetCollectionMgr().AddItemAppearance(itemEntry, bonus.AppearanceModID);
}
while (result.NextRow());
}
public void _LoadMail(SQLResult mailsResult, SQLResult mailItemsResult, SQLResult artifactResult, SQLResult azeriteItemResult, SQLResult azeriteItemMilestonePowersResult, SQLResult azeriteItemUnlockedEssencesResult, SQLResult azeriteEmpoweredItemResult)
{
@@ -2762,6 +2738,26 @@ namespace Game.Entities
_playerDataFlagsNeedSave.Clear();
}
void _SaveCharacterBankTabSettings(SQLTransaction trans)
{
PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHARACTER_BANK_TAB_SETTINGS);
stmt.AddValue(0, GetGUID().GetCounter());
trans.Append(stmt);
for (int i = 0; i < m_activePlayerData.CharacterBankTabSettings.Size(); ++i)
{
BankTabSettings tabSetting = m_activePlayerData.CharacterBankTabSettings[i];
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.INS_CHARACTER_BANK_TAB_SETTINGS);
stmt.AddValue(0, GetGUID().GetCounter());
stmt.AddValue(1, i);
stmt.AddValue(2, tabSetting.Name);
stmt.AddValue(3, tabSetting.Icon);
stmt.AddValue(4, tabSetting.Description);
stmt.AddValue(5, tabSetting.DepositFlags);
trans.Append(stmt);
}
}
public void SaveInventoryAndGoldToDB(SQLTransaction trans)
{
_SaveInventory(trans);
@@ -2867,42 +2863,7 @@ namespace Game.Entities
}
}
}
void _SaveVoidStorage(SQLTransaction trans)
{
PreparedStatement stmt;
for (byte i = 0; i < SharedConst.VoidStorageMaxSlot; ++i)
{
if (_voidStorageItems[i] == null) // unused item
{
// DELETE FROM void_storage WHERE slot = ? AND playerGuid = ?
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT);
stmt.AddValue(0, i);
stmt.AddValue(1, GetGUID().GetCounter());
}
else
{
// REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomPropertyType, randomProperty, upgradeId, fixedScalingLevel, artifactKnowledgeLevel, bonusListIDs) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.REP_CHAR_VOID_STORAGE_ITEM);
stmt.AddValue(0, _voidStorageItems[i].ItemId);
stmt.AddValue(1, GetGUID().GetCounter());
stmt.AddValue(2, _voidStorageItems[i].ItemEntry);
stmt.AddValue(3, i);
stmt.AddValue(4, _voidStorageItems[i].CreatorGuid.GetCounter());
stmt.AddValue(5, (byte)_voidStorageItems[i].RandomBonusListId);
stmt.AddValue(6, _voidStorageItems[i].FixedScalingLevel);
stmt.AddValue(7, _voidStorageItems[i].ArtifactKnowledgeLevel);
stmt.AddValue(8, (byte)_voidStorageItems[i].Context);
StringBuilder bonusListIDs = new();
foreach (uint bonusListID in _voidStorageItems[i].BonusListIDs)
bonusListIDs.AppendFormat("{0} ", bonusListID);
stmt.AddValue(9, bonusListIDs.ToString());
}
trans.Append(stmt);
}
}
void _SaveCUFProfiles(SQLTransaction trans)
{
PreparedStatement stmt;
@@ -3006,10 +2967,8 @@ namespace Game.Entities
bagSlotFlags[i] = (BagSlotFlags)result.Read<uint>(fieldIndex++);
byte bankSlots = result.Read<byte>(fieldIndex++);
BagSlotFlags[] bankBagSlotFlags = new BagSlotFlags[7];
byte bankTabs = result.Read<byte>(fieldIndex++);
BagSlotFlags bankBagFlags = (BagSlotFlags)result.Read<uint>(fieldIndex++);
for (var i = 0; i < bankBagSlotFlags.Length; ++i)
bankBagSlotFlags[i] = (BagSlotFlags)result.Read<uint>(fieldIndex++);
PlayerRestState restState = (PlayerRestState)result.Read<byte>(fieldIndex++);
PlayerFlags playerFlags = (PlayerFlags)result.Read<uint>(fieldIndex++);
@@ -3179,9 +3138,8 @@ namespace Game.Entities
ReplaceAllBagSlotFlags(bagIndex, bagSlotFlags[bagIndex]);
SetBankBagSlotCount(bankSlots);
SetCharacterBankTabCount(bankTabs);
SetBankAutoSortDisabled(bankBagFlags.HasFlag(BagSlotFlags.DisableAutoSort));
for (int bagIndex = 0; bagIndex < bankBagSlotFlags.Length; ++bagIndex)
ReplaceAllBankBagSlotFlags(bagIndex, bankBagSlotFlags[bagIndex]);
SetNativeGender(gender);
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.Inebriation), drunk);
@@ -3608,12 +3566,11 @@ namespace Game.Entities
// must be before inventory (some items required reputation check)
reputationMgr.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.Reputation));
_LoadCharacterBankTabSettings(holder.GetResult(PlayerLoginQueryLoad.BankTabSettings));
_LoadInventory(holder.GetResult(PlayerLoginQueryLoad.Inventory), holder.GetResult(PlayerLoginQueryLoad.Artifacts), holder.GetResult(PlayerLoginQueryLoad.Azerite),
holder.GetResult(PlayerLoginQueryLoad.AzeriteMilestonePowers), holder.GetResult(PlayerLoginQueryLoad.AzeriteUnlockedEssences), holder.GetResult(PlayerLoginQueryLoad.AzeriteEmpowered), time_diff);
if (IsVoidStorageUnlocked())
_LoadVoidStorage(holder.GetResult(PlayerLoginQueryLoad.VoidStorage));
// update items with duration and realtime
UpdateItemDuration(time_diff, true);
@@ -3884,13 +3841,12 @@ namespace Game.Entities
foreach (uint bagSlotFlag in m_activePlayerData.BagSlotFlags)
stmt.AddValue(index++, bagSlotFlag);
stmt.AddValue(index++, GetBankBagSlotCount());
stmt.AddValue(index++, GetCharacterBankTabCount());
inventoryFlags = BagSlotFlags.None;
if (m_activePlayerData.BankAutoSortDisabled)
inventoryFlags |= BagSlotFlags.DisableAutoSort;
stmt.AddValue(index++, (uint)inventoryFlags);
foreach (uint bankBagSlotFlag in m_activePlayerData.BankBagSlotFlags)
stmt.AddValue(index++, bankBagSlotFlag);
stmt.AddValue(index++, m_activePlayerData.RestInfo[(int)RestTypes.XP].StateID);
stmt.AddValue(index++, m_playerData.PlayerFlags);
@@ -4019,13 +3975,12 @@ namespace Game.Entities
foreach (uint bagSlotFlag in m_activePlayerData.BagSlotFlags)
stmt.AddValue(index++, bagSlotFlag);
stmt.AddValue(index++, GetBankBagSlotCount());
stmt.AddValue(index++, GetCharacterBankTabCount());
inventoryFlags = BagSlotFlags.None;
if (m_activePlayerData.BankAutoSortDisabled)
inventoryFlags |= BagSlotFlags.DisableAutoSort;
stmt.AddValue(index++, (uint)inventoryFlags);
foreach (uint bankBagSlotFlag in m_activePlayerData.BankBagSlotFlags)
stmt.AddValue(index++, bankBagSlotFlag);
stmt.AddValue(index++, m_activePlayerData.RestInfo[(int)RestTypes.XP].StateID);
stmt.AddValue(index++, m_playerData.PlayerFlags);
@@ -4179,7 +4134,6 @@ namespace Game.Entities
_SaveCustomizations(characterTransaction);
_SaveBGData(characterTransaction);
_SaveInventory(characterTransaction);
_SaveVoidStorage(characterTransaction);
_SaveQuestStatus(characterTransaction);
_SaveDailyQuestStatus(characterTransaction);
_SaveWeeklyQuestStatus(characterTransaction);
@@ -4203,6 +4157,7 @@ namespace Game.Entities
_SaveCurrency(characterTransaction);
_SaveCUFProfiles(characterTransaction);
_SavePlayerData(characterTransaction);
_SaveCharacterBankTabSettings(characterTransaction);
if (_garrison != null)
_garrison.SaveToDB(characterTransaction);
@@ -4717,10 +4672,6 @@ namespace Game.Entities
stmt.AddValue(0, guid);
trans.Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHAR_VOID_STORAGE_ITEM_BY_CHAR_GUID);
stmt.AddValue(0, guid);
trans.Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHAR_FISHINGSTEPS);
stmt.AddValue(0, guid);
trans.Append(stmt);
@@ -4755,6 +4706,18 @@ namespace Game.Entities
stmt.AddValue(0, guid);
trans.Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_PLAYER_DATA_ELEMENTS_CHARACTER_BY_GUID);
stmt.AddValue(0, guid);
trans.Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_PLAYER_DATA_FLAGS_CHARACTER_BY_GUID);
stmt.AddValue(0, guid);
trans.Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_CHARACTER_BANK_TAB_SETTINGS);
stmt.AddValue(0, guid);
trans.Append(stmt);
Global.CharacterCacheStorage.DeleteCharacterCacheEntry(playerGuid, name);
break;
}
@@ -41,7 +41,6 @@ namespace Game.Entities
List<ObjectGuid> m_itemSoulboundTradeable = new();
List<ObjectGuid> m_refundableItems = new();
public List<Item> ItemUpdateQueue = new();
VoidStorageItem[] _voidStorageItems = new VoidStorageItem[SharedConst.VoidStorageMaxSlot];
Item[] m_items = new Item[(int)PlayerSlots.Count];
uint m_WeaponProficiency;
uint m_ArmorProficiency;
@@ -490,32 +489,6 @@ namespace Game.Entities
public uint leftduration;
}
public class VoidStorageItem
{
public VoidStorageItem(ulong id, uint entry, ObjectGuid creator, uint randomBonusListId, uint fixedScalingLevel, uint artifactKnowledgeLevel, ItemContext context, List<uint> bonuses)
{
ItemId = id;
ItemEntry = entry;
CreatorGuid = creator;
RandomBonusListId = randomBonusListId;
FixedScalingLevel = fixedScalingLevel;
ArtifactKnowledgeLevel = artifactKnowledgeLevel;
Context = context;
foreach (var value in bonuses)
BonusListIDs.Add(value);
}
public ulong ItemId;
public uint ItemEntry;
public ObjectGuid CreatorGuid;
public uint RandomBonusListId;
public uint FixedScalingLevel;
public uint ArtifactKnowledgeLevel;
public ItemContext Context;
public List<uint> BonusListIDs = new();
}
public class EquipmentSetInfo
{
public EquipmentSetInfo()
+42 -276
View File
@@ -1449,7 +1449,7 @@ namespace Game.Entities
return res; // return latest error if any
}
Item EquipNewItem(ushort pos, uint item, ItemContext context, bool update)
public Item EquipNewItem(ushort pos, uint item, ItemContext context, bool update)
{
Item pItem = Item.CreateItem(item, 1, context, this);
if (pItem != null)
@@ -2055,12 +2055,6 @@ namespace Game.Entities
}
}
if (IsReagentBankPos(dst) && !IsReagentBankUnlocked())
{
SendEquipError(InventoryResult.ReagentBankLocked, pSrcItem, pDstItem);
return;
}
// NOW this is or item move (swap with empty), or swap with another item (including bags in bag possitions)
// or swap empty bag with another empty or not empty bag (with items exchange)
@@ -2094,7 +2088,6 @@ namespace Game.Entities
RemoveItem(srcbag, srcslot, true);
BankItem(dest, pSrcItem, true);
if (!IsReagentBankPos(dst))
ItemRemovedQuestCheck(pSrcItem.GetEntry(), pSrcItem.GetCount());
}
else if (IsEquipmentPos(dst))
@@ -2738,18 +2731,10 @@ namespace Game.Entities
if (slot >= InventorySlots.ItemStart && slot < InventorySlots.ItemStart + GetInventorySlotCount())
return true;
// bank main slots
if (slot >= InventorySlots.BankItemStart && slot < InventorySlots.BankItemEnd)
return true;
// bank bag slots
if (slot >= InventorySlots.BankBagStart && slot < InventorySlots.BankBagEnd)
return true;
// reagent bank bag slots
if (slot >= InventorySlots.ReagentStart && slot < InventorySlots.ReagentEnd)
return true;
return false;
}
@@ -4080,8 +4065,6 @@ namespace Game.Entities
return true;
if (bag >= InventorySlots.ReagentBagStart && bag < InventorySlots.ReagentBagEnd)
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentStart && slot < InventorySlots.ReagentEnd))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ChildEquipmentStart && slot < InventorySlots.ChildEquipmentEnd))
return true;
return false;
@@ -4168,10 +4151,6 @@ namespace Game.Entities
// prevent cheating
if ((slot >= InventorySlots.BuyBackStart && slot < InventorySlots.BuyBackEnd) || slot >= (byte)PlayerSlots.End)
return InventoryResult.WrongBagType;
// can't store anything else than crafting reagents in Reagent Bank
if (IsReagentBankPos(bag, slot) && (!IsReagentBankUnlocked() || !pProto.IsCraftingReagent()))
return InventoryResult.WrongBagType;
}
else
{
@@ -4271,14 +4250,10 @@ namespace Game.Entities
public static bool IsBankPos(byte bag, byte slot)
{
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BankItemStart && slot < InventorySlots.BankItemEnd))
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.BankBagStart && slot < InventorySlots.BankBagEnd))
return true;
if (bag >= InventorySlots.BankBagStart && bag < InventorySlots.BankBagEnd)
return true;
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentStart && slot < InventorySlots.ReagentEnd))
return true;
return false;
}
@@ -4293,12 +4268,6 @@ namespace Game.Entities
Cypher.Assert(bag == ItemConst.NullBag && slot == ItemConst.NullSlot); // when reagentBankOnly is true then bag & slot must be hardcoded constants, not client input
}
if ((IsReagentBankPos(bag, slot) || reagentBankOnly) && !IsReagentBankUnlocked())
return InventoryResult.ReagentBankLocked;
byte slotStart = reagentBankOnly ? InventorySlots.ReagentStart : InventorySlots.BankItemStart;
byte slotEnd = reagentBankOnly ? InventorySlots.ReagentEnd : InventorySlots.BankItemEnd;
uint count = pItem.GetCount();
Log.outDebug(LogFilter.Player, "STORAGE: CanBankItem bag = {0}, slot = {1}, item = {2}, count = {3}", bag, slot, pItem.GetEntry(), count);
@@ -4334,7 +4303,7 @@ namespace Game.Entities
if (!pItem.IsBag())
return InventoryResult.WrongSlot;
if (slot - InventorySlots.BagStart >= GetBankBagSlotCount())
if (slot - InventorySlots.BagStart >= GetCharacterBankTabCount())
return InventoryResult.NoBankSlot;
res = CanUseItem(pItem, not_loading);
@@ -4363,12 +4332,7 @@ namespace Game.Entities
{
if (bag == InventorySlots.Bag0)
{
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
if (count == 0)
return InventoryResult.Ok;
return InventoryResult.WrongSlot; // TODO: check if INVENTORY_SLOT_BAG_0 condition is neccessary
}
else
{
@@ -4387,12 +4351,7 @@ namespace Game.Entities
// search free slot in bag
if (bag == InventorySlots.Bag0)
{
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
if (count == 0)
return InventoryResult.Ok;
return InventoryResult.WrongSlot; // TODO: check if INVENTORY_SLOT_BAG_0 condition is neccessary
}
else
{
@@ -4413,34 +4372,13 @@ namespace Game.Entities
// search stack for merge to
if (pProto.GetMaxStackSize() != 1)
{
// in slots
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
if (count == 0)
return InventoryResult.Ok;
// don't try to store reagents anywhere else than in Reagent Bank if we're on it
if (!reagentBankOnly)
{
// in special bags
if (pProto.GetBagFamily() != BagFamilyMask.None)
{
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, true, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
if (count == 0)
return InventoryResult.Ok;
}
}
// in regular bags
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
// only consider tabs marked as reagents if requested
if (reagentBankOnly && (m_activePlayerData.CharacterBankTabSettings[i - InventorySlots.BankBagStart].DepositFlags & (int)BagSlotFlags.PriorityReagents) == 0)
continue;
res = CanStoreItem_InBag(i, dest, pProto, ref count, true, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
@@ -4449,35 +4387,14 @@ namespace Game.Entities
return InventoryResult.Ok;
}
}
}
// search free place in special bag
if (!reagentBankOnly && pProto.GetBagFamily() != BagFamilyMask.None)
{
// search free space in regular bags
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, false, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
// only consider tabs marked as reagents if requested
if (reagentBankOnly && (m_activePlayerData.CharacterBankTabSettings[i - InventorySlots.BankBagStart].DepositFlags & (int)BagSlotFlags.PriorityReagents) == 0)
continue;
if (count == 0)
return InventoryResult.Ok;
}
}
// search free space
res = CanStoreItem_InInventorySlots(slotStart, slotEnd, dest, pProto, ref count, false, pItem, bag, slot);
if (res != InventoryResult.Ok)
return res;
if (count == 0)
return InventoryResult.Ok;
// search free space in regular bags (don't try to store reagents anywhere else than in Reagent Bank if we're on it)
if (!reagentBankOnly)
{
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
res = CanStoreItem_InBag(i, dest, pProto, ref count, false, true, pItem, bag, slot);
if (res != InventoryResult.Ok)
continue;
@@ -4485,7 +4402,7 @@ namespace Game.Entities
if (count == 0)
return InventoryResult.Ok;
}
}
return reagentBankOnly ? InventoryResult.ReagentBankFull : InventoryResult.BankFull;
}
@@ -4530,10 +4447,6 @@ namespace Game.Entities
if (location.HasFlag(ItemSearchLocation.Bank))
{
for (byte i = InventorySlots.BankItemStart; i < InventorySlots.BankItemEnd; ++i)
if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount;
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; ++i)
{
Bag bag = GetBagByPos(i);
@@ -4556,25 +4469,11 @@ namespace Game.Entities
if (bag.GetItemByPos(j) == null)
++freeSlotCount;
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
if (GetItemByPos(InventorySlots.Bag0, i) == null)
++freeSlotCount;
}
return freeSlotCount;
}
//Reagent
public static bool IsReagentBankPos(ushort pos) { return IsReagentBankPos((byte)(pos >> 8), (byte)(pos & 255)); }
public static bool IsReagentBankPos(byte bag, byte slot)
{
if (bag == InventorySlots.Bag0 && (slot >= InventorySlots.ReagentStart && slot < InventorySlots.ReagentEnd))
return true;
return false;
}
//Bags
public Bag GetBagByPos(byte bag)
{
@@ -4898,7 +4797,7 @@ namespace Game.Entities
return ItemConst.NullSlot;
}
InventoryResult CanEquipNewItem(byte slot, out ushort dest, uint item, bool swap)
public InventoryResult CanEquipNewItem(byte slot, out ushort dest, uint item, bool swap)
{
dest = 0;
Item pItem = Item.CreateItem(item, 1, ItemContext.None, this);
@@ -5253,6 +5152,14 @@ namespace Game.Entities
//Child
public static bool IsChildEquipmentPos(ushort pos) { return IsChildEquipmentPos((byte)(pos >> 8), (byte)(pos & 255)); }
public static bool IsAccountBankPos(ushort pos) { return IsBankPos((byte)(pos >> 8), (byte)(pos & 255)); }
public static bool IsAccountBankPos(byte bag, byte slot)
{
if (bag >= (int)AccountBankBagSlots.Start && bag < (int)AccountBankBagSlots.End)
return true;
return false;
}
//Artifact
void ApplyArtifactPowers(Item item, bool apply)
{
@@ -5776,34 +5683,6 @@ namespace Game.Entities
}
}
// in bank
for (byte i = InventorySlots.BankItemStart; i < InventorySlots.BankItemEnd; i++)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
{
if (item.GetEntry() == itemEntry && !item.IsInTrade())
{
if (item.GetCount() + remcount <= count)
{
remcount += item.GetCount();
DestroyItem(InventorySlots.Bag0, i, update);
if (remcount >= count)
return remcount;
}
else
{
item.SetCount(item.GetCount() - count + remcount);
ItemRemovedQuestCheck(item.GetEntry(), count - remcount);
if (IsInWorld && update)
item.SendUpdateToPlayer(this);
item.SetState(ItemUpdateState.Changed, this);
return count;
}
}
}
}
// in bank bags
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; i++)
{
@@ -5872,35 +5751,6 @@ namespace Game.Entities
}
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
{
if (item.GetEntry() == itemEntry && !item.IsInTrade())
{
if (item.GetCount() + remcount <= count)
{
// all keys can be unequipped
remcount += item.GetCount();
DestroyItem(InventorySlots.Bag0, i, update);
if (remcount >= count)
return remcount;
}
else
{
item.SetCount(item.GetCount() - count + remcount);
ItemRemovedQuestCheck(item.GetEntry(), count - remcount);
if (IsInWorld && update)
item.SendUpdateToPlayer(this);
item.SetState(ItemUpdateState.Changed, this);
return count;
}
}
}
}
for (byte i = InventorySlots.ChildEquipmentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
@@ -6014,6 +5864,27 @@ namespace Game.Entities
public byte GetBankBagSlotCount() { return m_activePlayerData.NumBankSlots; }
public void SetBankBagSlotCount(byte count) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NumBankSlots), count); }
public byte GetCharacterBankTabCount() { return m_activePlayerData.NumCharacterBankTabs; }
public void SetCharacterBankTabCount(byte count) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NumCharacterBankTabs), count); }
public byte GetAccountBankTabCount() { return m_activePlayerData.NumAccountBankTabs; }
public void SetAccountBankTabCount(byte count) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NumAccountBankTabs), count); }
public void SetCharacterBankTabSettings(uint tabId, string name, string icon, string description, BagSlotFlags depositFlags)
{
var setter = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CharacterBankTabSettings, (int)tabId);
SetBankTabSettings(setter, name, icon, description, depositFlags);
}
public void SetAccountBankTabSettings(uint tabId, string name, string icon, string description, BagSlotFlags depositFlags)
{
var setter = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.AccountBankTabSettings, (int)tabId);
SetBankTabSettings(setter, name, icon, description, depositFlags);
}
public void SetBankTabSettings(BankTabSettings bantTabSettings, string name, string icon, string description, BagSlotFlags depositFlags)
{
SetUpdateFieldValue(bantTabSettings.ModifyValue(bantTabSettings.Name), name);
SetUpdateFieldValue(bantTabSettings.ModifyValue(bantTabSettings.Icon), icon);
SetUpdateFieldValue(bantTabSettings.ModifyValue(bantTabSettings.Description), description);
SetUpdateFieldValue(bantTabSettings.ModifyValue(bantTabSettings.DepositFlags), (int)depositFlags);
}
public bool IsBackpackAutoSortDisabled() { return m_activePlayerData.BackpackAutoSortDisabled; }
public void SetBackpackAutoSortDisabled(bool disabled) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BackpackAutoSortDisabled), disabled); }
@@ -6025,10 +5896,6 @@ namespace Game.Entities
public void SetBagSlotFlag(int bagIndex, BagSlotFlags flags) { SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BagSlotFlags, bagIndex), (uint)flags); }
public void RemoveBagSlotFlag(int bagIndex, BagSlotFlags flags) { RemoveUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BagSlotFlags, bagIndex), (uint)flags); }
public void ReplaceAllBagSlotFlags(int bagIndex, BagSlotFlags flags) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BagSlotFlags, bagIndex), (uint)flags); }
public BagSlotFlags GetBankBagSlotFlags(int bagIndex) { return (BagSlotFlags)m_activePlayerData.BankBagSlotFlags[bagIndex]; }
public void SetBankBagSlotFlag(int bagIndex, BagSlotFlags flags) { SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BankBagSlotFlags, bagIndex), (uint)flags); }
public void RemoveBankBagSlotFlag(int bagIndex, BagSlotFlags flags) { RemoveUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BankBagSlotFlags, bagIndex), (uint)flags); }
public void ReplaceAllBankBagSlotFlags(int bagIndex, BagSlotFlags flags) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BankBagSlotFlags, bagIndex), (uint)flags); }
//Loot
public ObjectGuid GetLootGUID() { return m_playerData.LootTargetGUID; }
@@ -6308,91 +6175,6 @@ namespace Game.Entities
}
}
//Void Storage
public bool IsVoidStorageUnlocked() { return HasPlayerFlag(PlayerFlags.VoidUnlocked); }
public void UnlockVoidStorage() { SetPlayerFlag(PlayerFlags.VoidUnlocked); }
public void LockVoidStorage() { RemovePlayerFlag(PlayerFlags.VoidUnlocked); }
public byte GetNextVoidStorageFreeSlot()
{
for (byte i = 0; i < SharedConst.VoidStorageMaxSlot; ++i)
if (_voidStorageItems[i] == null) // unused item
return i;
return SharedConst.VoidStorageMaxSlot;
}
public byte GetNumOfVoidStorageFreeSlots()
{
byte count = 0;
for (byte i = 0; i < SharedConst.VoidStorageMaxSlot; ++i)
if (_voidStorageItems[i] == null)
count++;
return count;
}
public byte AddVoidStorageItem(VoidStorageItem item)
{
byte slot = GetNextVoidStorageFreeSlot();
if (slot >= SharedConst.VoidStorageMaxSlot)
{
GetSession().SendVoidStorageTransferResult(VoidTransferError.Full);
return 255;
}
_voidStorageItems[slot] = item;
return slot;
}
public void DeleteVoidStorageItem(byte slot)
{
if (slot >= SharedConst.VoidStorageMaxSlot)
{
GetSession().SendVoidStorageTransferResult(VoidTransferError.InternalError1);
return;
}
_voidStorageItems[slot] = null;
}
public bool SwapVoidStorageItem(byte oldSlot, byte newSlot)
{
if (oldSlot >= SharedConst.VoidStorageMaxSlot || newSlot >= SharedConst.VoidStorageMaxSlot || oldSlot == newSlot)
return false;
_voidStorageItems.Swap(newSlot, oldSlot);
return true;
}
public VoidStorageItem GetVoidStorageItem(byte slot)
{
if (slot >= SharedConst.VoidStorageMaxSlot)
{
GetSession().SendVoidStorageTransferResult(VoidTransferError.InternalError1);
return null;
}
return _voidStorageItems[slot];
}
public VoidStorageItem GetVoidStorageItem(ulong id, out byte slot)
{
slot = 0;
for (byte i = 0; i < SharedConst.VoidStorageMaxSlot; ++i)
{
if (_voidStorageItems[i] != null && _voidStorageItems[i].ItemId == id)
{
slot = i;
return _voidStorageItems[i];
}
}
return null;
}
//Misc
void UpdateItemLevelAreaBasedScaling()
{
@@ -6469,14 +6251,6 @@ namespace Game.Entities
if (location.HasAnyFlag(ItemSearchLocation.Bank))
{
for (byte i = InventorySlots.BankItemStart; i < InventorySlots.BankItemEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
if (!callback(item))
return false;
}
for (byte i = InventorySlots.BankBagStart; i < InventorySlots.BankBagEnd; ++i)
{
Bag bag = GetBagByPos(i);
@@ -6509,14 +6283,6 @@ namespace Game.Entities
}
}
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ReagentEnd; ++i)
{
Item item = GetItemByPos(InventorySlots.Bag0, i);
if (item != null)
if (!callback(item))
return false;
}
}
return true;
+23 -1
View File
@@ -365,9 +365,20 @@ namespace Game.Entities
&& ((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) != TraitCombatConfigFlags.None;
});
if (specTraitConfigIndex >= 0)
SetActiveCombatTraitConfigID(m_activePlayerData.TraitConfigs[specTraitConfigIndex].ID);
{
TraitConfig activeTraitConfig = m_activePlayerData.TraitConfigs[specTraitConfigIndex];
SetActiveCombatTraitConfigID(activeTraitConfig.ID);
int activeSubTree = activeTraitConfig.SubTrees.FindIndexIf(subTree => subTree.Active != 0);
if (activeSubTree >= 0)
SetCurrentCombatTraitConfigSubTreeID(activeTraitConfig.SubTrees[activeSubTree].TraitSubTreeID);
else
SetCurrentCombatTraitConfigSubTreeID(0);
}
else
{
SetActiveCombatTraitConfigID(0);
SetCurrentCombatTraitConfigSubTreeID(0);
}
foreach (var talentInfo in CliDB.TalentStorage.Values)
{
@@ -1136,6 +1147,17 @@ namespace Game.Entities
}
}
if (applyTraits)
{
int activeSubTree = editedConfig.SubTrees.FindIndexIf(subTree => subTree.Active != 0);
if (activeSubTree >= 0)
SetCurrentCombatTraitConfigSubTreeID(editedConfig.SubTrees[activeSubTree].TraitSubTreeID);
else
SetCurrentCombatTraitConfigSubTreeID(0);
Item.UpdateItemSetAuras(this, false);
}
m_traitConfigStates[editedConfigId] = PlayerSpellState.Changed;
}
+3 -18
View File
@@ -143,9 +143,6 @@ namespace Game.Entities
_cinematicMgr.Dispose();
for (byte i = 0; i < SharedConst.VoidStorageMaxSlot; ++i)
_voidStorageItems[i] = null;
ClearResurrectRequestData();
WorldMgr.DecreasePlayerCount();
@@ -599,21 +596,8 @@ namespace Game.Entities
if (target == this)
{
for (byte i = EquipmentSlot.Start; i < InventorySlots.BankBagEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].DestroyForPlayer(target);
}
for (byte i = InventorySlots.ReagentStart; i < InventorySlots.ChildEquipmentEnd; ++i)
{
if (m_items[i] == null)
continue;
m_items[i].DestroyForPlayer(target);
}
foreach (Item item in m_items)
item?.DestroyForPlayer(target);
}
}
public override void CleanupsBeforeDelete(bool finalCleanup = true)
@@ -7697,6 +7681,7 @@ namespace Game.Entities
}
void SetActiveCombatTraitConfigID(int traitConfigId) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ActiveCombatTraitConfigID), (uint)traitConfigId); }
void SetCurrentCombatTraitConfigSubTreeID(int traitSubTreeId) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.CurrentCombatTraitConfigSubTreeID), traitSubTreeId); }
void InitPrimaryProfessions()
{
+2
View File
@@ -458,6 +458,8 @@ namespace Game.Entities
public ObjectGuid castId;
public SpellInfo Spell;
public SpellCastVisual SpellVisual;
public uint StartTimeMs;
public uint Duration;
public uint damage;
public uint originalDamage;
public SpellSchoolMask schoolMask;
+8 -1
View File
@@ -2458,7 +2458,7 @@ namespace Game.Entities
{
SetAnimTier setAnimTier = new();
setAnimTier.Unit = GetGUID();
setAnimTier.Tier = (int)animTier;
setAnimTier.Tier = (byte)animTier;
SendMessageToSet(setAnimTier, true);
}
}
@@ -2486,6 +2486,13 @@ namespace Game.Entities
RemoveDynamicUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects), index);
}
public void SetChannelSpellData(uint startTimeMs, uint durationMs)
{
UnitChannel channelData = m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelData);
SetUpdateFieldValue(ref channelData.StartTimeMs, startTimeMs);
SetUpdateFieldValue(ref channelData.Duration, durationMs);
}
public sbyte GetSpellEmpowerStage() { return m_unitData.SpellEmpowerStage; }
public void SetSpellEmpowerStage(sbyte stage) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SpellEmpowerStage), stage); }
+11 -24
View File
@@ -2722,11 +2722,11 @@ namespace Game
// 0 1 2 3 4 5
SQLResult result = DB.World.Query("SELECT Entry, DifficultyID, LevelScalingDeltaMin, LevelScalingDeltaMax, ContentTuningID, HealthScalingExpansion, " +
//6 7 8 9 10 11 12
"HealthModifier, ManaModifier, ArmorModifier, DamageModifier, CreatureDifficultyID, TypeFlags, TypeFlags2, " +
//13 14 15 16 17
// 6 7 8 9 10 11 12 13
"HealthModifier, ManaModifier, ArmorModifier, DamageModifier, CreatureDifficultyID, TypeFlags, TypeFlags2, TypeFlags3, " +
// 14 15 16 17 18
"LootID, PickPocketLootID, SkinLootID, GoldMin, GoldMax," +
//18 19 20 21 22 23 24 25
// 19 20 21 22 23 24 25 26
"StaticFlags1, StaticFlags2, StaticFlags3, StaticFlags4, StaticFlags5, StaticFlags6, StaticFlags7, StaticFlags8 " +
"FROM creature_template_difficulty ORDER BY Entry");
if (result.IsEmpty())
@@ -2760,12 +2760,13 @@ namespace Game
creatureDifficulty.CreatureDifficultyID = result.Read<int>(10);
creatureDifficulty.TypeFlags = (CreatureTypeFlags)result.Read<uint>(11);
creatureDifficulty.TypeFlags2 = result.Read<uint>(12);
creatureDifficulty.LootID = result.Read<uint>(13);
creatureDifficulty.PickPocketLootID = result.Read<uint>(14);
creatureDifficulty.SkinLootID = result.Read<uint>(15);
creatureDifficulty.GoldMin = result.Read<uint>(16);
creatureDifficulty.GoldMax = result.Read<uint>(17);
creatureDifficulty.StaticFlags = new(result.Read<uint>(18), result.Read<uint>(19), result.Read<uint>(20), result.Read<uint>(21), result.Read<uint>(22), result.Read<uint>(23), result.Read<uint>(24), result.Read<uint>(25));
creatureDifficulty.TypeFlags3 = result.Read<uint>(13);
creatureDifficulty.LootID = result.Read<uint>(14);
creatureDifficulty.PickPocketLootID = result.Read<uint>(15);
creatureDifficulty.SkinLootID = result.Read<uint>(16);
creatureDifficulty.GoldMin = result.Read<uint>(17);
creatureDifficulty.GoldMax = result.Read<uint>(18);
creatureDifficulty.StaticFlags = new(result.Read<uint>(19), result.Read<uint>(20), result.Read<uint>(21), result.Read<uint>(22), result.Read<uint>(23), result.Read<uint>(24), result.Read<uint>(25), result.Read<uint>(26));
// TODO: Check if this still applies
creatureDifficulty.DamageModifier *= Creature.GetDamageMod(template.Classification);
@@ -10997,10 +10998,6 @@ namespace Game
if (!result.IsEmpty())
Global.GuildMgr.SetNextGuildId(result.Read<uint>(0) + 1);
result = DB.Characters.Query("SELECT MAX(itemId) from character_void_storage");
if (!result.IsEmpty())
_voidItemId = result.Read<ulong>(0) + 1;
result = DB.World.Query("SELECT MAX(guid) FROM creature");
if (!result.IsEmpty())
_creatureSpawnId = result.Read<ulong>(0) + 1;
@@ -11036,15 +11033,6 @@ namespace Game
}
return _mailId++;
}
public ulong GenerateVoidStorageItemId()
{
if (_voidItemId >= 0xFFFFFFFFFFFFFFFE)
{
Log.outError(LogFilter.Misc, "_voidItemId overflow!! Can't continue, shutting down server. ");
Global.WorldMgr.StopNow(ShutdownExitCode.Error);
}
return _voidItemId++;
}
public ulong GenerateCreatureSpawnId()
{
if (_creatureSpawnId >= 0xFFFFFFFFFFFFFFFE)
@@ -11789,7 +11777,6 @@ namespace Game
uint _hiPetNumber;
ulong _creatureSpawnId;
ulong _gameObjectSpawnId;
ulong _voidItemId;
uint[] _playerXPperLevel;
Dictionary<uint, uint> _baseXPTable = new();
#endregion
+6 -12
View File
@@ -520,7 +520,7 @@ namespace Game.Guilds
SQLTransaction trans = new SQLTransaction();
// Remove money from bank
ulong tabCost = GetGuildBankTabPrice(tabId) * MoneyConstants.Gold;
ulong tabCost = GetGuildBankTabPrice(tabId);
if (tabCost != 0 && !_ModifyBankMoney(trans, tabCost, false)) // Should not happen, this is checked by client
return;
@@ -2538,17 +2538,11 @@ namespace Game.Guilds
ulong GetGuildBankTabPrice(byte tabId)
{
// these prices are in gold units, not copper
switch (tabId)
{
case 0: return 100;
case 1: return 250;
case 2: return 500;
case 3: return 1000;
case 4: return 2500;
case 5: return 5000;
default: return 0;
}
var bankTab = CliDB.BankTabStorage.FirstOrDefault(bankTab => bankTab.Value.BankType == (int)BankType.Guild && bankTab.Value.OrderIndex == tabId).Value;
if (bankTab != null)
return bankTab.Cost;
return 0;
}
public static void SendCommandResult(WorldSession session, GuildCommandType type, GuildCommandError errCode, string param = "")
@@ -90,7 +90,6 @@ namespace Game
features.BpayStoreAvailable = false;
features.BpayStoreDisabledByParentalControls = false;
features.CharUndeleteEnabled = WorldConfig.GetBoolValue(WorldCfg.FeatureSystemCharacterUndeleteEnabled);
features.BpayStoreEnabled = WorldConfig.GetBoolValue(WorldCfg.FeatureSystemBpayStoreEnabled);
features.MaxCharactersOnThisRealm = WorldConfig.GetIntValue(WorldCfg.CharactersPerRealm);
features.MinimumExpansionLevel = (int)Expansion.Classic;
features.MaximumExpansionLevel = WorldConfig.GetIntValue(WorldCfg.Expansion);
+99 -125
View File
@@ -7,6 +7,7 @@ using Game.Entities;
using Game.Networking;
using Game.Networking.Packets;
using System.Collections.Generic;
using System.Linq;
namespace Game
{
@@ -127,65 +128,121 @@ namespace Game
}
}
[WorldPacketHandler(ClientOpcodes.BuyBankSlot, Processing = PacketProcessing.Inplace)]
void HandleBuyBankSlot(BuyBankSlot packet)
[WorldPacketHandler(ClientOpcodes.BuyAccountBankTab)]
void HandleBuyBankTab(BuyBankTab buyBankTab)
{
if (!CanUseBank(packet.Guid))
if (!CanUseBank(buyBankTab.Banker))
{
Log.outDebug(LogFilter.Network, "WORLD: HandleBuyBankSlot - {0} not found or you can't interact with him.", packet.Guid.ToString());
Log.outDebug(LogFilter.Network, $"WorldSession::HandleBuyBankTab {_player.GetGUID()} - Banker {buyBankTab.Banker} not found or can't interact with him.");
return;
}
uint slot = GetPlayer().GetBankBagSlotCount();
if (buyBankTab.BankType != BankType.Character)
{
Log.outDebug(LogFilter.Network, $"WorldSession::HandleBuyBankTab {_player.GetGUID()} - Bank type {buyBankTab.BankType} is not supported.");
return;
}
uint itemId = 0;
byte slot = 0;
byte inventorySlot = 0;
switch (buyBankTab.BankType)
{
case BankType.Character:
itemId = 242709;
slot = _player.GetCharacterBankTabCount();
inventorySlot = InventorySlots.BankBagStart;
break;
case BankType.Account:
itemId = 208392;
slot = _player.GetAccountBankTabCount();
inventorySlot = (byte)AccountBankBagSlots.Start;
break;
default:
Log.outDebug(LogFilter.Network, $"WorldSession::HandleBuyBankTab {_player.GetGUID()} - Bank type {buyBankTab.BankType} is not supported.");
return;
}
// next slot
++slot;
BankBagSlotPricesRecord slotEntry = CliDB.BankBagSlotPricesStorage.LookupByKey(slot);
if (slotEntry == null)
var bankTab = CliDB.BankTabStorage.FirstOrDefault(record => record.Value.BankType == (byte)buyBankTab.BankType && record.Value.OrderIndex == slot).Value;
if (bankTab == null)
return;
uint price = slotEntry.Cost;
if (!GetPlayer().HasEnoughMoney(price))
return;
GetPlayer().SetBankBagSlotCount((byte)slot);
GetPlayer().ModifyMoney(-price);
GetPlayer().UpdateCriteria(CriteriaType.BankSlotsPurchased);
}
[WorldPacketHandler(ClientOpcodes.BuyReagentBank)]
void HandleBuyReagentBank(ReagentBank reagentBank)
{
if (!CanUseBank(reagentBank.Banker))
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleBuyReagentBankOpcode - {reagentBank.Banker} not found or you can't interact with him.");
return;
}
if (_player.IsReagentBankUnlocked())
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleBuyReagentBankOpcode - Player ({_player.GetGUID()}, name: {_player.GetName()}) tried to unlock reagent bank a 2nd time.");
return;
}
long price = 100 * MoneyConstants.Gold;
ulong price = bankTab.Cost;
if (!_player.HasEnoughMoney(price))
return;
InventoryResult msg = _player.CanEquipNewItem(inventorySlot, out ushort inventoryPos, itemId, false);
if (msg != InventoryResult.Ok)
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleBuyReagentBankOpcode - Player ({_player.GetGUID()}, name: {_player.GetName()}) without enough gold.");
_player.SendEquipError(msg, null, null, itemId);
return;
}
_player.ModifyMoney(-price);
_player.UnlockReagentBank();
Item bag = _player.EquipNewItem(inventoryPos, itemId, ItemContext.None, true);
if (bag == null)
return;
switch (buyBankTab.BankType)
{
case BankType.Character:
_player.SetCharacterBankTabCount(slot);
break;
case BankType.Account:
_player.SetAccountBankTabCount(slot);
break;
default:
break;
}
[WorldPacketHandler(ClientOpcodes.DepositReagentBank)]
void HandleReagentBankDeposit(ReagentBank reagentBank)
_player.ModifyMoney(-(long)price);
_player.UpdateCriteria(CriteriaType.BankTabPurchased, (ulong)buyBankTab.BankType);
}
[WorldPacketHandler(ClientOpcodes.UpdateAccountBankTabSettings)]
void HandleUpdateBankTabSettings(UpdateBankTabSettings updateBankTabSettings)
{
if (!CanUseBank(reagentBank.Banker))
if (!CanUseBank(updateBankTabSettings.Banker))
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleReagentBankDepositOpcode - {reagentBank.Banker} not found or you can't interact with him.");
Log.outDebug(LogFilter.Network, $"WorldSession::HandleUpdateBankTabSettings {_player.GetGUID()} - Banker {updateBankTabSettings.Banker} not found or can't interact with him.");
return;
}
switch (updateBankTabSettings.BankType)
{
case BankType.Character:
if (updateBankTabSettings.Tab >= _player.m_activePlayerData.CharacterBankTabSettings.Size())
{
Log.outDebug(LogFilter.Network, $"WorldSession::HandleUpdateBankTabSettings {_player.GetGUID()} doesn't have bank tab {updateBankTabSettings.Tab} in bank type {updateBankTabSettings.BankType}.");
return;
}
_player.SetCharacterBankTabSettings(updateBankTabSettings.Tab, updateBankTabSettings.Settings.Name,
updateBankTabSettings.Settings.Icon, updateBankTabSettings.Settings.Description, updateBankTabSettings.Settings.DepositFlags);
break;
case BankType.Account:
if (updateBankTabSettings.Tab >= _player.m_activePlayerData.AccountBankTabSettings.Size())
{
Log.outDebug(LogFilter.Network, $"WorldSession::HandleUpdateBankTabSettings {_player.GetGUID()} doesn't have bank tab {updateBankTabSettings.Tab} in bank type {updateBankTabSettings.BankType}.");
return;
}
_player.SetAccountBankTabSettings(updateBankTabSettings.Tab, updateBankTabSettings.Settings.Name,
updateBankTabSettings.Settings.Icon, updateBankTabSettings.Settings.Description, updateBankTabSettings.Settings.DepositFlags);
break;
default:
Log.outDebug(LogFilter.Network, $"WorldSession::HandleUpdateBankTabSettings {_player.GetGUID()} - Bank type {updateBankTabSettings.BankType} is not supported.");
break;
}
}
[WorldPacketHandler(ClientOpcodes.AutoDepositCharacterBank)]
void HandleAutoDepositCharacterBank(AutoDepositCharacterBank autoDepositCharacterBank)
{
if (!CanUseBank(autoDepositCharacterBank.Banker))
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleAutoDepositCharacterBank - {autoDepositCharacterBank.Banker} not found or you can't interact with him.");
return;
}
@@ -204,13 +261,13 @@ namespace Game
if (msg != InventoryResult.Ok)
{
if (msg != InventoryResult.ReagentBankFull || !anyDeposited)
_player.SendEquipError(msg, item);
_player.SendEquipError(msg, item, null);
break;
}
if (dest.Count == 1 && dest[0].pos == item.GetPos())
{
_player.SendEquipError(InventoryResult.CantSwap, item);
_player.SendEquipError(InventoryResult.CantSwap, item, null);
continue;
}
@@ -219,90 +276,7 @@ namespace Game
_player.BankItem(dest, item, true);
anyDeposited = true;
}
}
[WorldPacketHandler(ClientOpcodes.AutobankReagent)]
void HandleAutoBankReagent(AutoBankReagent autoBankReagent)
{
if (!CanUseBank())
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleAutoBankReagentOpcode - {_player.PlayerTalkClass.GetInteractionData().SourceGuid} not found or you can't interact with him.");
return;
}
if (!_player.IsReagentBankUnlocked())
{
_player.SendEquipError(InventoryResult.ReagentBankLocked);
return;
}
Item item = _player.GetItemByPos(autoBankReagent.PackSlot, autoBankReagent.Slot);
if (item == null)
return;
List<ItemPosCount> dest = new();
InventoryResult msg = _player.CanBankItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item, false, true, true);
if (msg != InventoryResult.Ok)
{
_player.SendEquipError(msg, item);
return;
}
if (dest.Count == 1 && dest[0].pos == item.GetPos())
{
_player.SendEquipError(InventoryResult.CantSwap, item);
return;
}
_player.RemoveItem(autoBankReagent.PackSlot, autoBankReagent.Slot, true);
_player.BankItem(dest, item, true);
}
[WorldPacketHandler(ClientOpcodes.AutostoreBankReagent)]
void HandleAutoStoreBankReagent(AutoStoreBankReagent autoStoreBankReagent)
{
if (!CanUseBank())
{
Log.outDebug(LogFilter.Network, $"WORLD: HandleAutoBankReagentOpcode - {_player.PlayerTalkClass.GetInteractionData().SourceGuid} not found or you can't interact with him.");
return;
}
if (!_player.IsReagentBankUnlocked())
{
_player.SendEquipError(InventoryResult.ReagentBankLocked);
return;
}
Item pItem = _player.GetItemByPos(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot);
if (pItem == null)
return;
if (Player.IsReagentBankPos(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot))
{
List<ItemPosCount> dest = new();
InventoryResult msg = _player.CanStoreItem(ItemConst.NullBag, ItemConst.NullSlot, dest, pItem, false);
if (msg != InventoryResult.Ok)
{
_player.SendEquipError(msg, pItem);
return;
}
_player.RemoveItem(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot, true);
_player.StoreItem(dest, pItem, true);
}
else
{
List<ItemPosCount> dest = new();
InventoryResult msg = _player.CanBankItem(ItemConst.NullBag, ItemConst.NullSlot, dest, pItem, false, true, true);
if (msg != InventoryResult.Ok)
{
_player.SendEquipError(msg, pItem);
return;
}
_player.RemoveItem(autoStoreBankReagent.Slot, autoStoreBankReagent.PackSlot, true);
_player.BankItem(dest, pItem, true);
}
}
public void SendShowBank(ObjectGuid guid, PlayerInteractionType interactionType)
+5 -7
View File
@@ -1144,7 +1144,6 @@ namespace Game
features.CfgRealmRecID = 0;
features.CommercePricePollTimeSeconds = 300;
features.VoiceEnabled = false;
features.BrowserEnabled = false; // Has to be false, otherwise client will crash if "Customer Support" is opened
EuropaTicketConfig europaTicketSystemStatus = new();
europaTicketSystemStatus.ThrottleState.MaxTries = 10;
@@ -1163,7 +1162,6 @@ namespace Game
features.EuropaTicketSystemStatus = europaTicketSystemStatus;
features.CharUndeleteEnabled = WorldConfig.GetBoolValue(WorldCfg.FeatureSystemCharacterUndeleteEnabled);
features.BpayStoreEnabled = WorldConfig.GetBoolValue(WorldCfg.FeatureSystemBpayStoreEnabled);
features.WarModeEnabled = WorldConfig.GetBoolValue(WorldCfg.FeatureSystemWarModeEnabled);
features.IsChatMuted = !CanSpeak();
@@ -2796,10 +2794,6 @@ namespace Game
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.AzeriteEmpowered, stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.SEL_CHAR_VOID_STORAGE);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.VoidStorage, stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.SEL_MAIL);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.Mails, stmt);
@@ -2966,6 +2960,10 @@ namespace Game
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.SEL_PLAYER_DATA_FLAGS_CHARACTER);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.DataFlags, stmt);
stmt = CharacterDatabase.GetPreparedStatement(CharStatements.SEL_CHARACTER_BANK_TAB_SETTINGS);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.BankTabSettings, stmt);
}
public ObjectGuid GetGuid() { return m_guid; }
@@ -3060,7 +3058,6 @@ namespace Game
InstanceLockTimes,
SeasonalQuestStatus,
MonthlyQuestStatus,
VoidStorage,
Currency,
CufProfiles,
CorpseLocation,
@@ -3074,6 +3071,7 @@ namespace Game
TraitConfigs,
DataElements,
DataFlags,
BankTabSettings,
Max
}
-20
View File
@@ -1097,14 +1097,6 @@ namespace Game
SendPacket(new BagCleanupFinished());
}
[WorldPacketHandler(ClientOpcodes.SortReagentBankBags, Processing = PacketProcessing.Inplace)]
void HandleSortReagentBankBags(SortReagentBankBags sortReagentBankBags)
{
// TODO: Implement sorting
// Placeholder to prevent completely locking out bags clientside
SendPacket(new BagCleanupFinished());
}
[WorldPacketHandler(ClientOpcodes.RemoveNewItem, Processing = PacketProcessing.Inplace)]
void HandleRemoveNewItem(RemoveNewItem removeNewItem)
{
@@ -1134,18 +1126,6 @@ namespace Game
_player.RemoveBagSlotFlag(changeBagSlotFlag.BagIndex, changeBagSlotFlag.FlagToChange);
}
[WorldPacketHandler(ClientOpcodes.ChangeBankBagSlotFlag, Processing = PacketProcessing.Inplace)]
void HandleChangeBankBagSlotFlag(ChangeBankBagSlotFlag changeBankBagSlotFlag)
{
if (changeBankBagSlotFlag.BagIndex >= _player.m_activePlayerData.BankBagSlotFlags.GetSize())
return;
if (changeBankBagSlotFlag.On)
_player.SetBankBagSlotFlag(changeBankBagSlotFlag.BagIndex, changeBankBagSlotFlag.FlagToChange);
else
_player.RemoveBankBagSlotFlag(changeBankBagSlotFlag.BagIndex, changeBankBagSlotFlag.FlagToChange);
}
[WorldPacketHandler(ClientOpcodes.SetBackpackAutosortDisabled, Processing = PacketProcessing.Inplace)]
void HandleSetBackpackAutosortDisabled(SetBackpackAutosortDisabled setBackpackAutosortDisabled)
{
+17
View File
@@ -301,7 +301,16 @@ namespace Game
SendTradeStatus(info);
return;
}
if (Player.IsAccountBankPos(item.GetSlot(), item.GetBagSlot()))
{
info.Status = TradeStatus.Failed;
info.BagResult = InventoryResult.CantTradeAccountItem;
SendTradeStatus(info);
return;
}
}
item = his_trade.GetItem((TradeSlots)i);
if (item != null)
{
@@ -312,6 +321,14 @@ namespace Game
return;
}
}
if (Player.IsAccountBankPos(item.GetSlot(), item.GetBagSlot()))
{
info.Status = TradeStatus.Failed;
info.BagResult = InventoryResult.CantTradeAccountItem;
SendTradeStatus(info);
return;
}
}
if (his_trade.IsAccepted())
-230
View File
@@ -1,230 +0,0 @@
// 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 Game.Entities;
using Game.Networking;
using Game.Networking.Packets;
using System.Collections.Generic;
namespace Game
{
public partial class WorldSession
{
public void SendVoidStorageTransferResult(VoidTransferError result)
{
SendPacket(new VoidTransferResult(result));
}
[WorldPacketHandler(ClientOpcodes.UnlockVoidStorage, Processing = PacketProcessing.Inplace)]
void HandleVoidStorageUnlock(UnlockVoidStorage unlockVoidStorage)
{
Creature unit = GetPlayer().GetNPCIfCanInteractWith(unlockVoidStorage.Npc, NPCFlags.VaultKeeper, NPCFlags2.None);
if (unit == null)
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageUnlock - {0} not found or player can't interact with it.", unlockVoidStorage.Npc.ToString());
return;
}
if (GetPlayer().IsVoidStorageUnlocked())
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageUnlock - Player({0}, name: {1}) tried to unlock void storage a 2nd time.", GetPlayer().GetGUID().ToString(), GetPlayer().GetName());
return;
}
GetPlayer().ModifyMoney(-SharedConst.VoidStorageUnlockCost);
GetPlayer().UnlockVoidStorage();
}
[WorldPacketHandler(ClientOpcodes.QueryVoidStorage, Processing = PacketProcessing.Inplace)]
void HandleVoidStorageQuery(QueryVoidStorage queryVoidStorage)
{
Player player = GetPlayer();
Creature unit = player.GetNPCIfCanInteractWith(queryVoidStorage.Npc, NPCFlags.Transmogrifier | NPCFlags.VaultKeeper, NPCFlags2.None);
if (unit == null)
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageQuery - {0} not found or player can't interact with it.", queryVoidStorage.Npc.ToString());
SendPacket(new VoidStorageFailed());
return;
}
if (!GetPlayer().IsVoidStorageUnlocked())
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageQuery - {0} name: {1} queried void storage without unlocking it.", player.GetGUID().ToString(), player.GetName());
SendPacket(new VoidStorageFailed());
return;
}
VoidStorageContents voidStorageContents = new();
for (byte i = 0; i < SharedConst.VoidStorageMaxSlot; ++i)
{
VoidStorageItem item = player.GetVoidStorageItem(i);
if (item == null)
continue;
VoidItem voidItem = new();
voidItem.Guid = ObjectGuid.Create(HighGuid.Item, item.ItemId);
voidItem.Creator = item.CreatorGuid;
voidItem.Slot = i;
voidItem.Item = new ItemInstance(item);
voidStorageContents.Items.Add(voidItem);
}
SendPacket(voidStorageContents);
}
[WorldPacketHandler(ClientOpcodes.VoidStorageTransfer)]
void HandleVoidStorageTransfer(VoidStorageTransfer voidStorageTransfer)
{
Player player = GetPlayer();
Creature unit = player.GetNPCIfCanInteractWith(voidStorageTransfer.Npc, NPCFlags.VaultKeeper, NPCFlags2.None);
if (unit == null)
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageTransfer - {0} not found or player can't interact with it.", voidStorageTransfer.Npc.ToString());
return;
}
if (!player.IsVoidStorageUnlocked())
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageTransfer - Player ({0}, name: {1}) queried void storage without unlocking it.", player.GetGUID().ToString(), player.GetName());
return;
}
if (voidStorageTransfer.Deposits.Length > player.GetNumOfVoidStorageFreeSlots())
{
SendVoidStorageTransferResult(VoidTransferError.Full);
return;
}
if (!voidStorageTransfer.Withdrawals.Empty() && voidStorageTransfer.Withdrawals.Length > _player.GetFreeInventorySlotCount(ItemSearchLocation.Inventory))
{
SendVoidStorageTransferResult(VoidTransferError.InventoryFull);
return;
}
if (!player.HasEnoughMoney((voidStorageTransfer.Deposits.Length * SharedConst.VoidStorageStoreItemCost)))
{
SendVoidStorageTransferResult(VoidTransferError.NotEnoughMoney);
return;
}
VoidStorageTransferChanges voidStorageTransferChanges = new();
byte depositCount = 0;
for (int i = 0; i < voidStorageTransfer.Deposits.Length; ++i)
{
Item item = player.GetItemByGuid(voidStorageTransfer.Deposits[i]);
if (item == null)
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageTransfer - {0} {1} wants to deposit an invalid item ({2}).", player.GetGUID().ToString(), player.GetName(), voidStorageTransfer.Deposits[i].ToString());
continue;
}
VoidStorageItem itemVS = new(Global.ObjectMgr.GenerateVoidStorageItemId(), item.GetEntry(), item.GetCreator(),
item.GetItemRandomBonusListId(), item.GetModifier(ItemModifier.TimewalkerLevel), item.GetModifier(ItemModifier.ArtifactKnowledgeLevel),
item.GetContext(), item.GetBonusListIDs());
VoidItem voidItem;
voidItem.Guid = ObjectGuid.Create(HighGuid.Item, itemVS.ItemId);
voidItem.Creator = item.GetCreator();
voidItem.Item = new ItemInstance(itemVS);
voidItem.Slot = _player.AddVoidStorageItem(itemVS);
voidStorageTransferChanges.AddedItems.Add(voidItem);
player.DestroyItem(item.GetBagSlot(), item.GetSlot(), true);
++depositCount;
}
long cost = depositCount * SharedConst.VoidStorageStoreItemCost;
player.ModifyMoney(-cost);
for (int i = 0; i < voidStorageTransfer.Withdrawals.Length; ++i)
{
byte slot;
VoidStorageItem itemVS = player.GetVoidStorageItem(voidStorageTransfer.Withdrawals[i].GetCounter(), out slot);
if (itemVS == null)
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageTransfer - {0} {1} tried to withdraw an invalid item ({2})", player.GetGUID().ToString(), player.GetName(), voidStorageTransfer.Withdrawals[i].ToString());
continue;
}
List<ItemPosCount> dest = new();
InventoryResult msg = player.CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemVS.ItemEntry, 1);
if (msg != InventoryResult.Ok)
{
SendVoidStorageTransferResult(VoidTransferError.InventoryFull);
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidStorageTransfer - {0} {1} couldn't withdraw {2} because inventory was full.", player.GetGUID().ToString(), player.GetName(), voidStorageTransfer.Withdrawals[i].ToString());
return;
}
Item item = player.StoreNewItem(dest, itemVS.ItemEntry, true, itemVS.RandomBonusListId, null, itemVS.Context, itemVS.BonusListIDs);
if (item != null)
{
item.SetCreator(itemVS.CreatorGuid);
item.SetBinding(true);
GetCollectionMgr().AddItemAppearance(item);
}
voidStorageTransferChanges.RemovedItems.Add(ObjectGuid.Create(HighGuid.Item, itemVS.ItemId));
player.DeleteVoidStorageItem(slot);
}
SendPacket(voidStorageTransferChanges);
SendVoidStorageTransferResult(VoidTransferError.Ok);
}
[WorldPacketHandler(ClientOpcodes.SwapVoidItem, Processing = PacketProcessing.Inplace)]
void HandleVoidSwapItem(SwapVoidItem swapVoidItem)
{
Player player = GetPlayer();
Creature unit = player.GetNPCIfCanInteractWith(swapVoidItem.Npc, NPCFlags.VaultKeeper, NPCFlags2.None);
if (unit == null)
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidSwapItem - {0} not found or player can't interact with it.", swapVoidItem.Npc.ToString());
return;
}
if (!player.IsVoidStorageUnlocked())
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidSwapItem - Player ({0}, name: {1}) queried void storage without unlocking it.", player.GetGUID().ToString(), player.GetName());
return;
}
byte oldSlot;
if (player.GetVoidStorageItem(swapVoidItem.VoidItemGuid.GetCounter(), out oldSlot) == null)
{
Log.outDebug(LogFilter.Network, "WORLD: HandleVoidSwapItem - Player (GUID: {0}, name: {1}) requested swapping an invalid item (slot: {2}, itemid: {3}).", player.GetGUID().ToString(), player.GetName(), swapVoidItem.DstSlot, swapVoidItem.VoidItemGuid.ToString());
return;
}
bool usedDestSlot = player.GetVoidStorageItem((byte)swapVoidItem.DstSlot) != null;
ObjectGuid itemIdDest = ObjectGuid.Empty;
if (usedDestSlot)
itemIdDest = ObjectGuid.Create(HighGuid.Item, player.GetVoidStorageItem((byte)swapVoidItem.DstSlot).ItemId);
if (!player.SwapVoidStorageItem(oldSlot, (byte)swapVoidItem.DstSlot))
{
SendVoidStorageTransferResult(VoidTransferError.InternalError1);
return;
}
VoidItemSwapResponse voidItemSwapResponse = new();
voidItemSwapResponse.VoidItemA = swapVoidItem.VoidItemGuid;
voidItemSwapResponse.VoidItemSlotA = swapVoidItem.DstSlot;
if (usedDestSlot)
{
voidItemSwapResponse.VoidItemB = itemIdDest;
voidItemSwapResponse.VoidItemSlotB = oldSlot;
}
SendPacket(voidItemSwapResponse);
}
}
}
@@ -48,37 +48,6 @@ namespace Game.Networking.Packets
public override void Write() { }
}
class AreaTriggerRePath : ServerPacket
{
public AreaTriggerRePath() : base(ServerOpcodes.AreaTriggerRePath) { }
public override void Write()
{
_worldPacket.WritePackedGuid(TriggerGUID);
_worldPacket.WritePackedGuid(Unused_1100);
_worldPacket.WriteBit(AreaTriggerSpline != null);
_worldPacket.WriteBit(AreaTriggerOrbit != null);
_worldPacket.WriteBit(AreaTriggerMovementScript.HasValue);
_worldPacket.FlushBits();
if (AreaTriggerSpline != null)
AreaTriggerSpline.Write(_worldPacket);
if (AreaTriggerMovementScript.HasValue)
AreaTriggerMovementScript.Value.Write(_worldPacket);
if (AreaTriggerOrbit != null)
AreaTriggerOrbit.Write(_worldPacket);
}
public AreaTriggerSplineInfo AreaTriggerSpline;
public AreaTriggerOrbitInfo AreaTriggerOrbit;
public AreaTriggerMovementScriptInfo? AreaTriggerMovementScript;
public ObjectGuid TriggerGUID;
public ObjectGuid Unused_1100;
}
class AreaTriggerPlaySpellVisual : ServerPacket
{
public ObjectGuid AreaTriggerGUID;
@@ -108,31 +77,4 @@ namespace Game.Networking.Packets
TargetGUID = _worldPacket.ReadPackedGuid();
}
}
//Structs
class AreaTriggerSplineInfo
{
public static void WriteAreaTriggerSpline(WorldPacket data, uint timeToTarget, uint elapsedTimeForMovement, Spline<float> areaTriggerSpline)
{
data.WriteUInt32(timeToTarget);
data.WriteUInt32(elapsedTimeForMovement);
var points = areaTriggerSpline.GetPoints();
data.WriteBits(points.Length, 16);
data.FlushBits();
foreach (Vector3 point in points)
data.WriteVector3(point);
}
public void Write(WorldPacket data)
{
WriteAreaTriggerSpline(data, TimeToTarget, ElapsedTimeForMovement, Points);
}
public uint TimeToTarget;
public uint ElapsedTimeForMovement;
public Spline<float> Points;
}
}
+50 -43
View File
@@ -40,62 +40,30 @@ namespace Game.Networking.Packets
}
}
public class BuyBankSlot : ClientPacket
public class BuyBankTab : ClientPacket
{
public BuyBankSlot(WorldPacket packet) : base(packet) { }
public ObjectGuid Banker;
public BankType BankType;
public BuyBankTab(WorldPacket packet) : base(packet) { }
public override void Read()
{
Guid = _worldPacket.ReadPackedGuid();
Banker = _worldPacket.ReadPackedGuid();
BankType = (BankType)_worldPacket.ReadInt8();
}
}
public ObjectGuid Guid;
}
class AutoBankReagent : ClientPacket
class AutoDepositCharacterBank : ClientPacket
{
public AutoBankReagent(WorldPacket packet) : base(packet) { }
public ObjectGuid Banker;
public override void Read()
{
Inv = new(_worldPacket);
PackSlot = _worldPacket.ReadUInt8();
Slot = _worldPacket.ReadUInt8();
}
public InvUpdate Inv;
public byte Slot;
public byte PackSlot;
}
class AutoStoreBankReagent : ClientPacket
{
public AutoStoreBankReagent(WorldPacket packet) : base(packet) { }
public override void Read()
{
Inv = new(_worldPacket);
Slot = _worldPacket.ReadUInt8();
PackSlot = _worldPacket.ReadUInt8();
}
public InvUpdate Inv;
public byte Slot;
public byte PackSlot;
}
// CMSG_BUY_REAGENT_BANK
// CMSG_REAGENT_BANK_DEPOSIT
class ReagentBank : ClientPacket
{
public ReagentBank(WorldPacket packet) : base(packet) { }
public AutoDepositCharacterBank(WorldPacket packet) : base(packet) { }
public override void Read()
{
Banker = _worldPacket.ReadPackedGuid();
}
public ObjectGuid Banker;
}
class BankerActivate : ClientPacket
@@ -111,4 +79,43 @@ namespace Game.Networking.Packets
InteractionType = (PlayerInteractionType)_worldPacket.ReadInt32();
}
}
class UpdateBankTabSettings : ClientPacket
{
public ObjectGuid Banker;
public BankType BankType;
public byte Tab;
public BankTabSettings Settings;
public UpdateBankTabSettings(WorldPacket packet) : base(packet) { }
public override void Read()
{
Banker = _worldPacket.ReadPackedGuid();
BankType = (BankType)_worldPacket.ReadInt8();
Tab = _worldPacket.ReadUInt8();
Settings.Read(_worldPacket);
}
}
public struct BankTabSettings
{
public string Name;
public string Icon;
public string Description;
public BagSlotFlags DepositFlags;
public void Read(WorldPacket data)
{
data.ResetBitPos();
var nameLength = data.ReadBits<uint>(7);
var iconLength = data.ReadBits<uint>(9);
var descriptionLength = data.ReadBits<uint>(14);
DepositFlags = (BagSlotFlags)data.ReadInt32();
Name = data.ReadString(nameLength);
Icon = data.ReadString(iconLength);
Description = data.ReadString(descriptionLength);
}
}
}
@@ -50,6 +50,8 @@ namespace Game.Networking.Packets
for (int i = 0; i < PvpTalents.Count; ++i)
_worldPacket.WriteUInt16(PvpTalents[i]);
TalentInfo.Write(_worldPacket);
_worldPacket.WriteBit(GuildData.HasValue);
_worldPacket.WriteBit(AzeriteLevel.HasValue);
_worldPacket.FlushBits();
@@ -79,6 +81,7 @@ namespace Game.Networking.Packets
public ushort TodayHK;
public ushort YesterdayHK;
public byte LifetimeMaxRank;
public ClassicTalentInfoUpdate TalentInfo;
public TraitInspectInfo TraitsInfo = new();
}
@@ -657,13 +657,6 @@ namespace Game.Networking.Packets
public override void Read() { }
}
class SortReagentBankBags : ClientPacket
{
public SortReagentBankBags(WorldPacket packet) : base(packet) { }
public override void Read() { }
}
class BagCleanupFinished : ServerPacket
{
public BagCleanupFinished() : base(ServerOpcodes.BagCleanupFinished, ConnectionType.Instance) { }
@@ -1006,24 +999,6 @@ namespace Game.Networking.Packets
}
}
public ItemInstance(VoidStorageItem voidItem)
{
ItemID = voidItem.ItemEntry;
if (voidItem.FixedScalingLevel != 0)
Modifications.Values.Add(new ItemMod(voidItem.FixedScalingLevel, ItemModifier.TimewalkerLevel));
if (voidItem.ArtifactKnowledgeLevel != 0)
Modifications.Values.Add(new ItemMod(voidItem.ArtifactKnowledgeLevel, ItemModifier.ArtifactKnowledgeLevel));
if (!voidItem.BonusListIDs.Empty())
{
ItemBonus = new();
ItemBonus.Context = voidItem.Context;
ItemBonus.BonusListIDs = voidItem.BonusListIDs;
}
}
public ItemInstance(SocketedGem gem)
{
ItemID = gem.ItemId;
@@ -333,9 +333,9 @@ namespace Game.Networking.Packets
if (moveSpline.anim_tier != null)
{
data.WriteUInt32(moveSpline.anim_tier.TierTransitionId);
data.WriteUInt8(moveSpline.anim_tier.AnimTier);
data.WriteInt32(moveSpline.effect_start_time);
data.WriteUInt32(0);
data.WriteUInt8(moveSpline.anim_tier.AnimTier);
}
//if (HasUnknown901)
@@ -1473,9 +1473,9 @@ namespace Game.Networking.Packets
public void Write(WorldPacket data)
{
data.WriteInt32(TierTransitionID);
data.WriteUInt8(AnimTier);
data.WriteUInt32(StartTime);
data.WriteUInt32(EndTime);
data.WriteUInt8(AnimTier);
}
}
+93 -30
View File
@@ -782,6 +782,7 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt8(LeaderFactionGroup);
_worldPacket.WriteInt32((int)PingRestriction);
_worldPacket.WriteInt32(PlayerList.Count);
_worldPacket.WriteBit(ChallengeMode.HasValue);
_worldPacket.WriteBit(LfgInfos.HasValue);
_worldPacket.WriteBit(LootSettings.HasValue);
_worldPacket.WriteBit(DifficultySettings.HasValue);
@@ -796,6 +797,9 @@ namespace Game.Networking.Packets
if (DifficultySettings.HasValue)
DifficultySettings.Value.Write(_worldPacket);
if (ChallengeMode.HasValue)
ChallengeMode.Value.Write(_worldPacket);
if (LfgInfos.HasValue)
LfgInfos.Value.Write(_worldPacket);
}
@@ -815,6 +819,7 @@ namespace Game.Networking.Packets
public List<PartyPlayerInfo> PlayerList = new();
public ChallengeModeData? ChallengeMode;
public PartyLFGInfo? LfgInfos;
public PartyLootSettings? LootSettings;
public PartyDifficultySettings? DifficultySettings;
@@ -1253,8 +1258,50 @@ namespace Game.Networking.Packets
public DungeonScoreSummary DungeonScore = new();
}
public struct LeaverInfo
{
public ObjectGuid BnetAccountGUID;
public float LeaveScore;
public uint SeasonID;
public uint TotalLeaves;
public uint TotalSuccesses;
public int ConsecutiveSuccesses;
public long LastPenaltyTime;
public long LeaverExpirationTime;
public int Unknown_1120;
public bool LeaverStatus;
public void Write(WorldPacket data)
{
data.WritePackedGuid(BnetAccountGUID);
data.WriteFloat(LeaveScore);
data.WriteUInt32(SeasonID);
data.WriteUInt32(TotalLeaves);
data.WriteUInt32(TotalSuccesses);
data.WriteInt32(ConsecutiveSuccesses);
data.WriteInt64(LastPenaltyTime);
data.WriteInt64(LeaverExpirationTime);
data.WriteInt32(Unknown_1120);
data.WriteBits(LeaverStatus, 1);
data.FlushBits();
}
}
struct PartyPlayerInfo
{
public ObjectGuid GUID;
public string Name;
public string VoiceStateID; // same as bgs.protocol.club.v1.MemberVoiceState.id
public LeaverInfo Leaver;
public byte Class;
public byte Subgroup;
public byte Flags;
public byte RolesAssigned;
public byte FactionGroup;
public bool FromSocialQueue;
public bool VoiceChatSilenced;
public bool Connected;
public void Write(WorldPacket data)
{
data.WriteBits(Name.GetByteCount(), 6);
@@ -1262,6 +1309,7 @@ namespace Game.Networking.Packets
data.WriteBit(Connected);
data.WriteBit(VoiceChatSilenced);
data.WriteBit(FromSocialQueue);
Leaver.Write(data);
data.WritePackedGuid(GUID);
data.WriteUInt8(Subgroup);
data.WriteUInt8(Flags);
@@ -1272,22 +1320,21 @@ namespace Game.Networking.Packets
if (!VoiceStateID.IsEmpty())
data.WriteString(VoiceStateID);
}
public ObjectGuid GUID;
public string Name;
public string VoiceStateID; // same as bgs.protocol.club.v1.MemberVoiceState.id
public byte Class;
public byte Subgroup;
public byte Flags;
public byte RolesAssigned;
public byte FactionGroup;
public bool FromSocialQueue;
public bool VoiceChatSilenced;
public bool Connected;
}
struct PartyLFGInfo
{
public uint Slot;
public byte MyFlags;
public uint MyRandomSlot;
public byte MyPartialClear;
public float MyGearDiff;
public byte MyStrangerCount;
public byte MyKickVoteCount;
public byte BootCount;
public bool Aborted;
public bool MyFirstReward;
public void Write(WorldPacket data)
{
data.WriteUInt32(Slot);
@@ -1302,44 +1349,60 @@ namespace Game.Networking.Packets
data.WriteBit(MyFirstReward);
data.FlushBits();
}
public uint Slot;
public byte MyFlags;
public uint MyRandomSlot;
public byte MyPartialClear;
public float MyGearDiff;
public byte MyStrangerCount;
public byte MyKickVoteCount;
public byte BootCount;
public bool Aborted;
public bool MyFirstReward;
}
struct PartyLootSettings
{
public byte Method;
public ObjectGuid LootMaster;
public byte Threshold;
public void Write(WorldPacket data)
{
data.WriteUInt8(Method);
data.WritePackedGuid(LootMaster);
data.WriteUInt8(Threshold);
}
public byte Method;
public ObjectGuid LootMaster;
public byte Threshold;
}
struct PartyDifficultySettings
{
public uint DungeonDifficultyID;
public uint RaidDifficultyID;
public uint LegacyRaidDifficultyID;
public void Write(WorldPacket data)
{
data.WriteUInt32(DungeonDifficultyID);
data.WriteUInt32(RaidDifficultyID);
data.WriteUInt32(LegacyRaidDifficultyID);
}
}
public uint DungeonDifficultyID;
public uint RaidDifficultyID;
public uint LegacyRaidDifficultyID;
struct ChallengeModeData
{
public int Unknown_1120_1;
public int Unknown_1120_2;
public ulong Unknown_1120_3;
public long Unknown_1120_4;
public ObjectGuid KeystoneOwnerGUID;
public ObjectGuid LeaverGUID;
public bool IsActive;
public bool HasRestrictions;
public bool CanVoteAbandon;
public void Write(WorldPacket data)
{
data.WriteInt32(Unknown_1120_1);
data.WriteInt32(Unknown_1120_2);
data.WriteUInt64(Unknown_1120_3);
data.WriteInt64(Unknown_1120_4);
data.WritePackedGuid(KeystoneOwnerGUID);
data.WritePackedGuid(LeaverGUID);
data.WriteBit(IsActive);
data.WriteBit(HasRestrictions);
data.WriteBit(CanVoteAbandon);
data.FlushBits();
}
}
}
@@ -767,7 +767,7 @@ namespace Game.Networking.Packets
public int CreatureDifficultyID;
public int WidgetSetID;
public int WidgetSetUnitConditionID;
public uint[] Flags = new uint[2];
public uint[] Flags = new uint[3];
public uint[] ProxyCreatureID = new uint[SharedConst.MaxCreatureKillCredit];
public StringArray Name = new(SharedConst.MaxCreatureNames);
public StringArray NameAlt = new(SharedConst.MaxCreatureNames);
+11 -21
View File
@@ -29,7 +29,6 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(KioskSessionDurationMinutes);
_worldPacket.WriteInt64(RedeemForBalanceAmount);
_worldPacket.WriteUInt32(BpayStorePurchaseTimeout);
_worldPacket.WriteUInt32(ClubsPresenceDelay);
_worldPacket.WriteUInt32(ClubPresenceUnsubscribeDelay);
@@ -57,60 +56,58 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(VoiceEnabled);
_worldPacket.WriteBit(EuropaTicketSystemStatus.HasValue);
_worldPacket.WriteBit(BpayStoreEnabled);
_worldPacket.WriteBit(BpayStoreAvailable);
_worldPacket.WriteBit(BpayStoreDisabledByParentalControls);
_worldPacket.WriteBit(ItemRestorationButtonEnabled);
_worldPacket.WriteBit(BrowserEnabled);
_worldPacket.WriteBit(SessionAlert.HasValue);
_worldPacket.WriteBit(RAFSystem.Enabled);
_worldPacket.WriteBit(RAFSystem.RecruitingEnabled);
_worldPacket.WriteBit(CharUndeleteEnabled);
_worldPacket.WriteBit(RestrictedAccount);
_worldPacket.WriteBit(CommerceServerEnabled);
_worldPacket.WriteBit(TutorialEnabled);
_worldPacket.WriteBit(VeteranTokenRedeemWillKick);
_worldPacket.WriteBit(WorldTokenRedeemWillKick);
_worldPacket.WriteBit(KioskModeEnabled);
_worldPacket.WriteBit(CompetitiveModeEnabled);
_worldPacket.WriteBit(RedeemForBalanceAvailable);
_worldPacket.WriteBit(WarModeEnabled);
_worldPacket.WriteBit(CommunitiesEnabled);
_worldPacket.WriteBit(BnetGroupsEnabled);
_worldPacket.WriteBit(CharacterCommunitiesEnabled);
_worldPacket.WriteBit(ClubPresenceAllowSubscribeAll);
_worldPacket.WriteBit(VoiceChatParentalDisabled);
_worldPacket.WriteBit(VoiceChatParentalMuted);
_worldPacket.WriteBit(QuestSessionEnabled);
_worldPacket.WriteBit(IsChatMuted);
_worldPacket.WriteBit(ClubFinderEnabled);
_worldPacket.WriteBit(CommunityFinderEnabled);
_worldPacket.WriteBit(BrowserCrashReporterEnabled);
_worldPacket.WriteBit(SpeakForMeAllowed);
_worldPacket.WriteBit(DoesAccountNeedAADCPrompt);
_worldPacket.WriteBit(IsAccountOptedInToAADC);
_worldPacket.WriteBit(LfgRequireAuthenticatorEnabled);
_worldPacket.WriteBit(ScriptsDisallowedForBeta);
_worldPacket.WriteBit(TimerunningEnabled);
_worldPacket.WriteBit(WarGamesEnabled);
_worldPacket.WriteBit(IsPlayerContentTrackingEnabled);
_worldPacket.WriteBit(SellAllJunkEnabled);
_worldPacket.WriteBit(GroupFinderEnabled);
_worldPacket.WriteBit(IsPremadeGroupEnabled);
_worldPacket.WriteBit(false); // unused 10.2.7
_worldPacket.WriteBit(GuildEventsEditsEnabled);
_worldPacket.WriteBit(GuildTradeSkillsEnabled);
_worldPacket.WriteBits(Unknown1027.GetByteCount(), 7);
_worldPacket.WriteBits(Unknown1027.GetByteCount(), 10);
_worldPacket.WriteBit(BNSendWhisperUseV2Services);
_worldPacket.WriteBit(BNSendGameDataUseV2Services);
_worldPacket.WriteBit(IsAccountCurrencyTransferEnabled);
_worldPacket.WriteBit(false); // unused 11.0.7
_worldPacket.WriteBit(false); // unused 11.0.7
_worldPacket.WriteBit(LobbyMatchmakerQueueFromMainlineEnabled);
_worldPacket.WriteBit(CanSendLobbyMatchmakerPartyCustomizations);
_worldPacket.WriteBit(AddonProfilerEnabled);
@@ -139,9 +136,7 @@ namespace Game.Networking.Packets
}
public bool VoiceEnabled;
public bool BrowserEnabled;
public bool BpayStoreAvailable;
public bool BpayStoreEnabled;
public SessionAlertConfig? SessionAlert;
public EuropaTicketConfig? EuropaTicketSystemStatus;
public uint CfgRealmID;
@@ -149,7 +144,6 @@ namespace Game.Networking.Packets
public int CfgRealmRecID;
public uint CommercePricePollTimeSeconds;
public long RedeemForBalanceAmount;
public uint BpayStorePurchaseTimeout;
public uint ClubsPresenceDelay;
public uint ClubPresenceUnsubscribeDelay; // Timer for updating club presence when communities ui frame is hidden
public uint KioskSessionDurationMinutes;
@@ -308,7 +302,6 @@ namespace Game.Networking.Packets
public override void Write()
{
_worldPacket.WriteBit(BpayStoreEnabled);
_worldPacket.WriteBit(BpayStoreAvailable);
_worldPacket.WriteBit(BpayStoreDisabledByParentalControls);
_worldPacket.WriteBit(CharUndeleteEnabled);
@@ -316,8 +309,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(VeteranTokenRedeemWillKick);
_worldPacket.WriteBit(WorldTokenRedeemWillKick);
_worldPacket.WriteBit(ExpansionPreorderInStore);
_worldPacket.WriteBit(KioskModeEnabled);
_worldPacket.WriteBit(CompetitiveModeEnabled);
_worldPacket.WriteBit(BoostEnabled);
_worldPacket.WriteBit(TrialBoostEnabled);
@@ -325,8 +318,8 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(PaidCharacterTransfersBetweenBnetAccountsEnabled);
_worldPacket.WriteBit(LiveRegionCharacterListEnabled);
_worldPacket.WriteBit(LiveRegionCharacterCopyEnabled);
_worldPacket.WriteBit(LiveRegionAccountCopyEnabled);
_worldPacket.WriteBit(LiveRegionKeyBindingsCopyEnabled);
_worldPacket.WriteBit(BrowserCrashReporterEnabled);
_worldPacket.WriteBit(IsEmployeeAccount);
@@ -334,16 +327,16 @@ namespace Game.Networking.Packets
_worldPacket.WriteBit(NameReservationOnly);
_worldPacket.WriteBit(LaunchDurationETA.HasValue);
_worldPacket.WriteBit(TimerunningEnabled);
_worldPacket.WriteBit(ScriptsDisallowedForBeta);
_worldPacket.WriteBit(PlayerIdentityOptionsEnabled);
_worldPacket.WriteBit(AccountExportEnabled);
_worldPacket.WriteBit(AccountLockedPostExport);
_worldPacket.WriteBits(RealmHiddenAlert.GetByteCount() + 1, 11);
_worldPacket.WriteBit(BNSendWhisperUseV2Services);
_worldPacket.WriteBit(BNSendGameDataUseV2Services);
_worldPacket.WriteBit(CharacterSelectListModeRealmless);
_worldPacket.WriteBit(WowTokenLimitedMode);
_worldPacket.WriteBit(false); // unused 11.1.7
@@ -360,7 +353,6 @@ namespace Game.Networking.Packets
_worldPacket.WriteInt64(RedeemForBalanceAmount);
_worldPacket.WriteInt32(MaxCharactersOnThisRealm);
_worldPacket.WriteInt32(LiveRegionCharacterCopySourceRegions.Count);
_worldPacket.WriteUInt32(BpayStorePurchaseTimeout);
_worldPacket.WriteInt32(ActiveBoostType);
_worldPacket.WriteInt32(TrialBoostType);
_worldPacket.WriteInt32(MinimumExpansionLevel);
@@ -395,7 +387,6 @@ namespace Game.Networking.Packets
public bool BpayStoreAvailable; // NYI
public bool BpayStoreDisabledByParentalControls; // NYI
public bool CharUndeleteEnabled;
public bool BpayStoreEnabled; // NYI
public bool CommerceServerEnabled; // NYI
public bool VeteranTokenRedeemWillKick; // NYI
public bool WorldTokenRedeemWillKick; // NYI
@@ -428,7 +419,6 @@ namespace Game.Networking.Packets
public uint CommercePricePollTimeSeconds; // NYI
public long RedeemForBalanceAmount; // NYI
public int MaxCharactersOnThisRealm;
public uint BpayStorePurchaseTimeout; // NYI
public int ActiveBoostType; // NYI
public int TrialBoostType; // NYI
public int MinimumExpansionLevel;
@@ -22,12 +22,16 @@ namespace Game.Networking.Packets
_worldPacket.WriteUInt32(talentGroupInfo.SpecID);
_worldPacket.WriteInt32(talentGroupInfo.TalentIDs.Count);
_worldPacket.WriteInt32(talentGroupInfo.PvPTalents.Count);
_worldPacket.WriteInt32(talentGroupInfo.GlyphIDs.Count);
foreach (var talentID in talentGroupInfo.TalentIDs)
_worldPacket.WriteUInt16(talentID);
foreach (PvPTalent talent in talentGroupInfo.PvPTalents)
talent.Write(_worldPacket);
foreach (uint talent in talentGroupInfo.GlyphIDs)
_worldPacket.WriteUInt16((ushort)talent);
}
}
@@ -38,6 +42,7 @@ namespace Game.Networking.Packets
public uint SpecID;
public List<ushort> TalentIDs = new();
public List<PvPTalent> PvPTalents = new();
public List<uint> GlyphIDs = new();
}
public class TalentInfoUpdate
@@ -183,6 +188,9 @@ namespace Game.Networking.Packets
struct GlyphBinding
{
uint SpellID;
ushort GlyphID;
public GlyphBinding(uint spellId, ushort glyphId)
{
SpellID = spellId;
@@ -194,8 +202,66 @@ namespace Game.Networking.Packets
data.WriteUInt32(SpellID);
data.WriteUInt16(GlyphID);
}
}
uint SpellID;
ushort GlyphID;
public struct ClassicTalentEntry
{
public int TalentID;
public int Rank;
public void Write(WorldPacket data)
{
data.WriteInt32(TalentID);
data.WriteInt32(Rank);
}
}
public class ClassicTalentGroupInfo
{
public byte NumTalents;
public List<ClassicTalentEntry> Talents = new();
public byte NumGlyphs;
public List<ushort> GlyphIDs = new();
public sbyte Role;
public int PrimarySpecialization;
public void Write(WorldPacket data)
{
data.WriteUInt8(NumTalents);
data.WriteInt32(Talents.Count);
data.WriteUInt8(NumGlyphs);
data.WriteInt32(GlyphIDs.Count);
data.WriteInt8(Role);
data.WriteInt32(PrimarySpecialization);
foreach (ClassicTalentEntry talentEntry in Talents)
talentEntry.Write(data);
foreach (ushort id in GlyphIDs)
data.WriteUInt16(id);
}
}
public class ClassicTalentInfoUpdate
{
public int UnspentTalentPoints;
public byte ActiveGroup;
public bool IsPetTalents;
public List<ClassicTalentGroupInfo> Talents = new();
public void Write(WorldPacket data)
{
data.WriteInt32(UnspentTalentPoints);
data.WriteUInt8(ActiveGroup);
data.WriteInt32(Talents.Count);
foreach (ClassicTalentGroupInfo talents in Talents)
talents.Write(data);
data.WriteBit(IsPetTalents);
data.FlushBits();
}
}
}
@@ -121,6 +121,7 @@ namespace Game.Networking.Packets
public int TraitNodeEntryID;
public int Rank;
public int GrantedRanks;
public int BonusRanks;
public TraitEntryPacket() { }
public TraitEntryPacket(TraitEntry ufEntry)
@@ -137,6 +138,7 @@ namespace Game.Networking.Packets
TraitNodeEntryID = data.ReadInt32();
Rank = data.ReadInt32();
GrantedRanks = data.ReadInt32();
BonusRanks = data.ReadInt32();
}
public void Write(WorldPacket data)
@@ -145,6 +147,7 @@ namespace Game.Networking.Packets
data.WriteInt32(TraitNodeEntryID);
data.WriteInt32(Rank);
data.WriteInt32(GrantedRanks);
data.WriteInt32(BonusRanks);
}
}
@@ -1,169 +0,0 @@
// 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 Game.Entities;
using System.Collections.Generic;
namespace Game.Networking.Packets
{
class VoidTransferResult : ServerPacket
{
public VoidTransferResult(VoidTransferError result) : base(ServerOpcodes.VoidTransferResult, ConnectionType.Instance)
{
Result = result;
}
public override void Write()
{
_worldPacket.WriteInt32((int)Result);
}
public VoidTransferError Result;
}
class UnlockVoidStorage : ClientPacket
{
public UnlockVoidStorage(WorldPacket packet) : base(packet) { }
public override void Read()
{
Npc = _worldPacket.ReadPackedGuid();
}
public ObjectGuid Npc;
}
class QueryVoidStorage : ClientPacket
{
public QueryVoidStorage(WorldPacket packet) : base(packet) { }
public override void Read()
{
Npc = _worldPacket.ReadPackedGuid();
}
public ObjectGuid Npc;
}
class VoidStorageFailed : ServerPacket
{
public VoidStorageFailed() : base(ServerOpcodes.VoidStorageFailed, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteUInt8(Reason);
}
public byte Reason = 0;
}
class VoidStorageContents : ServerPacket
{
public VoidStorageContents() : base(ServerOpcodes.VoidStorageContents, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteBits(Items.Count, 8);
_worldPacket.FlushBits();
foreach (VoidItem voidItem in Items)
voidItem.Write(_worldPacket);
}
public List<VoidItem> Items = new();
}
class VoidStorageTransfer : ClientPacket
{
public VoidStorageTransfer(WorldPacket packet) : base(packet) { }
public override void Read()
{
Npc = _worldPacket.ReadPackedGuid();
var DepositCount = _worldPacket.ReadInt32();
var WithdrawalCount = _worldPacket.ReadInt32();
for (uint i = 0; i < DepositCount; ++i)
Deposits[i] = _worldPacket.ReadPackedGuid();
for (uint i = 0; i < WithdrawalCount; ++i)
Withdrawals[i] = _worldPacket.ReadPackedGuid();
}
public ObjectGuid[] Withdrawals = new ObjectGuid[(int)SharedConst.VoidStorageMaxWithdraw];
public ObjectGuid[] Deposits = new ObjectGuid[(int)SharedConst.VoidStorageMaxDeposit];
public ObjectGuid Npc;
}
class VoidStorageTransferChanges : ServerPacket
{
public VoidStorageTransferChanges() : base(ServerOpcodes.VoidStorageTransferChanges, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WriteBits(AddedItems.Count, 4);
_worldPacket.WriteBits(RemovedItems.Count, 4);
_worldPacket.FlushBits();
foreach (VoidItem addedItem in AddedItems)
addedItem.Write(_worldPacket);
foreach (ObjectGuid removedItem in RemovedItems)
_worldPacket.WritePackedGuid(removedItem);
}
public List<ObjectGuid> RemovedItems = new();
public List<VoidItem> AddedItems = new();
}
class SwapVoidItem : ClientPacket
{
public SwapVoidItem(WorldPacket packet) : base(packet) { }
public override void Read()
{
Npc = _worldPacket.ReadPackedGuid();
VoidItemGuid = _worldPacket.ReadPackedGuid();
DstSlot = _worldPacket.ReadUInt32();
}
public ObjectGuid Npc;
public ObjectGuid VoidItemGuid;
public uint DstSlot;
}
class VoidItemSwapResponse : ServerPacket
{
public VoidItemSwapResponse() : base(ServerOpcodes.VoidItemSwapResponse, ConnectionType.Instance) { }
public override void Write()
{
_worldPacket.WritePackedGuid(VoidItemA);
_worldPacket.WriteUInt32(VoidItemSlotA);
_worldPacket.WritePackedGuid(VoidItemB);
_worldPacket.WriteUInt32(VoidItemSlotB);
}
public ObjectGuid VoidItemA;
public ObjectGuid VoidItemB;
public uint VoidItemSlotA;
public uint VoidItemSlotB;
}
struct VoidItem
{
public void Write(WorldPacket data)
{
data .WritePackedGuid(Guid);
data .WritePackedGuid(Creator);
data .WriteUInt32(Slot);
Item.Write(data);
}
public ObjectGuid Guid;
public ObjectGuid Creator;
public uint Slot;
public ItemInstance Item;
}
}
+2
View File
@@ -4471,6 +4471,7 @@ namespace Game.Spells
unitCaster.ClearChannelObjects();
unitCaster.SetChannelSpellId(0);
unitCaster.SetChannelVisual(new SpellCastVisualField());
unitCaster.SetChannelSpellData(0, 0);
unitCaster.SetSpellEmpowerStage(-1);
}
@@ -4550,6 +4551,7 @@ namespace Game.Spells
unitCaster.SetChannelSpellId(m_spellInfo.Id);
unitCaster.SetChannelVisual(m_SpellVisual);
unitCaster.SetChannelSpellData(GameTime.GetGameTimeMS(), duration);
void setImmunitiesAndHealPrediction(ref SpellChannelStartInterruptImmunities? interruptImmunities, ref SpellTargetedHealPrediction? healPrediction)
{
+3 -3
View File
@@ -992,9 +992,9 @@ namespace Game.Spells
if (chargeCategoryEntry == null)
return 0;
uint charges = chargeCategoryEntry.MaxCharges;
charges += (uint)_owner.GetTotalAuraModifierByMiscValue(AuraType.ModMaxCharges, (int)chargeCategoryId);
return (int)charges;
int charges = chargeCategoryEntry.MaxCharges;
charges += _owner.GetTotalAuraModifierByMiscValue(AuraType.ModMaxCharges, (int)chargeCategoryId);
return charges;
}
public int GetChargeRecoveryTime(uint chargeCategoryId)
+4
View File
@@ -4898,6 +4898,10 @@ namespace Game.Spells
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 339 SPELL_EFFECT_UI_ACTION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 340 SPELL_EFFECT_340
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 341 SPELL_EFFECT_LEARN_WARBAND_SCENE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 342 SPELL_EFFECT_342
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 343 SPELL_EFFECT_343
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 344 SPELL_EFFECT_344
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 345 SPELL_EFFECT_ASSIST_ACTION
};
#region Fields
+18 -3
View File
@@ -3716,6 +3716,15 @@ namespace Game.Entities
});
});
// Summon Faol in Tirisfal
ApplySpellFix([202112], spellInfo =>
{
ApplySpellEffectFix(spellInfo, 0, spellEffectInfo =>
{
spellEffectInfo.TargetA = new SpellImplicitTargetInfo(Targets.DestDb);
});
});
//
// VIOLET HOLD SPELLS
//
@@ -4385,7 +4394,7 @@ namespace Game.Entities
});
// Flame Spout
ApplySpellFix([ 114685 ], spellInfo =>
ApplySpellFix([114685], spellInfo =>
{
spellInfo.AttributesEx |= SpellAttr1.NoThreat;
spellInfo.AttributesEx8 |= SpellAttr8.CanAttackImmunePC;
@@ -4692,17 +4701,23 @@ namespace Game.Entities
});
// Keg Smash
ApplySpellFix([ 121253 ], spellInfo =>
ApplySpellFix([121253], spellInfo =>
{
spellInfo._LoadSqrtTargetLimit(5, 0, null, 6, null, null);
});
// Odyn's Fury
ApplySpellFix([ 385060, 385061, 385062 ], spellInfo =>
ApplySpellFix([385060, 385061, 385062], spellInfo =>
{
spellInfo._LoadSqrtTargetLimit(5, 0, 385059, 5, null, null);
});
// Flamestrike
ApplySpellFix([ 2120 ], spellInfo =>
{
spellInfo._LoadSqrtTargetLimit(8, 0, null, 2, null, null);
});
Log.outInfo(LogFilter.ServerLoading, $"Loaded SpellInfo target caps in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
}