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